- Two Sum
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].
题意是给定一个乱序的数组和一个目标值,在数组中找到两个数使其之和为给定的目标数。
- 解法一:暴力搜索
class Solution {
public int[] twoSum(int[] nums, int target)
{
int[] res = new int[2];
if(nums==null||nums.length==0)
return res;
for(int i=0;i<nums.length;i++)
{
for(int j = i+1;j<nums.length;j++)
{
if(nums[i]+nums[j]==target)
{
res[0] = i;
res[1] = j;
return res;
}
}
}
retun res;
}
算法复杂度O(n^2),letcode上可以AC。
但是显然该种解法并不是最佳的解法,此题可以利用哈希映射或哈希表来使时间复杂度降为O(n),以空间换时间。其中利用HashMap比HashSet要少遍历一次数组,是该题较为理想的解法。
- 解法二:利用HashMap
import java.util.*;
class Solution
{
public int[] twoSum(int[] nums, int target)
{
if(nums==null)
return null;
HashMap<Integer,Integer> map = new HashMap<>();
for(int i = 0;i<nums.length;i++)
{
int temp = target-nums[i];
if(map.containsKey(temp))
return new int[]{map.get(temp),i};
map.put(nums[i],i);
}
return null;
}
}
该解法的核心思想是建立一个HashMap,然后从头遍历数组,依次判断目标值与数组中的值的差是否在HashMap中,如若不在则将该差以及数组值的下标存入HashMap中,直到找到某个差在HashMap中存在,则此时找到结果。
在Leetcode中还有一些类似与TwoSum的问题,如3Sum、4Sum等。该类问题都可以归结为K Sum问题。另外值得注意的是,若数组已经排序,则2Sum问题可以用双指针法,核心思想是使用两个index指向数组的起始和结束位置,若两标签指向的数之和小于目标数则左标签右移,若大于目标数则右标签左移,直到找到两数之和等于目标数或者左标签大于等于右标签结束,算法复杂度也为O(n)。
public void twoSum(int[]nums,int target,int start,int end)
{
int left = start,right = end;
while(left<right)
{
if(nums[left]+nums[right]==target)
{
ArrayList<Integer> list = new ArrayList<>();
list.add(-target);
list.add(nums[left]);
list.add(nums[right]);
res.add(list);
while(left<right&&nums[left]==nums[left+1])
left++;
while(left<right&&nums[right]==nums[right-1])
right--;
}
if(nums[left]+nums[right]<target)
left++;
else
right--;
}
}
- 3Sum
3Sum问题可以转化为2Sum问题,其中要注意答案的重复性,为此可以先将数组进行排序当前数字跟之前相同则跳过,然后依次遍历数组并调用twoSum的方法,算法复杂度为O(n^2)。
import java.util.*;
class Solution
{
List<List<Integer>> res = new ArrayList<List<Integer>>();
public List<List<Integer>> threeSum(int[] nums)
{
Arrays.sort(nums);
for(int i = 0;i<nums.length-2;i++)
{
int target = 0-nums[i];
if(i>0&&nums[i]==nums[i-1])
continue;
twoSum(nums,target,i+1,nums.length-1);
}
return res;
}
public void twoSum(int[]nums,int target,int start,int end)
{
int left = start,right = end;
while(left<right)
{
if(nums[left]+nums[right]==target)
{
ArrayList<Integer> list = new ArrayList<>();
list.add(-target);
list.add(nums[left]);
list.add(nums[right]);
res.add(list);
while(left<right&&nums[left]==nums[left+1])
left++;
while(left<right&&nums[right]==nums[right-1])
right--;
}
if(nums[left]+nums[right]<target)
left++;
else
right--;
}
}
}
- 4Sum
与3Sum问题一样,最后仍然转化为2Sum问题,算法复杂度O(n^3)。
import java.util.*;
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target)
{
List<List<Integer>> result = new ArrayList<List<Integer>>();
if(nums==null|| nums.length<4)
return result;
Arrays.sort(nums);
for(int i=0; i<nums.length-3; i++){
if(i!=0 && nums[i]==nums[i-1])
continue;
for(int j=i+1; j<nums.length-2; j++){
if(j!=i+1 && nums[j]==nums[j-1])
continue;
int k=j+1;
int l=nums.length-1;
while(k<l){
if(nums[i]+nums[j]+nums[k]+nums[l]<target){
k++;
}else if(nums[i]+nums[j]+nums[k]+nums[l]>target){
l--;
}else{
List<Integer> t = new ArrayList<Integer>();
t.add(nums[i]);
t.add(nums[j]);
t.add(nums[k]);
t.add(nums[l]);
result.add(t);
k++;
l--;
while(k<l &&nums[l]==nums[l+1] ){
l--;
}
while(k<l &&nums[k]==nums[k-1]){
k++;
}
}
}``
}
}
return result;
}
}
K Sum问题可以依次往下转化,最终转化为解决2Sum问题,算法复杂度为O(n^(k-1))。