代码随想录算法训练营第七天|leetcode454.四数相加II、leetcode383. 赎金信 、leetcode15. 三数之和、leetcode18.四数之和

1 leetcode454.四数相加II

题目链接:454. 四数相加 II - 力扣(LeetCode)

文章链接:代码随想录

视频链接:学透哈希表,map使用有技巧!LeetCode:454.四数相加II_哔哩哔哩_bilibili

自己的思路:第一反应就是暴力搜索,一层一层for循环来完成,就是会超时

1.1 自己的代码

纯纯暴力搜索

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        count = 0
        for i in nums1:
            for j in nums2:
                for k in nums3:
                    for l in nums4:
                        if i+j+k+l == 0:
                            count +=1
        return count

1.2 哈希表的方法

1.2.1哈希表未调用函数

之前出错的一个地方,如果查询的键未在函数内部,则需要建立一个键以及所对应的值

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        hashmap = dict()
        count = 0
        for i in nums1:
            for j in nums2:
                if i+j in hashmap:
                    hashmap[i+j] +=1
                else :
                    hashmap[i+j] = 1
        for k in nums3:
            for l in nums4:
                num = 0-(k+l)
                if num in hashmap:
                    count += hashmap[num]
        return count
1.2.2 使用get函数

之前会,但是没用过,今儿深切感受到了,其使用方法就是在字典内部看看对应的键的位置,没有就是获得一个键和值,值为0

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        hashmap = dict()
        count = 0
        for i in nums1:
            for j in nums2:
                hashmap[i+j] = hashmap.get(i+j,0)+1
        for k in nums3:
            for l in nums4:
                num = 0-(k+l)
                if num in hashmap:
                    count += hashmap[num]
        return count

1.3 本题小结

  1. 这道题很巧妙的地方就是如何求值,先将两个数组的值进行存储在一个字典中,然后用目标值减去另外两个数组的值得到一个值,然后这个值在字典中查找,这样时间复杂度只有n的平方了
  2. 在一个空字典中加键值对的方法,一种就是直接判断,不在里面就直接num[key] = 1或者就是num[key] = num.get(key,0)+1

2 leetcode 383. 赎金信

题目链接:383. 赎金信 - 力扣(LeetCode)

文章链接:代码随想录

自己的思路:

  1. 字符串总共有26个,所以建立一个可以容纳26个字符串的哈希表,初始值为0
  2. 统计第一个字符串s中每个字母出现的次数,这里计算就是用字符串位置减去第一个字母即'a'的值,计算两个字符串的值在python中转化为对ASCII码计算,函数是ord(),然后就是统计每个字符串出现的次数,对其数值进行相加
  3. 对第二个字符串t中的数据对哈希表进行一个减法的操作
  4. 对字符串中的字符进行循环,如果哈希表的值有小于0的,则证明两个字符串不相等,否则就是相等

2.1 自己的代码

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        recorde = [0]*26
        for i in magazine:
            recorde[ord(i)-ord('a')] +=1
        for j in ransomNote:
            recorde[ord(j)-ord('a')] -=1
        for k in range(26):
            if recorde[k] < 0:
                return False
        return True

2.2 哈希表的方法

看了别人的方法,觉得这道题的代码可以简单一点

2.2.1 数组的方法
class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        recorde = [0]*26
        for i in magazine:
            recorde[ord(i)-ord('a')] +=1
        for j in ransomNote:
            recorde[ord(j)-ord('a')] -=1
            if recorde[ord(j)-ord('a')] < 0:
                return False
        return True
2.2.2 字典的方法

字典的方法也是在随想录里面学习到的,发现这个方法真的很巧妙,就是如果目标键不在我们的字典中或者在字典中值为0,就代表没有

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        recorde = dict()
        for i in magazine:
            recorde[i] = recorde.get(i,0)+1
        for j in ransomNote:
            if j not in recorde or recorde[j] == 0:
                return False
            recorde[j] -=1
        return True

2.3 本题小结

  1. 这道题的基本思想和第一个哈希表的方法很相似,而且做法几乎一样
  2. 使用字典的时候,一定要注意键值对的值小于0会报错

3 leetcode15. 三数之和

题目链接:15. 三数之和 - 力扣(LeetCode)

文章链接:代码随想录

视频链接:梦破碎的地方!| LeetCode:15.三数之和_哔哩哔哩_bilibili

自己的思路:原计划是使用字典来存储,然后算一个值出来,如果这个值在字典里面并且和循环中的值不同,则进行输出,发现做的时候会有重复的

3.1视频后的思路

使用双指针的方法,就是不断去判断,感觉双指针的思路时间就比较久,但是结果还算比较好的,就是要去判断有没有相同的数,如果出现了就要往后面移动一位,这个点没想通开始的时候

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        result = []
        nums.sort()
        for i in range(len(nums)):
            if nums[i]>0:
                return result
            if i>0 and nums[i]==nums[i-1]:
                continue
            left = i+1
            right = len(nums)-1
            while 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]])
                    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

3.2本题小结

  1. 感觉这道题难点就在于去重,还有就是判断有0以后,后面的while语句要有两个条件,分开写也不是不行,就是时间会变长
  2. 主要就是需要去重,返回的是值而不是下标,下标重复无所谓,但是不能让值重复

4 leetcode18.四数之和

题目链接:18. 四数之和 - 力扣(LeetCode)

文章链接:代码随想录

视频链接:难在去重和剪枝!| LeetCode:18. 四数之和_哔哩哔哩_bilibili

自己的思路:这道题才开始真的没思路,因为今天感觉自己很烦躁,一直做不好题,看了里面的讲解以后,说再嵌套一层循环即可

4.1 双指针的思路

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums.sort()
        result = []
        for i in range(len(nums)):
            if nums[i]>target and nums[i]>=0:
                break
            if i>0 and nums[i]==nums[i-1]:
                continue
            for k in range(i+1,len(nums)):
                if nums[i]+nums[k]>target and nums[i]+nums[k]>=0:
                    break
                if k>i+1 and nums[k] == nums[k-1]:
                    continue
                left = k+1
                right = len(nums)-1
                while left<right:
                    sum_ = nums[i]+nums[k]+nums[left]+nums[right]
                    if sum_<target:
                        left +=1
                    elif sum_>target:
                        right -=1
                    else:
                        result.append([nums[i],nums[k],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

4.2 本题小结

  1. 其实这道题真的和三数之和超级超级像,感觉没有任何区别
  2. 就是有一个去重的操作,必须nums>=target的时候,还有就是target>0,因为如果小于0也会出现问题

5 本章小结

  1. 其实这个地方很重要的一点,就是不能陷入整个哈希表里面,因为题目是多源的,就是只要能做就好,不要陷入进去
  2. 在空字典里面添加键值对的方法,就是nums[a]=nums.get(a,0)
posted @ 2024-10-22 12:36  小方呀0524  阅读(5)  评论(0编辑  收藏  举报