2Sum Ksum解法

2Sum

题目
Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

翻译
给定一个整数数组,找出其中两个数满足相加等于你指定的目标数字。
每个输入只有一个唯一解。相同的元素不能用两次。

解题思路
那么本题呢双重循环的方法在这里就不说了。主要展示一下借助HashMap实现。以及要考虑的问题。
思路还是比较简单的。首先我们把所有元素放到map中。key为元素本身。value为元素在数组中的索引值。放到map中是因为方便查找元素的位置。同时哈希表查找元素的时间复杂度是O(1)级别的。
然后再遍历一边数组。查找map中对应的那个元素。
代码如下

// 1. Two Sum
// https://leetcode.com/problems/two-sum/description/
// 时间复杂度:O(n)
// 空间复杂度:O(n)
public class Solution2 {

public int[] twoSum(int[] nums, int target) {

    HashMap<Integer, Integer> record = new HashMap<Integer, Integer>();
    for(int i = 0 ; i < nums.length ; i ++)
        record.put(nums[i], i);

    for(int i = 0 ; i < nums.length; i ++){

        if(record.containsKey(target - nums[i]))
            if(record.get(target - nums[i]) != i){ //不能是同一个的元素相加等于目标值
                int[] res = {i, record.get(target - nums[i])};
                return res;
            }

    }

    throw new IllegalStateException("the input has no solution");
}

}
题到这里就结束了吗?那么有没有想过这么一种可能。这个数组中假如有两个值都为a的元素。那么我们将数组中的元素放到map中时。后面的那个a就将前面那个a覆盖了。a对应的value值为后面那个a的索引。如图:
在这里插入图片描述
如果此题的目标值刚好是2a。就是这两个a相加呢?其实这种情况也没有关系。想想当我们第二次遍历数组时。首先肯定遍历到的是数组中的第一个a。此时我们查找map时。找到的另一个值也是a。而map中的这个a刚好使我们数组中的第二个a。因为map中第一个a已被第二个覆盖掉了。所以取当前数组中的a的索引。同时取map中a的索引。就刚好是我们要的答案。

K Sum

这里提供递归解法。

KSum解决方法:
解决这类问题有两个方法:

  1. 暴力法:这是最直接的简单方法,问题是这个方法在K 足够大的时候时间复杂度会竭尽无穷大,故不是有效的理想方案;
  2. 递归法: 该方法是有技巧性的,关键在于寻找递归基,该问题的递归基是k = 2情况,
    关于,3Sum,3Sum Closest,4Sum的解题思路和参考代码。

KSum java代码:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

public class KSum {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //int[] s = new int[] {1,0,-1,0,-2,2 };
        int[] s = new int[]{-500,-490,-471,-456,-422,-412,-406,-398,-381,-361,-341,-332,-292,-288,-272,-236,-235,-227,-207,-203,-185,-119,-59,-13,4,5,46,72,82,91,92,130,130,140,145,159,187,207,211,226,239,260,262,282,290,352,377,378,386,405,409,430,445,478,481,498};
        System.out.println(" A solution set is: ");
        List<List<Integer>> listArray = new ArrayList<List<Integer>>();
        listArray = kSum(s,-3213);
        for (int i = 0; i < listArray.size(); i++) {
            System.out.println(listArray.get(i));
        }
    }

    public static List<List<Integer>> kSum(int[] nums, int target) {

        List<List<Integer>> result = new ArrayList<List<Integer>>();
        Arrays.sort(nums);
        result = recursionRoutin(nums,0,4,0);
        return result;
    }

    public static List<List<Integer>> recursionRoutin(int[] nums,int begin,int k,int target){
        HashSet<List<Integer>> elementSet = new HashSet<List<Integer>>();
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        List<List<Integer>> subResult = new ArrayList<List<Integer>>();
        //Recursion Base
        if(k == 2){
            int left = begin;
            int right = nums.length - 1;
            while(left < right){
                int sum = nums[left] + nums[right];
                if(sum == target){
                    List<Integer> taplet = new ArrayList<Integer>();
                    taplet.add(nums[left]);
                    taplet.add(nums[right]);
                    //Avoid reduplication 
                    if(!elementSet.contains(taplet)){
                        result.add(taplet);
                        elementSet.add(taplet);
                    }
                    left ++;
                    right --;
                }else if(sum < target){
                    left ++;
                }else{
                    right --;
                }
            }
            return result;
        }else{

            for(int i = begin;i < nums.length - k - 1;i ++){
                subResult = recursionRoutin(nums,i + 1,k - 1,target - nums[i]);
                //System.out.println(k + " " + subResult);
                if(!subResult.isEmpty()){
                    for(int j = 0;j < subResult.size();j ++){
                        subResult.get(j).add(nums[i]);
                        result.add(subResult.get(j));
                    }
                }
            }
        }
        return result;
    }
    }

参考博客:
https://blog.csdn.net/github_27609763/article/details/47728809
https://blog.csdn.net/qq_26437925/article/details/52787136  (方法多)
http://lib.csdn.net/article/datastructure/13655
https://www.jianshu.com/p/f8277161041c

猜你喜欢

转载自blog.csdn.net/jiede1/article/details/84405401
今日推荐