2025/3/1 【双指针】LeetCode18.四数之和 【√】

终于走完双指针这一节了

方法一:双指针

具体为两个for循环(对应第一和第二个数)加left和right指针(找第三和第四个数)

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        res = []
        n = len(nums)
        if n < 4:
            return res
        
        nums.sort()
        for i in range(n-3):
            if target > 0 and nums[i] > target:
                return res
            if i > 0 and nums[i] == nums[i-1]:
                continue
            for j in range(i+1, n-2):
                if target > 0 and nums[i] + nums[j] > target:
                    break
                    # return res #注意!!!:如果这里直接return会导致有的组合没法输出
                    #[-10, -9, -8, -8, -8, -7, -2, 0, 0, 1, 3, 5, 6, 7, 7, 8, 8],target=4
                    # -2和7加起来大于4,直接return了,但后面得[0,0,1,3]是一个解,被跳过了
                if j > i+1 and nums[j] == nums[j-1]:
                    continue
                
                left, right = j+1, n-1
                while left < right:
                    sum = nums[i] + nums[j] + nums[left] + nums[right]
                    if sum > target:
                        right -= 1
                    elif sum < target:
                        left += 1
                    else:
                        res.append([nums[i], nums[j], nums[left], nums[right]])
                        while left < right and nums[right] == nums[right-1]:
                            right -= 1
                        while left < right and nums[left] == nums[left+1]:
                            left += 1

                        right -= 1
                        left += 1
        
        return res  

方法二:依旧是指针法。

我的方法:可以看做四个指针,分为两组的方法。

外圈的两个指针b_l,b_r,分别指代第一和第四个数字。

内圈的两个指针s_l,s_r,分别指代第二和第三个数字。

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        length = len(nums)
        res = []
        if length < 4:
            return res

        nums.sort()
        res = []
        
        for b_l in range(length-3):
            if target > 0 and nums[b_l] > target:
                return res
            if b_l > 0 and nums[b_l] == nums[b_l-1]:
                continue

            b_r = length-1
            while b_l < b_r:
                s_l = b_l + 1
                s_r = b_r - 1
                while s_l < s_r:
                    sum = nums[b_l] + nums[b_r] + nums[s_l] + nums[s_r]
                    if sum > target:
                        s_r -= 1
                    elif sum < target:
                        s_l += 1
                    else:
                        res.append([nums[b_l], nums[s_l], nums[s_r], nums[b_r]])
                        while s_r > s_l and nums[s_r] == nums[s_r-1]:
                            s_r -= 1
                        while s_r > s_l and nums[s_l] == nums[s_l+1]:
                            s_l += 1
                        s_r -= 1
                        s_l += 1
                while b_r > s_l and nums[b_r] == nums[b_r-1]:
                            b_r -= 1
                
                b_r -= 1
        
        return res

 

方法三:使用字典,元组,集合

这个解法需要对字典,元组,集合熟悉,才能灵活运用。

这个方法没有事先对nums排序。把满足条件得四个数字组合为元组形式,用集合避免重复。

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        freq = {}
        for num in nums:
            freq[num] = freq.get(num, 0) + 1
        
        res = set()
        n = len(nums)
        for i in range(n-3):
            for j in range(i+1, n-2):
                for k in range(j+1, n-1):
                    val = target - (nums[i] + nums[j] + nums[k])
                    if val in freq:
                        count = (nums[i] == val) + (nums[j] == val) + (nums[k] == val)
                        if count < freq[val]:
                            res.add(tuple(sorted([nums[i], nums[j], nums[k], val])))
        
        return [list(x) for x in res]

 

posted @ 2025-03-01 17:22  axuu  阅读(5)  评论(0)    收藏  举报