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].
一下能想到的思路就是内外两个循环找和为target的两个数字,这样的复杂度是O(n*n)。
想到能否用哈希表,每遍历到一个元素num,看target-num是否在hash表中,如果在就得出答案,如果不在就将当前num放入哈希表中。
public int[] twoSum(int[] nums, int target) {
HashMap map= new HashMap();
int[] result = new int[2];
for(int i=0;iif(map.containsKey(target-nums[i])){
result[0]=i;
result[1] = map.get(target-nums[i]);
break;
}else{
map.put(nums[i],i);
}
}
return result;
}
这种解法是O(n)的时间复杂度,但要额外增加O(n)的哈希表存储空间。
可以换个角度来考虑问题,如果给定的数组是已排序的数组,那么就可以设定lo和hi两个指针,如果这两个数字的和比target要大,那么就lo++,否则hi–。这样排序数组需要O(NlogN),找和的过程需要O(N),但是空间是in-place的。
其实这是167. Two Sum II - Input array is sorted
抛出的问题。这样我们就不用对数组排序了。
public int[] twoSum(int[] numbers, int target) {
int i = 0;
int j = numbers.length-1;
int[] result = new int[2];
while(j>i){
if(numbers[i]+numbers[j] == target){
result[0] = i+1;
result[1] = j+1;
break;
}else if(numbers[i]+numbers[j] < target){
i++;
}else{
j--;
}
}
return result;
}
时间复杂度为O(N)
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note: The solution set must not contain duplicate triplets.
For example, given array S = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
这次是寻找3个数的和为0的组合。可以接着2Sum解法三的思路来想。首先先对数组排序;然后从头开始每次取一个数作为sum,则此题变成了在后面的数组中寻找两个数其和为-sum,就和上面的过程一样。
这里还要注意一个重复的问题,当我们对数组排序后,重复的数是排列在一起的,此时若已经取过一个解后就不要再取重复的解了。
public List> threeSum(int[] nums) {
int len = nums.length;
List> result = new ArrayList>();
Arrays.sort(nums);
for(int i=0;i//防止重复解
if(i==0 || nums[i]!=nums[i-1]){
int sum = 0-nums[i];
int lo = i+1;
int hi = len-1;
while(loif(nums[lo]+nums[hi] == sum){
result.add(Arrays.asList(nums[i], nums[lo], nums[hi]));
//防止重复解
while(lo1])lo++;
while(lo1])hi--;
lo++;
hi--;
}else if(nums[lo]+nums[hi]>sum){
hi--;
}else{
lo++;
}
}
}
}
return result;
}
这种解法的时间复杂度为O(N*N)
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
其实和上面的过程一样,只不过是相等比较转换成了差值的比较。
public int threeSumClosest(int[] nums, int target) {
int len = nums.length;
if(len<3) return -1;
Arrays.sort(nums);
int result = nums[0]+nums[1]+nums[2];
for(int i=0;i2;i++){
int lo = i+1;
int hi = len-1;
while(loint sum = nums[i]+nums[lo]+nums[hi];
if(sum == target){
return sum;
}else{
if(Math.abs(sum-target) < Math.abs(target-result)){
result = sum;
}
if(sum>target){
hi--;
}else{
lo++;
}
}
}
}
return result;
}
这种解法的时间复杂度为O(N*N)
可以发现,two sum的解法三是适用于其他变种的,都是在数组已排序的情况下根据当前和与target的比较情况移动指针,其中也要特别注意避免重复解的问题。