代码随想录算法训练营第七天 | 454.四数相加II、383. 赎金信、15. 三数之和、18. 四数之和

第一题 四数相加II

题目描述:
   给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
思路:
   面对这种题,最简单直观的想法就是穷举出所有符合结果的组合。直接根据要求很容易写出O(n^4)的代码,如果使用哈希表中的hashmap就能有效降低时间复杂度。思路如下,首先需要将问题分解为两部分,一个是a+b,另一部分是0 - (c+d),在前两个数组中用hashmap的key记录a+b的值,value记录次数,接着计算c+d的值,同时设计一个计数值count,如果0 - (c+d)在hashmap之中,count加上hashmap的value。具体代码如下:

from typing import List

class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        hashmap = dict()

        for i in nums1:
            for j in nums2:
                if i+j in hashmap:
                    hashmap[i+j] += 1
                else:
                    hashmap[i+j] = 1
        count = 0

        for i in nums3:
            for j in nums4:
                if 0-(i+j) in hashmap:
                    count += hashmap[0-(i+j)]
        return count

if __name__ == '__main__':
    solution = Solution()
    nums1 = [1,2]
    nums2 = [-2,-1]
    nums3 = [-1,2]
    nums4 = [0,2]
    print(solution.fourSumCount(nums1, nums2, nums3, nums4))


第二题 赎金信

题目描述:
   给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。magazine 中的每个字符只能在 ransomNote 中使用一次。
思路:
   集合包含问题,使用哈希表统计次数,在根据次数去匹配,具体代码如下:

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        hashmap = dict()

        for s in magazine:
            if s in hashmap:
                hashmap[s] += 1
            else:
                hashmap[s] = 1

        strlen = len(ransomNote)

        for i in ransomNote:
            if i in hashmap and hashmap[i] > 0:
                hashmap[i] -= 1
                strlen -= 1

        return strlen == 0

if __name__ == '__main__':
    solution = Solution()
    ransomNote = "a"
    magazine = "b"
    print(solution.canConstruct(ransomNote, magazine))

第三题 三数之和

题目描述:
   
思路:
   这道题本来想用哈希表先记录0-(a+b)的值,然后在进行一次遍历。但是这样操作有一个问题,用哈希表会被误判。例如一个数组[3, 1, -1, 2],哈希表值为[-4, -5, 0, -2, -1, -3],检测到 -1 在哈希表中返回真,再去反向查找a+b,最终返回正确结果,本例子中根本就没有合法的结果。鉴于此,我们改进了算法,首先先排序,接着在判断重复,在使用哈希表。具体代码如下:

from typing import List

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
    	
    	nums.sort()
    	result = list()

    	for i in range(len(nums)):

    		if nums[i] > 0:
    			break

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

    		hashmap = dict()

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

    			if tmp in hashmap:
    				result.append([nums[i], nums[j], tmp ])
    				hashmap.pop(tmp)
    			else:
    				hashmap[nums[j]] = j    	

    	return result 





if __name__ == '__main__':
    solution = Solution()
    nums = [-1,0,1,2,-1,-4]
    print(solution.threeSum(nums))


第四题 四数之和

题目描述:
   给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复)
思路:
   思路和三数之和一致,就是加一个for循环,0改为target。具体代码如下

 
from typing import List

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        hashmap = dict()

        for s in nums:
            if s in hashmap:
                hashmap[s] += 1
            else:
                hashmap[s] = 1

        anser = set()

        for i in range(len(nums)):
            for j in range(i+1, len(nums)):
                for k in range(j+1, len(nums)):
                    val = target - (nums[i] + nums[j] + nums[k])
                    if val in hashmap:
                        count = (nums[i] == val) + (nums[j] == val) + (nums[k] == val)
                        if hashmap[val] > count:
                            anser.add(tuple(sorted([nums[i], nums[j], nums[k], val]))) 

        return [list(x) for x in anser ]

if __name__ == '__main__':
    solution = Solution()
    nums = [1,0,-1,0,-2,2]
    target = 0
    print(solution.fourSum(nums, target))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值