问题:K Sum问题是一个问题系列,在一个数组中找K个数的和能够满足题目中要求。从2 Sum 到 3 Sum , 3 Sum Clozet , 4 Sum。。解法虽一开始不容易想到,但get到解题技能后,该系列的题目其实解法较为单一。

一、核心解题思路。Two Sum。

题目:一个数组a中,找寻两个数,使其和等于target。返回两个数的下标。

思路:最白目的思路是O(n2)解法,无需多言。精彩的解法能够O(n)完成算法。

   将该数组进行排序。设置两个指针start,end指向数组的头尾。如果a[start] + a[end] < target,那么将start指针往后移,因为当前的和值比目标值小;反之,将end指针向前移,因为当前的和值比目标值大。直到两个指针相遇,结束查找。

代码:由于要返回两个数的下标,因此在对数组进行排序之前,需要记录数据的原始下标。

 public class Solution {
public int[] twoSum(int[] numbers, int target) { if(numbers.length <= 1) return null; Pair[] pairs = new Pair[numbers.length];
for(int i = 0 ; i < numbers.length ; i++){
pairs[i] = new Pair(numbers[i] , i+1);
} Comparator<Pair> comparator = new Comparator<Pair>(){
public int compare(Pair o1 , Pair o2){
return o1.val > o2.val ? 1 : -1 ;
}
}; Arrays.sort(pairs , comparator); int index1 = 0 , index2 = numbers.length - 1; while(index1 < index2){
int temp = pairs[index1].val + pairs[index2].val;
if(temp == target) break;
else if(temp < target) index1++;
else index2--;
}
if(pairs[index1].index < pairs[index2].index) return new int[]{pairs[index1].index , pairs[index2].index};
else return new int[]{pairs[index2].index , pairs[index1].index};
}
} class Pair{
int val;
int index;
Pair(int x , int y){
val = x;
index = y;
}
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

二、举一反三。3 Sum。

问题:一个数组a,判断其中是否存在三个数a , b , c 使其和为target。返回这些三元组集合。

思路:该问题可退化为 2 Sum问题来解答。先选择任意一个数a ,然后判断剩余数组中是否存在另外两个数的和等于target - a。<----这里就完全是2 Sum问题的方法了。

代码:

 public ArrayList<ArrayList<Integer>> threeSum(int[] num) {

         ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();

         Arrays.sort(num);

         for(int i = 0 ; i < num.length ; i++){
int target = 0 - num[i];
//由于结果要求三元组的值要非递减顺序,因此将数组排序后,从头开始定第一个数据,后两个数据从该数据的后部选取。
for(int j = i + 1 , k = num.length - 1 ; j < num.length && k >= 0 && j < k ;){
int temp = num[j] + num[k];
if(temp == target){ boolean ifAdd = true; //judge duplicate
for(int index = 0 ; index < result.size() ; index++){
if(result.get(index).get(0) == num[i]
&& result.get(index).get(1) == num[j]
&& result.get(index).get(2) == num[k]){
ifAdd = false;
break;
}
}
if(ifAdd){
ArrayList<Integer> one = new ArrayList<Integer>();
one.add(num[i]);
one.add(num[j]);
one.add(num[k]);
result.add(one);
}
j++; }else if(temp < target) j++;
else k--;
}
}
return result;
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

三、练习熟悉。3 Sum Closest。

题目:给顶一个数组a,求最接近target的三元组的和。输出该和。

思路:完全与3 Sum问题相同。唯一不同的地方在于,因为它是判断与target最接近,因此利用绝对值来判断当前和是否与target最接近。

代码:

public int threeSumClosest(int[] num, int target) {

        Arrays.sort(num);
int min = Integer.MAX_VALUE; for(int i = 0 ; i < num.length ; i++){ for(int j = i + 1 , k = num.length - 1 ; j < num.length && k >= 0 && j < k ;){
int threeSum = num[j] + num[k] + num[i];
if(threeSum == target) {
min = 0;
break;
}else{ int dis = target - threeSum;
//利用绝对值来判断是否与traget最接近。
if(Math.abs(dis) < Math.abs(min)) {
min = dis;
} if(dis > 0) j++;
else k--;
}
}
if(min == 0){
break;
}
}
return target - min;
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

四、还是练习。4 Sum。

问题:一个数组a,寻找是否存在四个数a + b + c + d = target。返回四元组集合。

思路:先固定住一个数a , 然后寻找剩余数组中是否存在三个数和 等于 target - a(退化为3Sum),然后计算三个数和时,再先固定一个数b,然后寻找剩余数组中是否存在两个数和等于target-a -b(退化为2Sum)。

代码:

 public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {

         ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();

         if(num.length <= 3) return result;

         Arrays.sort(num);

         for(int i = 0 ; i <= num.length - 4 ; i++){
for(int j = i + 1 ; j <= num.length - 3 ; j++){
int start = j + 1;
int end = num.length - 1;
while(start < end){
int temp = num[i] + num[j] + num[start] + num[end];
if(temp == target){
boolean ifAdd = true;
for(int k = 0 ; k < result.size() ; k++){
if(result.get(k).get(0) == num[i] && result.get(k).get(1) == num[j]
&& result.get(k).get(2) == num[start] && result.get(k).get(3) == num[end]){
ifAdd = false;
break;
}
} if(ifAdd){
ArrayList<Integer> each = new ArrayList<Integer>();
each.add(num[i]);
each.add(num[j]);
each.add(num[start]);
each.add(num[end]);
result.add(each);
} start++; }else if(temp < target) start++;
else end--;
}
}
} return result;
}

因此,总结K Sum的问题,其核心思路就是2Sum问题,任何K > 2时,都可通过逐层退化,到2Sum。而2Sum问题,在将数据进行排序后,就可通过两个指针来达到要求。

[leetcode]_K Sum 问题的更多相关文章

  1. LeetCode:Path Sum I II

    LeetCode:Path Sum Given a binary tree and a sum, determine if the tree has a root-to-leaf path such ...

  2. 剑指offer 65. 不用加减乘除做加法(Leetcode 371. Sum of Two Integers)

    剑指offer 65. 不用加减乘除做加法(Leetcode 371. Sum of Two Integers) https://leetcode.com/problems/sum-of-two-in ...

  3. [LeetCode] Path Sum III 二叉树的路径和之三

    You are given a binary tree in which each node contains an integer value. Find the number of paths t ...

  4. [LeetCode] Combination Sum IV 组合之和之四

    Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...

  5. [LeetCode] Max Sum of Rectangle No Larger Than K 最大矩阵和不超过K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

  6. [LeetCode] Range Sum Query 2D - Mutable 二维区域和检索 - 可变

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  7. [LeetCode] Range Sum Query - Mutable 区域和检索 - 可变

    Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive ...

  8. [LeetCode] Range Sum Query 2D - Immutable 二维区域和检索 - 不可变

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  9. [LeetCode] Range Sum Query - Immutable 区域和检索 - 不可变

    Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive ...

随机推荐

  1. SQL锁表解决并发性

    在数据库开发过程中,不得不考虑并发性的问题,因为很有可能当别人正在更新表中记录时,你又从该表中读数据,那你读出来的数据有可能就不是你希望得到的数据.可以说有些数据同时只能有一个事物去更新,否则最终显示 ...

  2. [Java] File文件列表

    package test.file; import java.io.File; import java.io.FilenameFilter; /** * 文件列表,文件过滤 * @author Fro ...

  3. [ActionScript 3.0] AS3 深入理解Flash的安全沙箱Security Domains

    简介 如果你还没有与复杂的的安全域(security domain)和应用程序域(application domain)问题打过交道,那么你真是个幸运的家伙.当你在加载外部内容(然后他们开始播放)的时 ...

  4. MySql中增加一列

    如果想在一个已经建好的表中添加一列,可以用诸如: alter table TABLE_NAME add column NEW_COLUMN_NAME varchar(20) not null; 这条语 ...

  5. esriSRGeoCS2Type Constants

    ArcGIS Developer Help  (Geometry)     esriSRGeoCS2Type Constants More geographic coordinate systems. ...

  6. windows下如何使用makefile编译

    1. 编写makefile. 2. 使用nmake进行编译, vs2010或者其他都是用nmake进行编译的,将bin目录添加到path环境变量中 先执行vcvars32.bat 再执行nmake

  7. Xml语言

    一.XML是什么?作用是什么? l  XML ( eXtensible Markup Language )语言是一种可扩展的标记语言.其中的可扩展是相对HTML来说的.因为XML标签没有被预定义,需要 ...

  8. java中高级软件工程师面试总结

    最近去了几家公司面试java中高级工程师,打击挺大的,感觉自己一直以来没有很好的深入学习,对各种知识都是一知半解,但心又太高,想找更高薪的职位,结果面试屡屡碰壁,哎,心情好低落,也是时候静下心来,好好 ...

  9. [ Office 365 开发系列 ] 开发模式分析

    前言 本文完全原创,转载请说明出处,希望对大家有用. 在正式开发Office 365应用前,我们先了解一下Office 365的开发模式,根据不同的应用场景,我们选择最适合的开发模式. 阅读目录 Of ...

  10. 在Web中实现C/S模式的Tab

    在探讨C/S模式的Tab之前,我们先总结一下B/S模式的Tab通常是什么样的.web中常见的tab设计通常是用于分节展示大量信息以提高页面空间的利用率,而且这些信息通常是静态的,或者交互比较简单.通过 ...