这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战
因为有年假要过期,今天休假了一天,难得在周一早上睡了个大懒觉,体会了一下生活节奏慢下来的感觉。慢慢吃了个早饭,也不用急匆匆背包出门,手机上刷刷咨询。每隔一段时间,确实需要一个像这样的周一,一个额外的、完全的放松身体的时间。
这个周末公司也发生了很多事,看到了无底线的丑陋行径,也有更多善良小伙伴的仗义执言。一个周末过去,恍如隔世。世间有太多丑恶,随着年龄和阅历的增长,甚至对一些突破底线的丑恶,也渐渐变更理性和麻木,不过挺身而出、仗义执言之时,看到还是有很多一样的小伙伴,真是有幸。想起来一句话,我们付出这么多努力,不是为了改变什么,而是为了不被这个世界改变。做好自己,心中有火、眼中有光,你是什么样子,你的世界就是什么样子。
扯远了,今天终于不是在晚上才做题了,继续挑战leetcode第18题。
题目
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] :
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]
思路
这题跟前两天的三数之和是非常类似的,3变成了4。 还是从暴力解法开始,最容易想到也最暴力就是4层for循环。 然后通过排序数组和收尾双指针,去掉了1层循环。跟三数之和不同的是,需要先假定2个数,才能做双指针,之前是先假定1个数,不过原理其实是一模一样的。不过过多描述,详情可以参看《leetcode-三数之和》
Java版本代码
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ans = new ArrayList<>();
int len = nums.length;
if (len < 4) {
return ans;
}
Arrays.sort(nums);
for (int i = 0; i < len - 3; i++) {
// 去重
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
// 因为数组从小到大排列,如果当前最小的4个数之和已经超过target了,就不需要再遍历这种情况了
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
break;
}
for (int j = i + 1; j < len -2; j++) {
// 去重
if (j > i + 1 && nums[j] == nums[j - 1]) {
continue;
}
// 因为数组从小到大排列,如果当前最小的4个数之和已经超过target了,就不需要再遍历这种情况了
if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
break;
}
// need为需要的后面2个数的和
int need = target - nums[i] - nums[j];
int start = j + 1;
int end = len - 1;
while (start < end) {
if (nums[start] + nums[end] == need) {
ans.add(Arrays.asList(nums[i], nums[j], nums[start], nums[end]));
start++;
end--;
while (start < end && nums[start] == nums[start - 1]) {
start++;
}
while (start < end && nums[end] == nums[end + 1]) {
end--;
}
} else if (nums[start] + nums[end] > need) {
end--;
} else if (nums[start] + nums[end] < need) {
start++;
}
}
}
}
return ans;
}
}