
两次遍历就不写了,这里写双指针做法:
class Data implements Comparable{
int num;
int index;
Data(int num, int index){
this.num = num;
this.index = index;
}
@Override
public int compareTo(Object o) {
if(this.num < ((Data) o).num){
return -1;
}else if(this.num == ((Data)o).num){
return 0;
}else{
return 1;
}
}
}
class Solution {
int []res = new int[2];
public int[] twoSum(int[] nums, int target) {
// 双指针
int left = 0;
int right = nums.length-1;
List<Data> ls = new ArrayList<>();
for(int i=0; i<nums.length; i++){
Data data = new Data(nums[i], i);
ls.add(data);
}
Collections.sort(ls);
while(left < right){
if(ls.get(left).num + ls.get(right).num < target){
left++;
continue;
}
if(ls.get(left).num + ls.get(right).num > target){
right--;
continue;
}
res[0] = ls.get(left).index;
res[1] = ls.get(right).index;
break;
}
return res;
}
}
三指针:固定死一个,其他的走
class Solution {
List<List<Integer>> res = new LinkedList<>();
Set<List<Integer>> set = new HashSet<>();
public List<List<Integer>> threeSum(int[] nums) {
// 三指针
int left = 0;
int right = nums.length-1;
int mid = 0;
// 排序
Arrays.sort(nums);
while(mid < nums.length){
while(left < right){
if(left == mid){
left+=1;
continue;
}
if(right == mid){
right--;
continue;
}
if(nums[left] + nums[mid] + nums[right] < 0){
left++;
continue;
}
if(nums[left] + nums[mid] + nums[right] > 0){
right--;
continue;
}
List<Integer> ls = new LinkedList<>();
if(mid < left){
ls.add(nums[mid]);
ls.add(nums[left]);
ls.add(nums[right]);
}else if(mid > left && mid < right){
ls.add(nums[left]);
ls.add(nums[mid]);
ls.add(nums[right]);
}else if(mid > right){
ls.add(nums[left]);
ls.add(nums[right]);
ls.add(nums[mid]);
}
set.add(ls);
left++;
right--;
//break;
}
left = 0;
right = nums.length-1;
mid++;
}
for(List lls: set){
res.add(lls);
}
return res;
}
}
同样使用的三指针......
class Solution {
public int threeSumClosest(int[] nums, int target) {
// 三指针
int left = 0;
int mid = 0;
int right = nums.length-1;
Arrays.sort(nums);
int res = 0;
int mv = Integer.MAX_VALUE;
while(mid < nums.length){
while(left < right){
if(left == mid){
left++;
continue;
}
if(right == mid){
right--;
continue;
}
if(Math.abs(nums[left] + nums[mid] + nums[right] - target) < mv){
res = nums[left] + nums[mid] + nums[right];
mv = Math.abs(nums[left] + nums[mid] + nums[right] - target);
}
if(nums[left] + nums[mid] + nums[right] - target > 0){
right--;
continue;
}
if(nums[left] + nums[mid] + nums[right] - target < 0){
left++;
continue;
}
if(nums[left] + nums[mid] + nums[right] - target == 0){
return target;
}
}
left = 0;
right = nums.length-1;
mid++;
}
// System.out.println(res);
return res;
}
}

看题解说,三指针的基础上再来一层for循环就能解决,但是我还是用了递归去做:
但凡少一个判断,或判断写的不对,剪枝有问题,就会超时......
class Solution {
List<List<Integer>> res = new LinkedList<>();
Set<LinkedList<Integer>> set = new HashSet<>();
private void dfs(int []nums, int target, int n, int index, LinkedList<Integer> ls, int sum, boolean sign[]){
// 如果换成 n > 4 return 会超时
if(n == 4 && sum != target){
return;
}
if(n == 4 && sum == target){
set.add(new LinkedList<>(ls));
return;
}
for(int i=index; i<nums.length; i++){
// 不加下面的剪枝会超时
if(nums[i] > 0 && sum >= target){
break;
}
if(sign[i]){
continue;
}
sign[i] = true;
ls.addLast(nums[i]);
dfs(nums, target, n+1, i, ls, sum+nums[i], sign);
ls.removeLast();
sign[i] = false;
}
}
public List<List<Integer>> fourSum(int[] nums, int target) {
// 保证不重复
Arrays.sort(nums);
LinkedList<Integer> ls = new LinkedList<>();
boolean sign[] = new boolean[nums.length];
dfs(nums, target, 0, 0, ls, 0, sign);
for(LinkedList lks: set){
res.add(lks);
}
return res;
}
}

被折叠的 条评论
为什么被折叠?



