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

一、454.四数相加II

题目链接:

LeetCode 454.四数相加II

学习前:

思路:

  1. 首先定义两个HashMap对象record12和record34,对应的key存放两个数组元素的和,value存放计算的和出现的次数

  2. 接着遍历record12,若record存在与之和为0的元素,则计算两个value相乘的结果,并进行累积,作为输出的结果

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

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

学习后:

可以只定义一个HashMap对象,整体遍历两次,将后两个遍历一次性完成,降低时间复杂度

二、383. 赎金信

题目链接:

LeetCode 383. 赎金信

学习前:

思路:

  1. 与"LeetCode242.有效的字母异位词"的思路一致,定义一个长度为26的int数组,每个下表对应每个小写字符,值为小写字符出现的次数
  2. 对于ransom进行自增运算,对于magazine进行自减运算,最后对record进行判断,若所有的值均飞正,则返回true,反之false

时间复杂度:O(n+m)

空间复杂度:O(1)

学习后:

增加了对ransom和magazine长度的判断,一方面进行了优化,一方面更加严谨

三、15. 三数之和

题目链接:

LeetCode 15. 三数之和

学习前:

思路:

学习后:

思路:

  1. 首先对数组按照由小到大进行排序

  2. 3个数分别为nums[i]、nums[left]、nums[right],选定nums[i],对left和right进行移动,使得三数之和为0,并且保证三个数各不相同

    for (int i = 0; i < len - 2; i++) {
        if (nums[i] > 0) break;
        if (i > 0 && nums[i] == nums[i - 1]) continue;
        int left = i + 1;
        int right = len - 1;
        while (left < right) {
            int sum = nums[i] + nums[left] + nums[right];
            if (sum < 0) left++;
             else if (sum > 0) right--;
             else {
                 List<Integer> list = new ArrayList<>();
                 list.add(nums[i]);
                 list.add(nums[left]);
                 list.add(nums[right]);
                 res.add(list);
                 left++;
                 right--;
                 while (left < right && nums[left] == nums[left - 1])
                     left++;
                 while (left < right && nums[right] == nums[right + 1])
                     right--;
             }
        }
    }
    

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

空间复杂度:O(1)

四、18. 四数之和

题目链接:

LeetCode 18. 四数之和

学习前:

思路:

  1. 首先对数组按照由小到大进行排序

  2. 4个数分别为nums[a]、nums[b]、nums[c]、nums[d],依次选定nums[a]、nums[b],对c和d进行移动,使得四数之和为target,并且保证四个数各不相同

    for (int a = 0; a < len - 3; a++) {
        if ( nums[a]>0 && nums[a]>target) break;
        if (a > 0 && nums[a] == nums[a - 1]) continue;
        for(int b = a+1; b < len - 2; b++) {
            if (nums[a]+nums[b]>0 && nums[a]+nums[b]>target) break;
            if (b > a+1 && nums[b] == nums[b - 1]) continue;
            int c = b + 1;
            int d = len - 1;
            while (c < d) {
                long sum = nums[a] + nums[b] + nums[c]+nums[d];
                if (sum < target) c++;
                else if (sum > target) d--;
                else {
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[a]);
                    list.add(nums[b]);
                    list.add(nums[c]);
                    list.add(nums[d]);
                    res.add(list);
                    while (c < d && nums[c] == nums[c + 1]) c++;
                    while (c < d && nums[d] == nums[d - 1]) d--;
                    c++;
                    d--;
                }
            }
        }
    }
  1. 需要注意sum的溢出问题

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

空间复杂度:O(1)

学习后:

加深理解

五、学习总结

  1. 时间:3h
  2. 双指针的应用
posted @   amulet  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示