首页 > 其他分享 >leetcode-n-sum总结

leetcode-n-sum总结

时间:2023-07-31 21:58:24浏览次数:44  
标签:总结 right target nums int sum leetcode left

总结一下leetcode中遇见的2-sum, 3-sum, 4-sum问题,并扩展到n-sum。

1. 两数之和 - 力扣(LeetCode)

梦开始的地方,不多说。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            int num = nums[i];
            if(map.containsKey(target - num)){
                return new int[]{i, map.get(target - num)};
            }
            else map.put(num, i);
        }
        return null;
    }
}

 

15. 三数之和 - 力扣(LeetCode)

写完两数之和可能觉得三数之和也可以用哈希法,但是貌似哈希法非常麻烦。本题较为简单的思路为三指针法(扩展版的双指针),时间复杂度为O(n^2)。

步骤如下:

1. 首先对数组进行排序,之后可以立刻对算法进行剪枝操作,条件为 if(nums[0] > 0) return res;

2. 给定一个指针i,外层遍历数组元素;

3. 给定两个指针left、right,left = i + 1, right = nums.length - 1,如果nums[i] + nums[left] + nums[right] == 0,则将结果加入到列表中,同时更新left和right(注意去重,防止加入相同的结果),如果 nums[i] + nums[left] + nums[right] > 0,则right--,否则left++;

 4. 返回结果。

 图示如下:

 

class Solution {
    //三指针法(双指针的扩展),时间负责度O(n^2)
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        //先给数组排序
        Arrays.sort(nums);
        //第一层循环
        for(int i = 0; i < nums.length - 2; i++){
            //剪枝
            if(nums[i] > 0) return res;
            //去重
            if(i > 0 && nums[i] == nums[i - 1]) continue;
            int target = 0 - nums[i];
            //二层循环
            int left = i + 1,right = nums.length - 1;
            while(left < right){
                //内层列表要放在这里
                List<Integer> ls = new ArrayList<>();
                int leftVal = nums[left], rightVal = nums[right];
                int sum = leftVal + rightVal;
                if(sum == target){
                    ls.add(nums[left]);
                    ls.add(nums[right]);
                    ls.add(nums[i]);
                    res.add(ls);
                    //left和right要去重,防止加入相同的组合
                    while(left < right && nums[left] == leftVal) left++;
                    while(left < right && nums[right] == rightVal) right--;
                }
                else if(sum < target)left++;
                else right--;
            }
        }
        return res;
    }
}

 

18. 四数之和 - 力扣(LeetCode)

四数之和为三数之和的加强版,采用四指针法(双指针法的加强版),时间复杂度为O(n^3)。

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        //排序
        Arrays.sort(nums);
        for(int i = 0; i < nums.length - 3; i++){
            //一级剪枝
            if(nums[i] > target && nums[i] >= 0) return res;
            //去重
            if(i > 0 && nums[i] == nums[i - 1]) continue;
            for(int j = i + 1; j< nums.length - 2; j++){
                //二级剪枝
                if(nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) break;
                //去重
                if(j > i + 1 && nums[j] == nums[j - 1]) continue;
                int left = j + 1, right = nums.length - 1;
                while(left < right){
                    List<Integer> ls = new ArrayList<>();
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if(sum == target){
                        ls.add(nums[i]);
                        ls.add(nums[j]);
                        ls.add(nums[left]);
                        ls.add(nums[right]);
                        //left去重
                        while(left < right && nums[left] == nums[left + 1]) left++;
                        while(left < right && nums[right] == nums[right - 1]) right--;
                        left++;
                        right--;
                        res.add(ls);
                    }
                    else if(sum < target) left++;
                    else    right--;
                }
            }
        }
        return res;
    }
}

【剪枝条件】

注意到当target为负数的时候,无法通过nums[i]> target来给程序做剪枝操作。举个例子[-5,-4,1,2], target = -9中,不能因为-5比-9大就直接做剪枝操作。这里的剪枝条件是nums[i] > target && nums[i] >= 0或者nums[i] + nums[j] > target && nums[i] + nums[j]  >= 0:

当nums[i] + nums[j] >= 0的时候,由于数组是非递减的,所以nums[i]和nums[j]中至少有一个非负数,nums[j]之后的也一定为非负数,又因为nums[i] + nums[j] > target,所以nums[i]、nums[j]与之后的数字相加的结果也必定大于target,可以直接剪枝。

 

【n-sum】

我们可以通过三数之和和四数之和把问题推广到n-sum上,大概的思路一致。通过多指针法可以把算法的复杂度从O(k ^ n)降低到O(k ^ (n - 1))。都是外层循环➕内层双指针的套路,剪枝操作的条件也大概相似。

标签:总结,right,target,nums,int,sum,leetcode,left
From: https://www.cnblogs.com/xkge/p/17593088.html

相关文章

  • 7月31日总结
    7.31周一今天上午写了pta发现二叉树链表都不会,下午学习了Java关键字static,多态与抽象类。static修饰特点1.被类的所有对象共享(也是判断是否使用静态关键字的条件)2可以通过类名调用(推荐),也可以通过对象名调用。多态同一个对象在不同时刻表现出来的不同形态eg:猫cat=new猫();动......
  • Linux知识点总结—3
    今天主要总结了Linux知识点中的网络编程相关知识点,希望可以帮助大家梳理网络编程中的知识点,那我们直接开始吧!!网络基础1IP地址本质:uint32_t类型的整数,例如:192.168.0.0作用:用于唯一标识一个设备在网络中的位置应用:网络通信中的每一条数据都应该具备源端IP地址和对端IP地址,通过这两个......
  • leetcode集训-2023年7月
    今天我想和大家分享一下我参与LeetcodeSQL题集训一个月来的心得体会。在这段时间里,我真的深入感受到SQL语句和数据库API的魅力,也体验到了数据库世界的各种趣味与挑战。SQL语句的执行顺序主要包含以下几个步骤:FROM:指定要查询的表或视图。WHERE:对FROM子句中的表进行条件过滤,只选择满......
  • LeetCode/课程表IV
    你总共需要上numCourses门课,课程编号依次为0到numCourses-1。你会得到一个数组prerequisite,其中prerequisites[i]=[ai,bi]表示如果你想选bi课程,你必须先选ai课程。有的课会有直接的先修课程,比如如果想上课程1,你必须先上课程0,那么会以[0,1]数对的形式给......
  • 每日总结(补档7月24日)
    今天去了乌尔禾,魔鬼城看了,大世界逛了,我不理解为啥要叫冰雪大世界,下午绕完电影城就回到了乌鲁木齐,明天要去天山看天池,路上看完了大道至简的第七章,现实中的工程往往都是很困难的,需要良好的心态和多方的努力,不要低估任何问题......
  • 法兰装配体相关总结
    法兰装配体相关总结参考文献:HG/T20592~20635-20091bar=0.1Mpa=1kg计算螺栓长度:选用粗牙,螺栓螺母外留长度为:螺距*3+倒角端垫片厚度为3mm常用法兰装配体组合:双法兰装配体:法兰*2垫片*1紧固件*1螺栓长度:螺栓长度=垫片+法兰*2+螺母*1+螺距*3+倒角端roundup5法兰阀......
  • Ubuntu卡机重启快捷键总结
    1、https://blog.51cto.com/u_15953612/6036313 https://blog.csdn.net/qq_28440017/article/details/121762759?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-121762759-blog-130485462.235^v38^pc_relevant_anti_t3&am......
  • 每日总结(补档7月21日)
    今天上了环疆铁路,才算是真正明白了校训中的话,什么是逢山开路,黄沙不再漫天,治理还是很有成效的,看了一个小时审美就疲劳了,真的是看不下去,这小一天的路程差点让我这辈子都不想来沙漠,晚饭就是有些新疆特色的炒饭还挺好吃的,晚上很累,马上就睡着了......
  • C# 获取当前月份天数的三种方法总结(转)
    原文连接方法一: intdays=System.Threading.Thread.CurrentThread.CurrentUICulture.Calendar.GetDaysInMonth(DateTime.Now.Year,DateTime.Now.Month);方法二:DateTimedtNow=DateTime.Today;intdays=dtNow.AddDays(1–dtNow.Day).AddMonths(1).AddDays(-1......
  • 代码随想录-哈希表-c++总结
    哈希表内容整体简单,关键是要有利用map映射的思想,以及巩固一些c++标准库的操作这次三数之和一题没有直接做出来,关键在于如何查重一点比较绕15.三数之和-力扣(LeetCode)利用排序+双指针解决三数之和的思路更加清楚此外,四数之和中,四个数相加会溢出int,应改为 ......