|
10 | 10 |
|
11 | 11 | # 第15题. 三数之和
|
12 | 12 |
|
13 |
| -[力扣题目链接](https://leetcode-cn.com/problems/3sum/) |
| 13 | +[力扣题目链接](https://leetcode.cn/problems/3sum/) |
14 | 14 |
|
15 | 15 | 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
|
16 | 16 |
|
@@ -345,6 +345,76 @@ var threeSum = function(nums) {
|
345 | 345 | return res
|
346 | 346 | };
|
347 | 347 | ```
|
| 348 | + |
| 349 | +解法二:nSum通用解法。递归 |
| 350 | + |
| 351 | +```js |
| 352 | +/** |
| 353 | + * nsum通用解法,支持2sum,3sum,4sum...等等 |
| 354 | + * 时间复杂度分析: |
| 355 | + * 1. n = 2时,时间复杂度O(NlogN),排序所消耗的时间。、 |
| 356 | + * 2. n > 2时,时间复杂度为O(N^n-1),即N的n-1次方,至少是2次方,此时可省略排序所消耗的时间。举例:3sum为O(n^2),4sum为O(n^3) |
| 357 | + * @param {number[]} nums |
| 358 | + * @return {number[][]} |
| 359 | + */ |
| 360 | +var threeSum = function (nums) { |
| 361 | + // nsum通用解法核心方法 |
| 362 | + function nSumTarget(nums, n, start, target) { |
| 363 | + // 前提:nums要先排序好 |
| 364 | + let res = []; |
| 365 | + if (n === 2) { |
| 366 | + res = towSumTarget(nums, start, target); |
| 367 | + } else { |
| 368 | + for (let i = start; i < nums.length; i++) { |
| 369 | + // 递归求(n - 1)sum |
| 370 | + let subRes = nSumTarget( |
| 371 | + nums, |
| 372 | + n - 1, |
| 373 | + i + 1, |
| 374 | + target - nums[i] |
| 375 | + ); |
| 376 | + for (let j = 0; j < subRes.length; j++) { |
| 377 | + res.push([nums[i], ...subRes[j]]); |
| 378 | + } |
| 379 | + // 跳过相同元素 |
| 380 | + while (nums[i] === nums[i + 1]) i++; |
| 381 | + } |
| 382 | + } |
| 383 | + return res; |
| 384 | + } |
| 385 | + |
| 386 | + function towSumTarget(nums, start, target) { |
| 387 | + // 前提:nums要先排序好 |
| 388 | + let res = []; |
| 389 | + let len = nums.length; |
| 390 | + let left = start; |
| 391 | + let right = len - 1; |
| 392 | + while (left < right) { |
| 393 | + let sum = nums[left] + nums[right]; |
| 394 | + if (sum < target) { |
| 395 | + while (nums[left] === nums[left + 1]) left++; |
| 396 | + left++; |
| 397 | + } else if (sum > target) { |
| 398 | + while (nums[right] === nums[right - 1]) right--; |
| 399 | + right--; |
| 400 | + } else { |
| 401 | + // 相等 |
| 402 | + res.push([nums[left], nums[right]]); |
| 403 | + // 跳过相同元素 |
| 404 | + while (nums[left] === nums[left + 1]) left++; |
| 405 | + while (nums[right] === nums[right - 1]) right--; |
| 406 | + left++; |
| 407 | + right--; |
| 408 | + } |
| 409 | + } |
| 410 | + return res; |
| 411 | + } |
| 412 | + nums.sort((a, b) => a - b); |
| 413 | + // n = 3,此时求3sum之和 |
| 414 | + return nSumTarget(nums, 3, 0, 0); |
| 415 | +}; |
| 416 | +``` |
| 417 | + |
348 | 418 | TypeScript:
|
349 | 419 |
|
350 | 420 | ```typescript
|
@@ -616,6 +686,49 @@ public class Solution
|
616 | 686 | }
|
617 | 687 | }
|
618 | 688 | ```
|
619 |
| - |
| 689 | +Scala: |
| 690 | +```scala |
| 691 | +object Solution { |
| 692 | + // 导包 |
| 693 | + import scala.collection.mutable.ListBuffer |
| 694 | + import scala.util.control.Breaks.{break, breakable} |
| 695 | + |
| 696 | + def threeSum(nums: Array[Int]): List[List[Int]] = { |
| 697 | + // 定义结果集,最后需要转换为List |
| 698 | + val res = ListBuffer[List[Int]]() |
| 699 | + val nums_tmp = nums.sorted // 对nums进行排序 |
| 700 | + for (i <- nums_tmp.indices) { |
| 701 | + // 如果要排的第一个数字大于0,直接返回结果 |
| 702 | + if (nums_tmp(i) > 0) { |
| 703 | + return res.toList |
| 704 | + } |
| 705 | + // 如果i大于0并且和前一个数字重复,则跳过本次循环,相当于continue |
| 706 | + breakable { |
| 707 | + if (i > 0 && nums_tmp(i) == nums_tmp(i - 1)) { |
| 708 | + break |
| 709 | + } else { |
| 710 | + var left = i + 1 |
| 711 | + var right = nums_tmp.length - 1 |
| 712 | + while (left < right) { |
| 713 | + var sum = nums_tmp(i) + nums_tmp(left) + nums_tmp(right) // 求三数之和 |
| 714 | + if (sum < 0) left += 1 |
| 715 | + else if (sum > 0) right -= 1 |
| 716 | + else { |
| 717 | + res += List(nums_tmp(i), nums_tmp(left), nums_tmp(right)) // 如果等于0 添加进结果集 |
| 718 | + // 为了避免重复,对left和right进行移动 |
| 719 | + while (left < right && nums_tmp(left) == nums_tmp(left + 1)) left += 1 |
| 720 | + while (left < right && nums_tmp(right) == nums_tmp(right - 1)) right -= 1 |
| 721 | + left += 1 |
| 722 | + right -= 1 |
| 723 | + } |
| 724 | + } |
| 725 | + } |
| 726 | + } |
| 727 | + } |
| 728 | + // 最终返回需要转换为List,return关键字可以省略 |
| 729 | + res.toList |
| 730 | + } |
| 731 | +} |
| 732 | +``` |
620 | 733 | -----------------------
|
621 | 734 | <div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
0 commit comments