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

454.四数相加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

示例1:
输入:nums1 = [1, 2], nums2 = [-2, -1], nums3 = [-1, 2], nums4 = [0, 2]
输出:2
解释:两个元组如下:
1.(0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
2.(1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0

示例2:
输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
输出:1
class Solution:
    def fourSumCount(self, nums1: int, nums2: int, nums3: int, nums4: int) -> int:
        dict_num1 = {}
        for i in range(len(nums1)):
            for j in range(len(nums2)):
                tmp = nums1[i] + nums2[j]
                if tmp not in dict_num1:
                    dict_num1[tmp] = [[i,j]]
                else:
                    dict_num1[tmp].append([i,j])
        dict_num2 = {}
        for i in range(len(nums3)):
            for j in range(len(nums4)):
                tmp = nums3[i] + nums4[j]
                if tmp not in dict_num2:
                    dict_num2[tmp] = [[i,j]]
                else:
                    dict_num2[tmp].append([i,j])
        res = 0
        for i in dict_num1:
            for j in dict_num2:
                if i + j == 0:
                    li = len(dict_num1[i])
                    lj = len(dict_num2[j])
                    tmp = li * lj
                    res += tmp
        return res

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

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        unordered_map<int,int> map1;
        for(int i = 0; i < nums1.size(); i++){
            for(int j = 0; j < nums2.size(); j++){
                int tmp = nums1[i]+nums2[j];
                map1[tmp]++;
            }
        }
        int res = 0;
        for(int i = 0; i < nums3.size(); i++){
            for(int j = 0; j < nums4.size(); j++){
                int tmp = nums3[i] + nums4[j];
                if(map1.find(0-tmp) != map1.end()){
                    res += map1[0-tmp];
                }
            }
        }
        return res;
    }
};

看了一下解法,因为只需要求计数,所以可以直接count计数,这样可以少循环一次。

383.赎金信

给你两个字符串:ransomNote和magazine ,判断ransomNote能不能由magazine里面的字符构成。
如果可以,返回true ;否则返回false 。
magazine中的每个字符只能在ransomNote中使用一次。

示例1:
输入:ransomNote = "a", magazine = "b"
输出:false

示例2:
输入:ransomNote = "aa", magazine = "ab"
输出:false

示例3:
输入:ransomNote = "aa", magazine = "aab"
输出:true

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        dic = {}
        for i in ransomNote:
            if i not in dic:
                dic[i] = 1
            else:
                dic[i] += 1
        dic_mag = {}
        for j in magazine:
            if j not in dic_mag:
                dic_mag[j] = 1
            else:
                dic_mag[j] += 1
        for k, v in dic.items():
            tmp = dic_mag.get(k)
            if tmp is None or v > tmp:
                return False
        return True

if __name__ == '__main__':
    ransomNote = "aa"
    magazine = "aab"
    tmp = Solution()
    res = tmp.canConstruct(ransomNote,magazine)
    print(res)
class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        int alpha[26] = {0};
        for(char a : magazine){
            alpha[a - 'a']++;
        }
        for(char b: ransomNote){
            alpha[b - 'a']--;
            if(alpha[b - 'a'] < 0){
                return false;
            }
        }
        return true;
    }
};

看了一下随想录,发现python有四种解法, 麻了

重写发现C++的写法很有意思

15.三数之和

给你一个整数数组nums ,判断是否存在三元组[nums[i], nums[j], nums[k]]满足i != j、i != k且
j != k ,同时还满足nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为0且不重复的三元组。
注意:答案中不可以包含重复的三元组。

示例1:
输入:nums = [-1, 0, 1, 2, -1, -4]
输出:[[-1, -1, 2], [-1, 0, 1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是[-1, 0, 1]和[-1, -1, 2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例2:
输入:nums = [0, 1, 1]
输出:[]
解释:唯一可能的三元组和不为0 。

示例3:
输入:nums = [0, 0, 0]
输出:[[0, 0, 0]]

解释:唯一可能的三元组和为0

class Solution:
    def threeSum(self, nums):
        long = len(nums)
        res = []
        nums.sort()
        for i in range(long):
            if i == long - 2:
                break
            left = i + 1
            right = long - 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:
                    tmp = [nums[i], nums[left], nums[right]]
                    tmp.sort()
                    if tmp not in res:
                        res.append(tmp)
                    left += 1
        return res

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

注意,这里是24年4月,上面的python写法已经被规避了,必须要掌握a,b,c 三种去重方法,第一种是对i的去重,是 i > 0 and nums[i] == num[i-1],第二种则是在获取到结果的此刻,判断 b 是否和b+1相等,但是注意,不能让b+1越界,且这是个持续动作,所以,是 right > left and nums[left ]  == nums[left+1] ,c的判断方法和b等同。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(),nums.end());
        int cnt = nums.size();
        for(int i = 0; i < cnt; i++){
            int start = i + 1;
            int end = cnt - 1;
            if(nums[i] > 0){
                return res;
            }
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            while(start < end){
                int sum = nums[i] + nums[start] + nums[end];
                if(sum == 0){
                    vector<int> tmp;
                    tmp.push_back(nums[i]);
                    tmp.push_back(nums[start]);
                    tmp.push_back(nums[end]);
                    res.push_back(tmp);                    
                    //[-2,0,0,2,2]这个示例指引去重
                    while(end > start and nums[end] == nums[end-1]){
                        end--;
                    }
                    while(end > start and nums[start] == nums[start+1]){
                        start++;
                    }
                    start++;
                    end--;                    
                }
                else if(sum > 0){
                    end--;
                }
                else{
                    start++;
                }
            }
        }
        return res;
    }
};

18. 四数之和

给你一个由n个整数组成的数组nums ,和一个目标值target 。请你找出并返回满足下述全部条件且不重复的四元
组[nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c和d互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按任意顺序返回答案 。

示例1:
输入:nums = [1, 0, -1, 0, -2, 2], target = 0
输出:[[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]]

示例2:
输入:nums = [2, 2, 2, 2, 2], target = 8
输出:[[2, 2, 2, 2]]
class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums.sort()
        cnt = len(nums)
        res = []
        for i in range(cnt-2):
            if i > 0 and nums[i] == nums[i-1]:
                continue
            for j in range(i+1,cnt-2):
                if j > i + 1 and nums[j] == nums[j-1]:
                    continue
                k = j + 1
                m = cnt - 1                
                while k < m:
                    sum_ = nums[i] + nums[j] + nums[k] + nums[m]
                    if sum_ == target:
                        tmp = [nums[i], nums[j], nums[k], nums[m]]
                        # if tmp not in res:
                        #     res.append(tmp)
                        res.append(tmp)
                        while m > k and nums[k] == nums[k+1]:
                            k += 1
                        while m > k and nums[m] == nums[m-1]:
                            m -= 1
                        k += 1
                        m -= 1
                    elif sum_ > target:
                        m -= 1
                    else:
                        k += 1
        return res

第四题需要再看看,压力好大啊,这个节奏真的快

这里需要思考一下四层去重

1.第一个数的去重和三数之和一样,a > 0 and nums[a] == nums[a-1];

2.第二个数的去重是基于第一个数,所以和第一个数的条件不同,b=a+1,他需要和前一个数对比,但是前一个数不能是a,所以要往前一格,即 b > a + 1 and nums[b] == nums[b-1];

3.第三和第四个数就和三数之后的道理一样了,在获取到结果的前提下,满足 d > c ,然后 nums[c] 和 nums[c+1]相比,nums[d] 和 nums[d-1]相比,然后c向前,d向后。

4.注释行的代码可以代替a和b的去重。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值