thảo luận Leetcode contest, đường tới Guardian

  • Người tạo chủ đề Người tạo chủ đề freedom.9
  • Ngày bắt đầu Ngày bắt đầu
Trạng thái
Không mở để trả lời thêm.
anh @freedom.9 ơi, em mới stalk profile leetcode của a, khủng vãi. Có cách nào để a kiên trì với mục tiêu của mình thế ạ, anh chia sẻ cho anh em với :D
Về skill thì trong topic này anh đếm cũng hơn chục bạn khủng hơn anh mà, còn em muốn kiên trì thì anh nghĩ có vài điểm như thế này em phải luôn manifest vô trong đầu:
1) Em phải luôn tin là ko có skill nào là ko luyện tập được, ở mọi lĩnh vực đều thế, ko chỉ là Algorithm mà tiếng Anh hay tất cả mọi thứ khác. Để xuất chúng thì cần cộng thêm tài năng + luyện tập, nhưng muốn giỏi thì cần kiên trì luyện tập cái kĩ năng đấy thôi.
2) Bắt đầu bằng đích đến, em đặt mục tiêu qua các giai đoạn học, cố gắng ko từ bỏ hoàn thành nó, anh hay hủy những buổi ăn nhậu ko cần thiết để làm contests lắm. Vì anh biết anh mà ko làm một vài hôm thì anh sẽ bỏ cuộc ngay.
Còn cách học Dsa như thế nào từ lúc beginner thì em có thể inbox anh anh chỉ cho một vài cách học hiệu quả, chỉ cần em kiên trì thì chắc chắn sẽ giỏi hơn anh nhiều. Các bạn trẻ hơn thường có lợi thế hơn mà :boss: Anh học algorithm chỉ để hiểu hơn những dòng code mình viết ra hàng ngày thôi chứ ko dùng để interview gì đâu, lên voz post bài daily chửi vozliz, thi contests các thứ là vui rồi
zFNuZTA.gif


via theNEXTvoz for iPhone
 
Sửa lần cuối:
Q4 ko biết cách xử lý phần trùng buồn vl =((
=(( e stuck hơn 30p cho Q4 vì ban đầu nghĩ ra cách dp gọi f[ i ][diff_sum][diff_count] là số cách chọn từ i số đầu tiên sao cho tổng even - tổng odd = diff_sum và even_count - odd_count == diff_count. Thì kq là f[len(nums)-1][0][0] + f[len(nums)-1][0][1]. Nhưng làm cách này ko tính được số hoán vị.

Sau mới nhận ra là digits chỉ từ 0-9, cũng chả quan tâm thứ tự trong nums như nào, mình chỉ cần số lượng xuất hiện của từng digit thôi.
Thì lúc này e mới ra công thức mới là gọi f[d][diff][n_even][n_odd] là số cách chọn first d digits ([0..d]) sao cho sum_even - sum_odd == diff.
Thì f[d][diff][n_even][n_odd] = sum(f[d-1][diff + d*e - d*(freq[d]-e)][n_even-e][n_odd-freq[d]+e] * n_even_C_e * n_odd_C_(freq[d]-e))
Mã:
class Solution:
    def countBalancedPermutations(self, num: str) -> int:
        digits_freq = [0] * 10
        for c in num:
            digits_freq[ord(c) - ord('0')] += 1
        s = 0
        for i in range(10):
            s += i * digits_freq[i]

        if s & 1:
            return 0

        MOD = 10**9 + 7
        
        @lru_cache(None)
        def c(n, k):
            if k == 0:
                return 1
            if n == k:
                return 1
            else:
                return (c(n-1, k-1) + c(n-1, k)) % MOD

        @lru_cache(None)
        def dp(d, diff, n_even, n_odd):
            if n_even < 0 or n_odd < 0:
                return 0

            if d == -1:
                return 1 if diff == 0 else 0

            res = 0
            for e in range(digits_freq[d] + 1):
                remain_even = n_even-e
                remain_odd = n_odd-(digits_freq[d]-e)
                if remain_even < 0 or remain_odd < 0:
                    continue

                temp = dp(d-1, diff + e*d - (digits_freq[d]-e)*d, remain_even, remain_odd)
                temp = (temp * c(n_even, e) * c(n_odd, digits_freq[d]-e)) % MOD
                res = (res + temp) % MOD
            return res
            
        return dp(9, 0, (len(num) + 1) // 2, len(num) // 2)
 
=(( e stuck hơn 30p cho Q4 vì ban đầu nghĩ ra cách dp gọi f[ i ][diff_sum][diff_count] là số cách chọn từ i số đầu tiên sao cho tổng even - tổng odd = diff_sum và even_count - odd_count == diff_count. Thì kq là f[len(nums)-1][0][0] + f[len(nums)-1][0][1]. Nhưng làm cách này ko tính được số hoán vị.

Sau mới nhận ra là digits chỉ từ 0-9, cũng chả quan tâm thứ tự trong nums như nào, mình chỉ cần số lượng xuất hiện của từng digit thôi.
Thì lúc này e mới ra công thức mới là gọi f[d][diff][n_even][n_odd] là số cách chọn first d digits ([0..d]) sao cho sum_even - sum_odd == diff.
Thì f[d][diff][n_even][n_odd] = sum(f[d-1][diff + d*e - d*(freq[d]-e)][n_even-e][n_odd-freq[d]+e] * n_even_C_e * n_odd_C_(freq[d]-e))
Mã:
class Solution:
    def countBalancedPermutations(self, num: str) -> int:
        digits_freq = [0] * 10
        for c in num:
            digits_freq[ord(c) - ord('0')] += 1
        s = 0
        for i in range(10):
            s += i * digits_freq[i]

        if s & 1:
            return 0

        MOD = 10**9 + 7
        
        @lru_cache(None)
        def c(n, k):
            if k == 0:
                return 1
            if n == k:
                return 1
            else:
                return (c(n-1, k-1) + c(n-1, k)) % MOD

        @lru_cache(None)
        def dp(d, diff, n_even, n_odd):
            if n_even < 0 or n_odd < 0:
                return 0

            if d == -1:
                return 1 if diff == 0 else 0

            res = 0
            for e in range(digits_freq[d] + 1):
                remain_even = n_even-e
                remain_odd = n_odd-(digits_freq[d]-e)
                if remain_even < 0 or remain_odd < 0:
                    continue

                temp = dp(d-1, diff + e*d - (digits_freq[d]-e)*d, remain_even, remain_odd)
                temp = (temp * c(n_even, e) * c(n_odd, digits_freq[d]-e)) % MOD
                res = (res + temp) % MOD
            return res
            
        return dp(9, 0, (len(num) + 1) // 2, len(num) // 2)
Cách bác là xét từng chữ số một, từ 9 về 0 nhỉ, tính số hoán vị thì chỉ nhân thêm số cách đặt một số lượng chữ số đang xét vào 2 mảng chẵn-lẻ thôi. Làm thế này hay thật. Em lại xét từng vị trí i trong xâu gốc, nên ra kết quả vẫn phải nhân/chia một mớ lên.
 
Sửa lần cuối:
=(( e stuck hơn 30p cho Q4 vì ban đầu nghĩ ra cách dp gọi f[ i ][diff_sum][diff_count] là số cách chọn từ i số đầu tiên sao cho tổng even - tổng odd = diff_sum và even_count - odd_count == diff_count. Thì kq là f[len(nums)-1][0][0] + f[len(nums)-1][0][1]. Nhưng làm cách này ko tính được số hoán vị.

Sau mới nhận ra là digits chỉ từ 0-9, cũng chả quan tâm thứ tự trong nums như nào, mình chỉ cần số lượng xuất hiện của từng digit thôi.
Thì lúc này e mới ra công thức mới là gọi f[d][diff][n_even][n_odd] là số cách chọn first d digits ([0..d]) sao cho sum_even - sum_odd == diff.
Thì f[d][diff][n_even][n_odd] = sum(f[d-1][diff + d*e - d*(freq[d]-e)][n_even-e][n_odd-freq[d]+e] * n_even_C_e * n_odd_C_(freq[d]-e))
Mã:
class Solution:
    def countBalancedPermutations(self, num: str) -> int:
        digits_freq = [0] * 10
        for c in num:
            digits_freq[ord(c) - ord('0')] += 1
        s = 0
        for i in range(10):
            s += i * digits_freq[i]

        if s & 1:
            return 0

        MOD = 10**9 + 7
        
        @lru_cache(None)
        def c(n, k):
            if k == 0:
                return 1
            if n == k:
                return 1
            else:
                return (c(n-1, k-1) + c(n-1, k)) % MOD

        @lru_cache(None)
        def dp(d, diff, n_even, n_odd):
            if n_even < 0 or n_odd < 0:
                return 0

            if d == -1:
                return 1 if diff == 0 else 0

            res = 0
            for e in range(digits_freq[d] + 1):
                remain_even = n_even-e
                remain_odd = n_odd-(digits_freq[d]-e)
                if remain_even < 0 or remain_odd < 0:
                    continue

                temp = dp(d-1, diff + e*d - (digits_freq[d]-e)*d, remain_even, remain_odd)
                temp = (temp * c(n_even, e) * c(n_odd, digits_freq[d]-e)) % MOD
                res = (res + temp) % MOD
            return res
            
        return dp(9, 0, (len(num) + 1) // 2, len(num) // 2)
Lúc đầu mình cũng đi DP y như fen, sau mới nhận ra là cách đi DP này ko tính được số trùng.
Sau mình cũng chuyển qua dựa vào cái count của digits như thế này mà vẫn thiếu cases =(( để mai mình nghiên cứu lại xem.
ĐM cái Q2 đề là represents the minimum time in seconds when you can start moving to that room nên phải + thêm 1 vô ở next step :ah: cay thật sự chứ đọc lộn nên làm lâu quá.
Python:
class Solution:
    def countBalancedPermutations(self, num: str) -> int:
        m = len(num)
        MOD = 10**9 + 7
        count = defaultdict(int)
        for i in range(m):
            count[int(num[i])] += 1

        digits = list(set(list(num)))
        n = len(digits)
        oddCounts = m//2 + 1
        evenConts = m//2
            
        @lru_cache(None)
        def dp(i, oddSum, evenSum, diff):
            if i == n:
                if m%2 == 0 and diff == 0 and oddSum == evenSum:
                    return 1

                if m%2 == 1 and abs(diff) == 1 and oddSum == evenSum:
                    return 1

                return 0

            ans = 0
            total = count[int(digits[i])]
            intDigit = int(digits[i])
            for k in range(0, total + 1):
                currentDiff = k - (total - k)
                odds = k
                evens = total - k
                if odds <= oddCounts and evens <= evenConts:
                    ans += dp(i + 1, oddSum + intDigit*k, evenSum + intDigit*(total - k), diff + currentDiff)

            return ans%MOD

        ans = dp(0, 0, 0, 0)
            
        return ans
 
Q3 chỉ modify 1 tí ở Q2 thôi mà fen, mà tụi nó viết đề khó hiểu quá =((
Q3 thì em ko nhìn ra cách làm. Q4 em thấy giống Q3 weekly trước nhỉ. Cũng là đếm cách chia 1 tập đã cho thành 2 tập nhỏ (có thể chia hết, hoặc không), để thoả mãn điều kiện nào đó.
 
hay nhỉ cách này sẽ giảm được 1 chiều (từ [sum_even][sum_odd] -> [diff]), lâu không động vào quên hết trick :D :D
Hồi xưa e học còn nhiều trick lỏ lắm mà lâu không đụng cũng quên hết rồi. :( CP phải cày thường xuyên mới được
Cách bác là xét từng chữ số một, từ 9 về 0 nhỉ, tính số hoán vị thì chỉ nhân thêm số cách đặt một số lượng chữ số đang xét vào 2 mảng chẵn-lẻ thôi. Làm thế này hay thật. Em lại xét từng vị trí i trong xâu gốc, nên ra kết quả vẫn phải nhân/chia một mớ lên.
Mỗi cách có cái hay riêng bác. E vẫn chưa nghĩ ra cách nào dp trên từng vị trí i trong xâu gốc mà tính được số hoán vị =((
Xem tệp đính kèm 2762028
Vẫn ko đủ điểm guardian cay lỏ thế nhỉ :ah: đọc lộn đề q2 làm loay hoay mãi =((
chăm chỉ report cheating thôi bác, nhiều khi lên đc 3-400 ranks thì cũng vừa đủ lên guardian đó :p

1730610021379.png

Contest này bay quá, e đang đặt mục tiêu rating 2500+ để pv FAANG, chắc nhanh nhất thì năm sau mới đạt được, chứ giờ performance hơi phập phùng =((
 
Hồi xưa e học còn nhiều trick lỏ lắm mà lâu không đụng cũng quên hết rồi. :( CP phải cày thường xuyên mới được

Mỗi cách có cái hay riêng bác. E vẫn chưa nghĩ ra cách nào dp trên từng vị trí i trong xâu gốc mà tính được số hoán vị =((

chăm chỉ report cheating thôi bác, nhiều khi lên đc 3-400 ranks thì cũng vừa đủ lên guardian đó :p

Xem tệp đính kèm 2762063
Contest này bay quá, e đang đặt mục tiêu rating 2500+ để pv FAANG, chắc nhanh nhất thì năm sau mới đạt được, chứ giờ performance hơi phập phùng =((
vãi lọ Faang bây h 2k5 mới tự tin cơ à bác?
 
Hồi xưa e học còn nhiều trick lỏ lắm mà lâu không đụng cũng quên hết rồi. :( CP phải cày thường xuyên mới được

Mỗi cách có cái hay riêng bác. E vẫn chưa nghĩ ra cách nào dp trên từng vị trí i trong xâu gốc mà tính được số hoán vị =((

chăm chỉ report cheating thôi bác, nhiều khi lên đc 3-400 ranks thì cũng vừa đủ lên guardian đó :p

Xem tệp đính kèm 2762063
Contest này bay quá, e đang đặt mục tiêu rating 2500+ để pv FAANG, chắc nhanh nhất thì năm sau mới đạt được, chứ giờ performance hơi phập phùng =((
Mới report cả đống cheaters rồi, lên tầm 50 ranks nữa chắc đủ điểm Guardian.
Hơi tiếc chỗ Q2 đọc đề ngu quá tốn đống thời gian =(( lại bị cái Q2 củ chuối này
FAANG mà cần gì tới 2k5 bác, bác pv FAANG ở đâu mà ác thế:ah:
 
Trạng thái
Không mở để trả lời thêm.

Thống kê chủ đề

Ngày tạo
freedom.9,
Người trả lời cuối
freedom.9,
Trả lời
2.480
Lượt xem
130.111
Quay lại
Lên đầu trang