1. 两数之和
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 :
1 2 3 4 > Given nums = [2, 7, 11, 15], target = 9, > Because nums[0] + nums[1] = 2 + 7 = 9, > return [0, 1]. >
思路:
首先,这一题有如下要求:
- 得到的index要是有序的
- 假设只有一组解满足要求,大大降低了难度
- 相同的元素是不可以用两次的。(ps:一开始我是没有注意到这点的,结果有个测试用例【5 5 7 8】,导致没有通过)
其实最简单的就是通过一个二层循环来解决,但这肯定不是最优解,
所以我们可以考虑用HashMap来存储这些元素,如键:nums中的元素,值为元素的index。之后用一次循环来解决这个问题
代码:
import java.util.Map;
import java.util.HashMap;
class Solution {
public int[] twoSum(int[] numbers, int target) {
int[] temp = new int[2];
HashMap<Integer,Integer> hs = new HashMap<Integer,Integer>();
for(int i=0;i<numbers.length;i++){
if(hs.containsKey(target-numbers[i])){
temp[1] = i; //之前存进去的值肯定是index较小的,所以放在第一位
temp[0] = hs.get(target-numbers[i]);
return temp;
}
hs.put(numbers[i],i);
}
return temp;
}
}
从三数之和开始,我采用的方法并不是最优解,下面这个链接中的解法认为是比较好的:
https://blog.csdn.net/zkyzq/article/details/78038631
2.三数之和
给出一个有n个整数的数组S,在S中找到三个整数a, b, c,找到所有使得a + b + c = 0的三元组。
在三元组(a, b, c),要求a <= b <= c。
结果不能包含重复的三元组。
如S = {-1 0 1 2 -1 -4}, 你需要返回的三元组集合的是:
(-1, 0, 1)
(-1, -1, 2)
思路: 我是利用回溯,一个个地去探查的,时间复杂度有点高。
时间复杂度低地讲解:
public static List<List<Integer>> res = new ArrayList<>();
public static List<List<Integer>> threeSum(int[] numbers) {
// write your code here
List<Integer> list = new ArrayList<>();
int sum = 0;
backtracing(numbers, 0, list, sum);
return res;
}
public static void backtracing(int[] nums, int start, List<Integer> list, int sum){
if(list.size()==3){
if(sum==0){
ArrayList<Integer> temp = new ArrayList<>(list); // zhuyi
Collections.sort(temp);
if(!res.contains(temp)){
res.add(temp);
}
}
return;
}
for (int i = start; i < nums.length; i++) {
list.add(nums[i]);
backtracing(nums, i+1, list, sum+nums[i]);
list.remove(list.size()-1);
}
}
3.最接近的三数之和
给一个包含 n 个整数的数组 S, 找到和与给定整数 target 最接近的三元组,返回这三个数的和。
只需要返回三元组之和,无需返回三元组本身
例如 S = [-1, 2, 1, -4]
and target = 1
. 和最接近 1 的三元组是 -1 + 2 + 1 = 2.
思路:跟上面一样,采用的是回溯遍历,只是判断条件改了
代码:
public static int flag = Integer.MAX_VALUE;
public static int res = Integer.MAX_VALUE;
public static int threeSumClosest(int[] numbers, int target) {
// write your code here
List<Integer> list = new ArrayList<>();
int sum = 0;
backtracing(numbers, 0, list, 0, target);
return res;
}
public static void backtracing(int[] nums, int start, List<Integer> list, int sum, int target){
if(list.size()==3){
if(Math.abs(sum-target)<flag){
flag = Math.abs(sum-target);
res = sum;
}
return;
}
for (int i = start; i < nums.length; i++) {
list.add(nums[i]);
backtracing(nums, i+1, list, sum+nums[i], target);
list.remove(list.size()-1);
}
}
3.四数之和
给一个包含n个数的整数数组S,在S中找到所有使得和为给定整数target的四元组(a, b, c, d)。
四元组(a, b, c, d)中,需要满足a <= b <= c <= d
答案中不可以包含重复的四元组。
样例例如,对于给定的整数数组S=[1, 0, -1, 0, -2, 2] 和 target=0. 满足要求的四元组集合为:
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)
思路:一开始采用了上述的回溯遍历,但是时间超了,下面是比较好的解:
代码:
public List<List<Integer>> fourSum(int[] num, int target) {
List<List<Integer>> rst = new ArrayList<List<Integer>>();
Arrays.sort(num);
for (int i = 0; i < num.length - 3; i++) {
if (i != 0 && num[i] == num[i - 1]) {
continue;
}
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) {
left++;
} else if (sum > target) {
right--;
} else {
ArrayList<Integer> tmp = new ArrayList<Integer>();
tmp.add(num[i]);
tmp.add(num[j]);
tmp.add(num[left]);
tmp.add(num[right]);
rst.add(tmp);
left++;
right--;
while (left < right && num[left] == num[left - 1]) {
left++;
}
while (left < right && num[right] == num[right + 1]) {
right--;
}
}
}
}
}
return rst;
}