三数之和
图二:
图三:
java:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ret = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length;) {
// 固定数 a
int a = nums[i];
int target = -a;
// 小优化
if (a > 0) {
// 此时 left 和 right 表示的数都为正数
break;
}
// 双指针
int left = i + 1;
int right = nums.length - 1;
while (left < right) {
if (nums[left] + nums[right] < target) {
left++;
} else if (nums[left] + nums[right] > target) {
right--;
} else {
// 此时相等 --> 将数据填入到 ret 中
ret.add(Arrays.asList(nums[left], nums[right], a));
left++;
right--;
// 去重操作 --> left < right 是防止出现越界的情况
while (left < right && nums[left] == nums[left - 1]) {
left++;
}
while (left < right && nums[right] == nums[right + 1]) {
right--;
}
}
}
// left 和 right 完成去重操作 对 a 进行去重操作
i++;
while (i < nums.length && nums[i] == nums[i - 1]) {
i++;
}
}
return ret;
}
}
python:
class Solution(object):
# 三数之和
def threeSum(self, nums):
ret = []
nums.sort()
i = 0
while i < len(nums):
# 固定一个数
a = nums[i]
# 三数之和相加为 0
target = -a
if a > 0:
break
# 双指针
left = i + 1
right = len(nums) - 1
# 进行遍历
while left < right:
sum = nums[left] + nums[right]
if sum < target:
left += 1
elif sum > target:
right -= 1
else:
# 此时找到了
ret.append([a, nums[left], nums[right]])
left += 1
right -= 1
# 去重操作
while left < right and nums[left] == nums[left - 1]:
left += 1
while left < right and nums[right] == nums[right + 1]:
right -= 1
i += 1
while i < len(nums) and nums[i] == nums[i - 1]:
i += 1
return ret
这里思路其实非常好像,就是 排序完后固定一个值,然后 双指针找一个数,但难在如何进行去重操作, 如果上面去重操作觉得有点问题的话,可以使用 set 来去重,set 里面存储的数据是唯一的.
java:
// 1. 排序 2.双指针 3.去重
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
HashSet<List<Integer>> hashSet = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
int left = i + 1;
int right = nums.length - 1;
int a = nums[i];
while (left < right) {
List<Integer> list1 = new ArrayList<>();
if (a + nums[left] + nums[right] == 0) {
list1.add(a);
list1.add(nums[left]);
list1.add(nums[right]);
hashSet.add(list1);
left++;
right--;
} else if (a + nums[left] + nums[right] > 0) {
right--;
} else {
left++;
}
}
}
return new ArrayList<>(hashSet);
}
四数之和
这道题是对三数之和的衍生, 这里 先固定一个数,接下来不就剩下三个数了吗,那么三个数就直接使用三数之和的思路不就好了.
java
class Solution {
// 四数之和
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ret = new ArrayList<>();
Arrays.sort(nums);
if(nums == null || nums.length < 4){
return ret;
}
for (int i = 0; i < nums.length;) {
// 固定第一个数
int a = nums[i];
if (a > 0 && target < 0) {
break;
}
// 三数之和
for (int j = i + 1; j < nums.length;) {
// 固定第二个数
int b = nums[j];
long number = (long)target - a - b;
// 使用双指针
int left = j + 1;
int right = nums.length - 1;
while (left < right) {
int cur1 = nums[left];
int cur2 = nums[right];
if (cur1 + cur2 > number) {
right--;
} else if (cur1 + cur2 < number) {
left++;
} else {
// 此时找到了 添加到 ret 中
ret.add(Arrays.asList(a, b, cur1, cur2));
left++;
right--;
// 去重操作
while (left < right && nums[left] == nums[left - 1]) {
left++;
}
while (left < right && nums[right] == nums[right + 1]) {
right--;
}
}
}
// 对三数固定的值进行去重
j++;
while (j < nums.length && nums[j] == nums[j - 1]) {
j++;
}
}
// 此时对 第一个固定的数进行去重操作
i++;
while (i < nums.length && nums[i - 1] == nums[i]) {
i++;
}
}
return ret;
}
}
这道题 力扣 很 恶心 弄出来两个溢出的情况,只需要使用 Long 即可.
python:
class Solution(object):
# 四数之和
def fourSum(self, nums, target):
ret = []
nums.sort()
if nums is None or len(nums) < 4:
return ret
i, j = 0, 0
while i < len(nums):
a = nums[i]
if a > 0 > target:
break
j = i + 1
while j < len(nums):
b = nums[j]
left, right = j + 1, len(nums) - 1
number = target - a - b
while left < right:
sum = nums[left] + nums[right]
if sum < number:
left += 1
elif sum > number:
right -= 1
else:
# 此时相等
ret.append([a, b, nums[left], nums[right]])
left += 1
right -= 1
# 去重
while left < right and nums[left] == nums[left - 1]:
left += 1
while left < right and nums[right] == nums[right + 1]:
right -= 1
# 对 j 进行去重
j += 1
while j < len(nums) and nums[j] == nums[j - 1]:
j += 1
# 对 i 进行去重
i += 1
while i < len(nums) and nums[i] == nums[i - 1]:
i += 1
return ret