thảo luận Leetcode mỗi ngày

  • Người tạo chủ đề Người tạo chủ đề _Gia_Cat_Luong_
  • Ngày bắt đầu Ngày bắt đầu
Trạng thái
Không mở để trả lời thêm.
C#:
public class Solution {
    public int LastStoneWeightII(int[] stones) {
        var possibility = new List<int>{ 0 };
        foreach (var t in stones)
        {
            var length = possibility.Count;
            var casePlus = possibility.Select(x => x + t).ToList();
            possibility = possibility.Select(x => Math.Abs(x - t)).Union(casePlus).ToList();
        }

        return possibility.Min();
    }
}

chưa tối ưu lắm, nhờ các thím xem qua chứ mới beat 70% TC
yBBewst.png
Cái này là BF rồi, mà ko bị dính TLE nhỉ, mình python dùng backtrack ko tối ưu gì TLE lòi mắt, nhưng về cơ bản bài này tối ưu thì là m*sum(stones), cách thì cũng phải dùng trick ảo vãi, ko làm trước gặp bài này lúc interview khéo hẹo chắc.
 
Nó là brute force đó thím vì mình sẽ phải duyệt qua tất cả các cặp có khả năng xảy ra (exploring all possibilities) . Bài này mình cũng làm khá lâu rồi nhưng vừa xem lại thì mình làm theo cách Top-down vì thấy nó intuitive hơn (đối với mình). Còn bài Knapsack là bài nhập môn Dynamic Programming đó (chọn hoặc không chọn).

Còn bài này pattern thì viết ra giấy là sẽ ra. Ví dụ : [2,7,4,1,8,1] mình có thì nó sẽ là
(2-7) (4-1) (8-1) or (2-4) (7-1) (8-1) ...=> 5 3 7 => (5 - 3) 7 or (5-7) 3 => Res = 1

Nhìn vào đấy thì sẽ thấy pattern là thêm dấu ( + hoặc -) vào trước số hiện tại trong mảng rồi cộng với current sum rồi check xem giá trị nào nhỏ hơn.
Python:
# Approach 1 : Recursive - top down + memorize
        n = len(stones)
        @lru_cache(None)
        def helper(i, curr):
            if i >= n:
                return abs(curr)
            return min(helper(i + 1, curr - stones[i]),helper(i + 1, curr + stones[i]))
        return helper(0,0)
Dựa vào đâu come up được cái intuition này thế bác? có cái pattern nào cụ thể ko? bài này thấy nhiều người ghi nào 01 Knapsack nhưng bản chất từ đâu để đưa về 01 Knapsack nó lại khác hoàn toàn.
 
Dựa vào đâu come up được cái intuition này thế bác? có cái pattern nào cụ thể ko? bài này thấy nhiều người ghi nào 01 Knapsack nhưng bản chất từ đâu để đưa về 01 Knapsack nó lại khác hoàn toàn.
Nháp ra giấy là sẽ ra (+num1 - num2) (+num3 - num4)…., bản chất là thêm dấu +/- vào trước thôi…

via theNEXTvoz for iPhone
 
Dựa vào đâu come up được cái intuition này thế bác? có cái pattern nào cụ thể ko? bài này thấy nhiều người ghi nào 01 Knapsack nhưng bản chất từ đâu để đưa về 01 Knapsack nó lại khác hoàn toàn.
Cái này trong solution có bác hướng dẫn ấy ông, ý tưởng phân ra 2 bịch đá S1 và S2 mà S1 + S2 = total, đồng thời kết quả cần tìm là S1 - S2 = res, do đó thế trên vào thì res = total - 2 * S2, với mấy cái kia là hằng số thì mình maximize thằng S2 với giá trị cap của S2 là total / 2 cũng là max weight của knapsack luôn.
 
Kiếm đâu ra code của vozlit vậy fèn
dDcJCFN.png
tìm max trong dfs được mà sao phải sort với binary search chi
gq7t32C.png


Python:
class Solution:

    def lastStoneWeightII(self, stones: List[int]) -> int:
        total = sum(stones)
        target = total // 2
       
        memo = {}
        self.largestSum = 0

        def dfs(index, sumSoFar):
            if sumSoFar > target:
                return
           
            if index == len(stones):
                self.largestSum = max(self.largestSum, sumSoFar)
                return
           
            if (index, sumSoFar) in memo:
                return memo[(index, sumSoFar)]

            dfs(index + 1, sumSoFar + stones[index])
            dfs(index + 1, sumSoFar)

            memo[(index, sumSoFar)] = self.largestSum

        dfs(0, 0)

        return total - 2 * self.largestSum
Chưa đủ trình độ ko hiểu được tinh hoa trong này đâu
zFNuZTA.gif

Cách này dùng trong trường hợp n <= 40 và sum lớn, với max num 10^7.
Thay vì backtrack sẽ cho ra kết quả 2^40 thì chuyển về 2^20log(2^20)

via theNEXTvoz for iPhone
 
C#:
public class Solution {
    public int GreatestCommonDivisior(int a, int b)
    {
        int remainder = 0;
        while(b != 0)
        {
            remainder = a % b;
            a = b;
            b = remainder;
        }
        return a;
    }
    
    public ListNode InsertGreatestCommonDivisors(ListNode head) {
        var temp = head;
        while(temp.next != null)
        {
            var newNode = new ListNode()
            {
                val = GreatestCommonDivisior(temp.val, temp.next.val),
                next = temp.next
            };
            temp.next = newNode;
            temp = temp.next.next;
        }
        return head;
    }
}
 
Mã:
class Solution:
    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:
        current = head
        while current and current.next:
            firstVal = current.val
            secondVal = current.next.val
            gcdNode = ListNode(gcd(firstVal, secondVal))  
            gcdNode.next = current.next  
            current.next = gcdNode  
            current = gcdNode.next  
        return head
 
Chưa đủ trình độ ko hiểu được tinh hoa trong này đâu
zFNuZTA.gif

Cách này dùng trong trường hợp n <= 40 và sum lớn, với max num 10^7.
Thay vì backtrack sẽ cho ra kết quả 2^40 thì chuyển về 2^20log(2^20)

via theNEXTvoz for iPhone
backtrack khi có mem thì khác, với dfs(index, curSum), với mỗi tuple (index, curSum) chỉ gọi dfs một lần duy nhất với mem. với index in range(0, n) curSum in range (0, total/2) thì cùng lắm worse case chỉ có O(n * total)

Còn của anh là O(2^(n/2) * n) do đoạn binary search
 
Sửa lần cuối:
backtrack khi có mem thì khác, với dfs(index, curSum), với mỗi tuple (index, curSum) chỉ gọi dfs một lần duy nhất với mem. với index in range(0, n) curSum in range (0, total/2) thì cùng lắm worse case chỉ có O(n * total)

Còn của anh là O(2^(n/2) * n) do đoạn binary search
Thế giờ cho nums <= 10^7 thì fence làm thế nào :doubt: vấn đề ở chỗ là với nums lớn thì fence sẽ ko xài được DP hiểu ko.
Chứ bài kia thì xài DP là ok rồi, vì nums chỉ có khoảng <=100 thì DP sẽ cho ra time complexity là O(n*k)
Vấn đề là fence sẽ ko thể nào giải O(n*k) cho nums <= 10^7 được. Thế nên mới phải cần meet in the middle, như bài này này.
 
Thế giờ cho nums <= 10^7 thì fence làm thế nào :doubt: vấn đề ở chỗ là với nums lớn thì fence sẽ ko xài được DP hiểu ko.
Chứ bài kia thì xài DP là ok rồi, vì nums chỉ có khoảng <=100 thì DP sẽ cho ra time complexity là O(n*k)
Vấn đề là fence sẽ ko thể nào giải O(n*k) cho nums <= 10^7 được. Thế nên mới phải cần meet in the middle, như bài này này.
Đã hiểu
zFNuZTA.png
Cảm ơn thím đã khai sáng
+1 điểm tình bạn (Mốt nhớ phát card nhiều
JEWoIdl.png
)
 
Trạng thái
Không mở để trả lời thêm.

Thống kê chủ đề

Ngày tạo
_Gia_Cat_Luong_,
Người trả lời cuối
Vipluckystar,
Trả lời
17.755
Lượt xem
1.213.926
Quay lại
Lên đầu trang