代码随想录算法训练营第六天(哈希表篇)|Leetcode484四数相加II,Leetcode383赎金信,Leetcode15三数之和,Leetcode18四数之和

Leetcode 484 四数相加II

题目链接: 四数相加II
给定四个长度均为n的数组,从四个数组中分别取一个数,使得四数之和为0,将这四个数组成一个元组。返回最终能够组成的元组的个数。

思路: 由于没有要求对元组进行去重,且四个数组之间相互独立,本题非常适合使用哈希表进行求解。将四个数组分为两组,nums1和nums2一组,nums3和nums4一组,先通过字典,记录从nums1和nums2中分别取元素时,元素和->出现次数的映射;随后再遍历nums3和nums4,从字典中找出对应元素和的出现次数,将其进行累加,即可得到最终结果

具体代码实现

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        count = 0
        mydict = dict()
        for i in range(len(nums1)):
            for j in range(len(nums2)):
                mydict[nums1[i]+nums2[j]] = mydict.get(nums1[i]+nums2[j], 0) + 1

        for i in range(len(nums3)):
            for j in range(len(nums4)):
                count += mydict.get(-nums3[i]-nums4[j], 0)

        return count

时间复杂度: O(n^2)

Leetcode 383 赎金信

题目链接: 赎金信
给定两个字符串ransomNotemagazine,判断ransomNote字符串是否能够通过magazine中的字母组成

思路: 记录ransomNote字符串中字母的出现次数和magazine中字母的出现次数,进行比较即可

具体代码实现

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        # 使用数组作为哈希表求解
        if len(ransomNote) > len(magazine):
            return False
        hasharr = [0] * 26
        for ch in ransomNote:
            hasharr[ord(ch)-ord('a')] -= 1

        for ch in magazine:
            hasharr[ord(ch)-ord('a')] += 1

        for i in hasharr:
            if i < 0:
                return False

        return True
class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        # 使用python计数器类求解
        from collections import Counter
        if Counter(ransomNote) <= Counter(magazine):
            return True
        return False

时间复杂度: O(n)

Leetcode 15 三数之和

题目链接: 三数之和
给定一个数组,从中取三个下标不相同的数,使得这三个数之和为0,并将这三个数保存为一个元组,返回所有这样的元组。

思路: 本题与先前四数之和II的主要不同之处在于: 1. 本题在一个数组中进行操作,而四数之和II在四个独立的数组中进行操作;2. 本题得到的数组需要去重,而四数之和II题目中不需要进行去重。为此,我们需要考虑如何进行去重。此题既可以通过双指针进行求解,在遍历的过程中进行去重;也可以仍然使用哈希表,同样在遍历过程中进行去重

三数之和

具体代码实现

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        # 双指针法
        result = []
        nums = sorted(nums)  # 首先对数组进行排序,方便后续处理时进行去重
        for i in range(len(nums)):
            # 由于数组元素从小到大进行排列,此时最小的数已经大于0,此后的情况一定不满足条件,直接剪枝
            if nums[i] > 0:  
                return result
            
            # 跳过已经处理过的元素
            # 将当前元素与前一个元素进行对比,而不是将当前元素与后一个元素进行对比
            # 如[-1, -1, 2, 3]这种情况,若使用后者进行去重,则会遗漏掉
            if i>0 and nums[i] == nums[i-1]:
                continue

            left, right = i+1, len(nums)-1
            while left<right:
                if nums[i] + nums[left] + nums[right] < 0:  # 小于目标值,移动左指针
                    left += 1
                elif nums[i] + nums[left] + nums[right] > 0:  # 大于目标值,移动右指针
                    right -= 1
                else:
                    result.append([nums[i], nums[left], nums[right]])
                    # 不断去重,跳过重复元素
                    while left<right and nums[left] == nums[left+1]:
                        left += 1
                    while left<right and nums[right] == nums[right-1]:
                        right -= 1
                    left += 1
                    right -= 1

        return result
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        # 哈希表法
        # 在符合条件的三元组(a,b,c)中,b(存储) = 0-(a+c)(遍历)
        nums = sorted(nums)
        result = []

        for i in range(len(nums)):
            if nums[i] > 0:
                return result

            if i>0 and nums[i] == nums[i-1]:
                continue

            # 每处理完一个元素,初始化一个字典
            mydict = dict()
            for j in range(i+1, len(nums)):

                if j>i+2 and nums[j] == nums[j-1] == nums[j-2]:
                    continue

                cur = 0-(nums[i]+nums[j])

                # 当cur在mydict中存在时,nums[j]为c
                if cur in mydict:
                    result.append([nums[i], nums[j], cur])
                    mydict.pop(cur)  # 弹出字典中对应键,避免重复

                else:  # 当cur在mydict中不存在时,nums[j]为b,将其进行记录
                    mydict[nums[j]] = 1

        return result

时间复杂度: O(n^2)

Leetcode 18 四数之和

题目链接: 四数之和
给定一个数组,从中取出下标各不相同的四个数,使得这四个数的和等于目标和target,记录这四个数构成的元组,返回所有这样的元组

思路: 思路与三数之和类似,不同之处在于多一层循环,以及去重部分需要进行调整。

四数之和

具体代码实现

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        # 双指针法
        nums = sorted(nums)
        result = []

        for i in range(len(nums)):
            if i > 0 and nums[i] == nums[i-1]:
                continue

            for j in range(i+1, len(nums)):
                if j > i+1 and nums[j] == nums[j-1]:
                    continue

                left, right = j+1, len(nums) - 1
                while left < right:
                    if nums[i] + nums[j] + nums[left] + nums[right] > target:
                        right -= 1
                    elif nums[i] + nums[j] + nums[left] + nums[right] < target:
                        left += 1
                    else:
                        result.append([nums[i], nums[j], nums[left], nums[right]])
                        while left<right and nums[left] == nums[left+1]:
                            left += 1
                        while left<right and nums[right] == nums[right-1]:
                            right -= 1
                        left += 1
                        right -= 1

        return result

时间复杂度: O(n^3)

posted @ 2025-08-13 15:55  雪痕春风天音九重色  阅读(9)  评论(0)    收藏  举报