kSum问题总结

1、2Sum

题目:

方法一:两次迭代

public class TwoSum {

    public static int[] twoSum(int[] nums, int target) {
        int[] indices = {-1,-1};
        for(int i=0; i<nums.length-1; i++ ){
            if(target>=nums[i]){
                for(int k=i+1; k<=nums.length-1; k++){
                    if(nums[k] == (target-nums[i])){
                        indices[0]=i;
                        indices[1]=k;
                        return indices;
                    }
                }

            }
        }
        return indices;

    }
}

方法二:利用HashMap,减少一次迭代

import java.util.HashMap;

public class Two_Sum1 {
    public static int[] twosum(int[] nums, int target){
        int[] result = new int[2];
        if(nums.length < 2) return result;

        HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
        for(int i=0; i<nums.length; i++){
            if(!map.containsKey(target-nums[i])){
                map.put(nums[i],i);
            }else{
                result[0]=map.get(target-nums[i]);
                result[1]=i;
                break;
            }
        }
        return result;
    }
}

2、3Sum

思路分析:数组排序 + twoPointers

public class _3Sum {
    public static List<List<Integer>> threeSum(int[] num){
        Arrays.sort(num);
        List<List<Integer>> res = new LinkedList<>();
        for(int i=0; i<num.length-2; i++){
            if(i==0 || (i>0 && num[i]!= num[i-1])){
                int lo=i+1, hi=num.length-1, sum=0-num[i];
                while(lo<hi){
                    if(num[lo]+num[hi]==sum){
                        res.add(Arrays.asList(num[i],num[lo],num[hi]));
                        while(lo<hi && num[lo] == num[lo+1]) lo++;
                        while(lo<hi && num[hi] == num[hi-1]) hi--;
                        lo++; hi--;
                    }else if(num[lo]+num[hi]<sum) lo++;
                    else hi--;
                }
            }
        }
        return res;
    }
}

3、3Sum Cloest

思路分析:数组排序 + twoPointers

public class _3SumClosest {
    public static int threeSumClosest(int[] nums, int target){
        Arrays.sort(nums);
        int diff = Integer.MAX_VALUE, closest=0;
        for(int i=0;i<nums.length-2;i++){
            int lo=i+1, hi=nums.length-1;
            while(lo<hi){
                int sum = nums[i]+nums[lo]+nums[hi];
                if(sum == target) return target;
                else if(sum > target){
                    if(sum-target<diff){
                        diff = sum - target;
                        closest = sum;
                    }
                    hi--;
                }else{
                    if(target-sum<diff){
                        diff = target - sum;
                        closest = sum;
                    }
                    lo++;
                }
            }
        }
        return closest;
    }
}

4、4Sum

思路分析:数组排序+转化问题为3Sum + 2Sum

public class FourSum {
    public  static List<List<Integer>> fourSum(int[] nums, int target){

        LinkedList<List<Integer>> res = new LinkedList<List<Integer>>();
        if(nums==null || nums.length<4) return res;

        Arrays.sort(nums);
        int len = nums.length;
        int max = nums[len-1];
        if(4*nums[0]>target || 4*max<target) return res;

        for(int i=0; i<len-3; i++){
            int z=nums[i];
            if(i>0 && z==nums[i-1]) continue;
            if(z+3*max<target) continue;
            if(4*z>target) break;
            if(4*z==target) {
                if(i+3<len && nums[i+3]==z) res.add(Arrays.asList(z,z,z,z));
                break;
            }
            threeSum(nums,target-z,i+1,len-1,res,z);
        }
        return res;
    }

    public static void threeSum(int[] nums, int target, int lo, int hi, LinkedList<List<Integer>> fourSumList, int z1){

        if(lo+1>=hi) return;

        int max = nums[hi];
        if(3*nums[lo]>target || 3*max<target) return;

        for(int i=lo; i<hi-1; i++){
            int z=nums[i];
            if(i>lo && z==nums[i-1]) continue;
            if(z+2*max<target) continue;
            if(3*z>target) break;
            if(3*z == target){
                if(i+1<hi && nums[i+2]==z) fourSumList.add(Arrays.asList(z1,z,z,z));
                break;
            }
            twoSum(nums,target-z,i+1,hi,fourSumList,z1,z);
        }
    }

    public static void twoSum(int[] nums, int target, int lo, int hi, LinkedList<List<Integer>> fourSumList, int z1, int z2){
        if(lo>=hi) return;
        if(2*nums[lo]>target || 2*nums[hi]<target) return;

        while(lo<hi){
            int sum = nums[lo]+nums[hi];
            if(sum == target){
                fourSumList.add(Arrays.asList(z1,z2,nums[lo],nums[hi]));

                while(lo<hi && nums[lo]==nums[lo+1]) lo++;
                while(lo<hi && nums[hi]==nums[hi-1]) hi--;
                lo++;hi--;
            }
            if(sum<target) lo++;
            if(sum>target) hi--;
        }
        return;
    }
}

5、kSum

public class KSum {
    public  ArrayList<List<Integer>> kSum(int[] nums, int target, int k, int index){
        ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
        if(nums==null || nums.length<k) return res;
        Arrays.sort(nums);
        int len = nums.length;
        int max = nums[len-1];
        if(k*nums[0]>target || k*max<target) {
            return res;
        }
        if(index >= len) {
            return res;
        }
        if(k==2){
            int i=index, j=len-1;
            while(i<j){
                if(nums[i]+nums[j] == target){
                    res.add(Arrays.asList(nums[i],nums[j]));
                    while(i<j && nums[i]==nums[i+1]) i++;
                    while(i<j && nums[j]==nums[j-1]) j--;
                    i++;j--;
                } else if(nums[i]+nums[j]<target) i++;
                else j--;
            } //while循环结束
        }else{
            for (int i = index; i < len - k + 1; i++) {
                ArrayList<List<Integer>> temp = kSum(nums,target-nums[i],k-1,i+1);
                if(temp!=null && temp.size()!=0){
                    for(List<Integer> t : temp){
                        t.add(0,nums[i]);
                    }
                    res.addAll(temp);
                }
                while(i<len-1 && nums[i] == nums[i+1]){
                    i++;
                }
            }//for循环结束
        }
        return res;
    }
}

时间: 2024-11-07 02:17:39

kSum问题总结的相关文章

[算法]K-SUM problem

一.Two Sum Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please

kSUM

leetcode中有几个求sum的问题,思路基本上一样,在这里一并列出. 这几道题主要思路是在使用双指针解决2SUM的基础上,将kSUM逐步reduce到2SUM. 大致框架如下: 1) sort 2) repeatedly reduce kSUM to k-1SUM, until 2SUM 3) solve 2SUM 那么问题就变成了怎样解决2SUM.这里2SUM描述成: “Given an sorted array of integers, find two numbers such tha

【数组】kSum问题

一.2Sum 思路1: 首先对数组排序.不过由于最后返回两个数字的索引,所以需要事先对数据进行备份.然后采用2个指针l和r,分别从左端和右端向中间运动:当l和r位置的两个数字之和小于目标数字target时,r减1:当l和r位置的两个数字之和大于目标数字target时,l加1.因此只需扫描一遍数组就可以检索出两个数字了.最后再扫描一遍原数组,获取这两个数字的索引. 思路2: 将数组的数组映射到哈希表,key是元素的值,value是该值在数组中的索引.考虑到数组中元素有重复,我们使用STL中的uno

2Sum,3Sum,4Sum,kSum,3Sum Closest系列

1).2sum 1.题意:找出数组中和为target的所有数对 2.思路:排序数组,然后用两个指针i.j,一前一后,计算两个指针所指内容的和与target的关系,如果小于target,i右移,如果大于,j左移,否则为其中一个解 3.时间复杂度:O(nlgn)+O(n) 4.空间:O(1) 5.代码: void twoSum(vector<int>& nums,int numsSize,int target,vector<vector<int>>& two

kSum问题的总结

kSum问题是一类题型,常见的有2Sum,3Sum,4Sum等.这篇博文就来总结一些kSum问题的解法,以及对应的时间复杂度. 1. 2Sum 在一个给定的数组nums中,寻找和为定值target的两个数. [解法1]:把数组排序,然后使用two pointers的方法来求解.时间复杂度分析:排序O(nlogn),两指针遍历O(n),总体O(nlogn). [解法2]:先遍历一遍,把整个数组存入到hash_map中,key是每个数,value是出现的次数.然后再遍历一次,每次取查找hasp_ma

[LeetCode]30. KSum问题总结

[LeetCode]1. 2Sum题目:https://leetcode.com/problems/two-sum/,解答:http://www.cnblogs.com/aprilcheny/p/4823576.html: [LeetCode]2. 3Sum题目:https://leetcode.com/problems/3sum/,解答:http://www.cnblogs.com/aprilcheny/p/4872283.html: [LeetCode]3. 3Sum Closest题目:h

【NOIP2016提高A组五校联考4】ksum

题目 分析 发现,当子段[l,r]被取了出来,那么[l-1,r].[l,r+1]一定也被取了出来. 那么,首先将[1,n]放入大顶堆,每次将堆顶的子段[l,r]取出来,因为它是堆顶,所以一定是最大的子段,输出它,并将[l+1,r]和[l,r-1]放进堆中. 一共就只用做k次就可以了. #include <cmath> #include <iostream> #include <cstdio> #include <cstdlib> #include <c

[poj2104]可持久化线段树入门题(主席树)

解题关键:离线求区间第k小,主席树的经典裸题: 对主席树的理解:主席树维护的是一段序列中某个数字出现的次数,所以需要预先离散化,最好使用vector的erase和unique函数,很方便:如果求整段序列的第k小,我们会想到离散化二分和线段树的做法, 而主席树只是保存了序列的前缀和,排序之后,对序列的前缀分别做线段树,具有差分的性质,因此可以求任意区间的第k小,如果主席树维护索引,只需要求出某个数字在主席树中的位置,即为sort之后v中的索引:若要求第k大,建树时反向排序即可 1 #include

2015 一中培训 day 5

又是一天的爆零!!!!! 原本第一题 很容易做 竟然优化过度 丢了答案 先贴上一题 1693: ksum Time Limit 1000 ms Memory Limit 524288 KBytes Judge Standard Judge Solved 18 Submit 41 Submit Status Description Peter喜欢玩数组.NOIP这天,他从Jason手里得到了大小为n的一个正整数 数组. Peter求出了这个数组的所有子段和,并将这n(n+1)/2个数降序排序,他想