algo/di-ling-zh-bfe1b/yi-ge-fang-894da/ #1451
Replies: 13 comments 6 replies
-
4Sum问题力扣的测试用例加了几个会导致原代码无法通过,比如 |
Beta Was this translation helpful? Give feedback.
-
Java 测试了 tuple.add(nums[i]); for each loop 会报错 |
Beta Was this translation helpful? Give feedback.
-
return new int[]{nums[lo], nums[hi]};不是返回下标吗? |
Beta Was this translation helpful? Give feedback.
-
python3在解决3sum时仍然会出现重复答案,因为由于语言特性,在
|
Beta Was this translation helpful? Give feedback.
-
python3的nSum函数还是会出现重复的,下面对i的循环应改成 class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
return self.nSumTarget(nums, 4, 0, target)
def nSumTarget(self, nums, n, start, target):
sz = len(nums)
res = []
if n < 2 or sz < n:
return res
if n == 2:
l, r = start, sz - 1
while l < r:
left, right = nums[l], nums[r]
sum_ = left + right
if sum_ < target:
l += 1
elif sum_ > target:
r -= 1
else:
res.append([left, right])
while l < r and nums[l] == left:
l += 1
while l < r and nums[r] == right:
r -= 1
else:
i = start
while i < sz:
sub = self.nSumTarget(nums, n - 1, i+1, target - nums[i])
for arr in sub:
arr.append(nums[i])
res.append(arr)
while i < sz - 1 and nums[i] == nums[i+1]:
i += 1
i += 1
return res |
Beta Was this translation helpful? Give feedback.
-
有同学反馈,threeSum的题java代码执行不通过,这是因为twoSumTarget方法中这行代码导致的,List list = Arrays.asList(left, right); 这里返回的list是不可变list,在后面threeSumTarget中内层for循环中使用tuple.add(nums[i]);会报错。 class Solution {
public List<List<Integer>> twoSumTarget(int[] nums, int start, int target) {
// 左指针改为从 start 开始,其他不变
int lo = start, hi = nums.length - 1;
List<List<Integer>> res = new ArrayList<>();
while (lo < hi) {
int sum = nums[lo] + nums[hi];
// 记录索引 lo 和 hi 最初对应的值
int left = nums[lo], right = nums[hi];
if (sum < target)
lo++;
else if (sum > target)
hi--;
else {
res.add(new ArrayList<>(Arrays.asList(left, right)));
// 跳过所有重复的元素
while (lo < hi && nums[lo] == left) lo++;
while (lo < hi && nums[hi] == right) hi--;
}
}
return res;
}
public List<List<Integer>> threeSum(int[] nums) {
// 求和为 0 的三元组
return threeSumTarget(nums, 0);
}
/* 计算数组 nums 中所有和为 target 的三元组 */
public List<List<Integer>> threeSumTarget(int[] nums, int target) {
// 数组得排个序
Arrays.sort(nums);
int n = nums.length;
List<List<Integer>> res = new ArrayList<>();
// 穷举 threeSum 的第一个数
for (int i = 0; i < n; i++) {
// 对 target - nums[i] 计算 twoSum
List<List<Integer>> tuples =
twoSumTarget(nums, i + 1, target - nums[i]);
// 如果存在满足条件的二元组,再加上 nums[i] 就是结果三元组
for (List<Integer> tuple : tuples) {
tuple.add(nums[i]);
res.add(tuple);
}
// 跳过第一个数字重复的情况,否则会出现重复结果
while (i < n - 1 && nums[i] == nums[i + 1]) i++;
}
return res;
}
} |
Beta Was this translation helpful? Give feedback.
-
看完以后豁然开朗,谢谢博主带我领略到了算法世界的美妙 |
Beta Was this translation helpful? Give feedback.
-
Java 版本的有 2 个bug:其中第一个其他版本也有,没有通过 leetcode 的测试用例,希望楼主改下 if (sum < target) {
while (lo < hi && nums.get(lo) == left) lo++;
} else if (sum > target) {
while (lo < hi && nums.get(hi) == right) hi--;
} else {
// bug1: 这里如果一直 sum > target ,会导致 lo==hi, 但是这里的 left + right != sum。
// 只是 lo==hi 这个因素导致逻辑走了这里,需要排除下这种情况。
// bug2,也是这里,只是 java 特有,楼主如果使用了 Arrays.asList(..) 这个 api,返回的 List 是
// 只读的,而你在下面又拿出这个列表添加元素,会导致异常
res.add(Arrays.asList(left, right));
while (lo < hi && nums.get(lo) == left) lo++;
while (lo < hi && nums.get(hi) == right) hi--;
} |
Beta Was this translation helpful? Give feedback.
-
ThreeSum这里真的有必要放这个么? if (sum < target) {
while (lo < hi && nums[lo] == left) lo++;
} else if (sum > target) {
while (lo < hi && nums[hi] == right) hi--; 假设数字不相等,这里就得跑两遍,因为 就算数字相等,你这里还是得多跑一遍,还是那个原因: 一开始 即便可以优化成避免第一次重复的情况
实际来说也没什么太大的意义,如果相同,这里比了2次+取1次值,进入下一个内循环也就是比1次+取两次值+一次加的操作,如果不相同,你就多了一轮。 总结来说优化后依然意义不大,而且代码看起来很乱。 |
Beta Was this translation helpful? Give feedback.
-
nSum 問題的 Python3 解法 class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
self.n = len(nums)
return self.nSum(nums, 4, 0, target)
# 給定 nums, n , start, target,返回 k 個數字的總和為 target 的所有 List[List[int]]
def nSum(self, nums, k, start, target):
res = []
if k < 2 or self.n < k:
return res
# Base case 為 twoSum
if k == 2:
left, right = start, self.n - 1
while left < right:
s = nums[left] + nums[right]
if s < target:
left += 1
elif s > target:
right -= 1
else:
res.append([nums[left], nums[right]])
while left < right and nums[left] == nums[left + 1]:
left += 1
while left < right and nums[right] == nums[right - 1]:
right -= 1
left += 1
right -= 1
else:
# k > 2, 遞歸調用 (n-1)Sum
for i in range(start, self.n):
if i == start or (i > start and nums[i] != nums[i - 1]):
sub = self.nSum(nums, k - 1, i + 1, target - nums[i])
for arr in sub:
res.append([nums[i]] + arr)
return res |
Beta Was this translation helpful? Give feedback.
-
3Sum里“跳过第一个数字重复的情况,否则会出现重复结果” 感觉用while写更清楚,原本在每个for循环还要i++一次就很难思考。
|
Beta Was this translation helpful? Give feedback.
-
nSum问题是不是也可以看做组合/子集问题? 即返回n个数的组合其sum正好为指定值时,就存到res里。套用 https://labuladong.github.io/algo/di-ling-zh-bfe1b/hui-su-sua-56e11/ 方法做? |
Beta Was this translation helpful? Give feedback.
-
algo/di-ling-zh-bfe1b/yi-ge-fang-894da/
Info 数据结构精品课 (https://aep.h5.xeknow.com/s/1XJHEO) 和 递归算法专题课 (https://aep.xet.tech/s/3YGcq3) 限时附赠网站会员!第 21 期打卡挑战 (https://opedk.xet.tech/s/4ptSo2) 最后一天报名! 读完本文,你不仅学会了算法套路,还可以顺便解决...
https://labuladong.github.io/algo/di-ling-zh-bfe1b/yi-ge-fang-894da/
Beta Was this translation helpful? Give feedback.
All reactions