Suzy找到实习了吗Day 7 | 哈希表结束啦 454. 四数相加 II,383. 赎金信,15. 三数之和,18. 四数之和

454. 四数相加 II(dict hash)

题目

给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

题目分析

这道题关键是不需要去重,只要i,j,k,l在不同的位置都算成合格

solution

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        # 四个数组1、2、3、4
        # 首先遍历前面两个数组1、2记录和以及和出现的次数—>map
        # 再遍历后两个数组3、4,得到和c+d,到map中寻找-c-d是否出现以及次数
        ab=dict()
        for i in nums1:
            for j in nums2:
                sum_ab=i+j
                if sum_ab in ab:#这里需要注意!!!一定要先判断是否在字典中再加计数
                    ab[sum_ab]+=1
                else:
                    ab[sum_ab]=1
        #print(ab)
        count=0
        for i in nums3:
            for j in nums4:
                sum_cd=i+j
                if (-sum_cd) in ab:
                    count+=ab[-sum_cd]
                else:
                    continue
        return count

时间复杂度

从暴力解法的O(n^4)降到了O(n ^2)

383. 赎金信(array hash)

题目

给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false 。

magazine 中的每个字符只能在 ransomNote 中使用一次。

solution

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        # 跟242. 有效的字母异位词类似的解法
        arrayhash=[0]*26
        for i in magazine:
            arrayhash[ord(i)-ord('a')]+=1
        #print(arrayhash)
        for j in ransomNote:
            arrayhash[ord(j)-ord('a')]-=1
        for k in arrayhash:
            if k<0:
                return False
        return True

15. 三数之和

题目

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

错误示范版——但我更深层次地理解了set和dict的值必须是无重复的!!!!!

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        count=0
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                #print(nums)
                sum12=nums[i]+nums[j]
                temp=nums.copy()
                temp.pop(i)
                temp.pop(j-1)
                a=[1]*len(temp)
                b=dict(zip(temp,a))
                print(b,i,j)
                # 不能这么做 因为set是必须无重复的 但是temp应该重复的被删掉了!!!
                # 也不能换成dict,因为dict的key也必须是无重复的!!!!
                if (-sum12) in b:
                    count+=1
        print(count)

solution

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        # 如果有hash做法的话 会存在很多去重的现象
        # 首先对结果进行排序,从小到大
        # 遍历nums固定a,然后用双指针left and right
        nums.sort()
        result=[]
        #print(nums)
        for i in range(len(nums)-2):
            #print(i)
            if(i>=1 and nums[i]==nums[i-1]):continue
            left=i+1#这里没有判断是否能加 会不会超界(修改了i的范围0~(len-3))
            right=len(nums)-1
            if nums[i]>0:
                continue
            while(left<right):
                #print(left,right)
                if (nums[i]+nums[left]+nums[right]>0):
                    right-=1
                elif (nums[i]+nums[left]+nums[right]<0):
                    left+=1
                else:
                    result.append([nums[i],nums[left],nums[right]])
                    # b和c的去重在这里 
                    # print(result)
                    while left<right and nums[left]==nums[left+1]:
                        left+=1 
                        # 跳出这个循环表示此时的left位上的数字于它的下一位不一样
                        # 即0,0,2,跳出的时候left在最后一个0位上
                    while left<right and nums[right]==nums[right-1]:
                        right-=1
                    left+=1 #所以最后还要往前走啊啊啊啊笨蛋!!!!
                    right-=1
        return result

要重新做几遍,特别是去重有很多细节!!!!

18. 四数之和(好难,思路沿用三数之和)

这是看完视频写的,注意剪枝和去重的操作!

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        result=[]
        nums.sort()
        #print(nums)
        for i in range(len(nums)):
            if nums[i]>0 and target>0 and nums[i]>target:continue # 剪枝
            if(i>=1 and nums[i]==nums[i-1]):continue # 去重
            for j in range(i+1,len(nums)):
                if(nums[i]+nums[j]>0 and target>0 and nums[i]+nums[j]>target):continue #剪枝
                if (j>i+1 and nums[j]==nums[j-1]):continue # 去重
                #yeyeye!!!聪明蛋!!!j>=1不对!j只能于前一值是j的取值进行比较,所以必须大于i+1
                left=j+1
                right=len(nums)-1
                print(i,j,left,right)
                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

你可能感兴趣的:(散列表,哈希算法,数据结构)