题目一:2 sum 找两数之和为target的下标。
hashmap 当哈希表中不存在当前i的数字target-numbers[i]时,将(numbers[i],i)put入表;找到则返回。
import java.util.*;
public class Solution {
public int[] twoSum(int[] numbers, int target) {
int[] index=new int[2];
if(numbers == null||numbers.length<2)
return index;
Map<Integer,Integer> map=new HashMap();
map.put(numbers[0],0);
for(int i=1;i<numbers.length;i++)
{
if(map.containsKey(target-numbers[i]))
{
index[0]=map.get(target-numbers[i])+1;
index[1]=i+1;
}
else
{
map.put(numbers[i],i);
}
}
return index;
}
}
若题目要求为保存数值,也可排序后使用双下标从两端查找。
public int[] twoSum(int[] numbers, int target) {
int[] index=new int[2];
if(numbers == null||numbers.length<2)
return index;
Arrays.sort(numbers);
int left=0;
int right=numbers.length-1;
while(left<right)
{
if(numbers[left]+numbers[right] == target)
{
index[0]=numbers[left];
index[1]=numbers[right];
break;
}
else if(numbers[left]+numbers[right] < target)
{
left++;
}else
{
right--;
}
}
return index;
}
题目二:3 sum 数组中是否存在三个数a,b,c使得a+b+c = 0?
并且需要满足的条件为:
- 1. triplet (a,b,c) 不能降序排列. (ie,a ≤ b ≤ c),
- 2. ArrayList<ArrayList<Integer>>中不能存放重复的triplet.
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)题解:从所需满足的条件判断,应该先对数组num排序,然后将3 Sum分解为【1 sum+2 sum】,即固定一个数字,另外的两个数组按照2 sum的解法,并且所要储存的是值,所2 sum可以采用两个下标的方法。
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
ArrayList<ArrayList<Integer>> array=new ArrayList();
if(num == null||num.length<3)
return array;
ArrayList<Integer> list=new ArrayList();
Arrays.sort(num);//排序;
for(int i=0;i<num.length-2;i++)
{
if(i>0&&num[i] == num[i-1])//不能有重复的triplet;
continue;
int left=i+1;
int right=num.length-1;
while(left<right)//防止越界;
{
int sum=num[i]+num[left]+num[right];
if(sum == 0)
{
list.add(num[i]);
list.add(num[left]);
list.add(num[right]);
array.add(list);
list=new ArrayList();
//left和right都要移位。
left++;
while(left<right&&num[left] == num[left-1])//防止有连续重复的值;
{
left++;
}
right--;
while(right>left&&num[right] == num[right+1])//防止有连续重复的值;
{
right--;
}
}
else if(sum<0)
left++;
else
right--;
}
}
return array;
}
题目三:3 sum closed
错误分析:
closed为数组中三数之和中最接近target的,那么初始化closed时随便找三个数组元素求和就好了,如closed =num[0]+num[]1+num[2] is correct!
import java.util.*;
public class Solution {
public int threeSumClosest(int[] num, int target) {
if(num == null||num.length<3)
return 0;
Arrays.sort(num);
int closed=Integer.MAX_VALUE;//closed =num[0]+num[]1+num[2] is correct!
// System.out.println(Math.abs(Integer.MAX_VALUE-(-1)));得:-2147483648。补码的原因。
for(int i=0;i<num.length-2;i++)
{
if(i>0&&num[i] == num[i-1])
continue;
int left=i+1;
int right=num.length-1;
while(left<right)
{
int sum=num[i]+num[left]+num[right];
if(sum == target)
{
return target;
}
if(Math.abs(target-sum)<Math.abs(closed-target))
{
closed=sum;
}
if(sum<target)
{
left++;
}else
{
right--;
}
}
}
return closed;
}
}
题目四:4 Sum
题目描述
一个有n个整数的数组,是否存在四个元素a, b, c, d使得 a + b + c + d = target? 找出所有的满足条件的四个为一组的元素。
注:
- 1.quadruplet (a,b,c,d) 不能降序排列. (ie, a ≤ b ≤ c ≤ d),
- 2. ArrayList<ArrayList<Integer>>中不能存放重复的quadruplet.
例如:
given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: (-1, 0, 0, 1) (-2, -1, 1, 2) (-2, 0, 0, 2)
题解:
1.先对数组进行排序;
2.固定一个数num[i],对之后的数进行3 Sum;
总的时间复杂度为O(N^3)!
public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) { ArrayList<ArrayList<Integer>> array=new ArrayList(); if(num == null||num.length<4) return array; ArrayList<Integer> list=new ArrayList(); Arrays.sort(num); for(int i=0;i<num.length-3;i++) { if(i>0&&num[i] == num[i-1]) continue;//避免重复; //3 Sum for(int j=i+1;j<num.length-2;j++) { if(j>i+1&&num[j] == num [j-1]) continue;//避免重复; int left=j+1; int right=num.length-1; while(left<right) { int sum=num[i]+num[j]+num[left]+num[right]; if(sum == target) { list.add(num[i]); list.add(num[j]); list.add(num[left]); list.add(num[right]); array.add(list); list=new ArrayList(); //sum == target情况时,left++和right--操作不能遗漏,且两个都有必要! left++; while(left<right&&num[left] == num[left-1])//避免重复; left++; right--; while(left<right&&num[right] == num[right+1])//避免重复; right--; } else if(sum<target) { left++; }else { right--; } } } } return array; }