1. 程式人生 > >LeetCode第15題 三數之和

LeetCode第15題 三數之和

i++ while 剪枝 right ger 超時 分析 leetcode 復雜度

/*

給定一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重復的三元組。

註意:答案中不可以包含重復的三元組。

例如, 給定數組 nums = [-1, 0, 1, 2, -1, -4],

滿足要求的三元組集合為:
[
[-1, 0, 1],
[-1, -1, 2]
]
*/


/*
思路: 首先想到的肯定是窮舉,時間復雜度為O(n^3) , 但如果使用這種方法,也實在稱不上算法題了,果不其然,超時.

[-1, 0, 1, 2, -1, -4] 對於這個數組,可以先固定一個數,然後判斷其他2個數的和是否與這個數相反,如果
相反,自然就是一個解.
      ****先排序****
首先固定一個數,這個題中,從下標i=0開始,一直到length - 3.(因為固定的這個數右面起碼有2個位置留給另外2個數用於求和的.)
另外兩個數分別從 pos = i+1,和pos = length - 1 開始,向中間遍歷,求和sum,分析和.
1.如果sum與固定的數剛好相反,加入到解中。但也要考慮到去重的問題:如果這個數和接下來的數相同,就跳過
2.如果sum大於固定的數,就讓sum變小 , right++
3.如果sum小於固定的數,就讓sum變大 , left++
時間復雜度為O(n^2)

*/

 1 class Solution15 {
 2 
 3   public List<List<Integer>> threeSum(int[] nums) {
 4     List<List<Integer>> res = new ArrayList<>();
 5     if (nums == null || nums.length < 3) {
 6       return res;
 7     }
 8     Arrays.sort(nums);
 9     for (int i = 0; i < nums.length - 2; i++) {
10 if (i > 0 && nums[i] == nums[i - 1]) { //剪枝,如果這一步不進行剪枝,會產生重復解 11 continue; 12 } 13 if (nums[i] > 0) { 14 break; 15 } 16 int left = i + 1; 17 int right = nums.length - 1; 18 while (left < right) { 19 int sum = nums[left] + nums[right];
20 if (sum + nums[i] == 0) { //加入到解中,並剪枝(while),如果這一步不進行剪枝,會產生重復解 21 res.add(Arrays.asList(nums[i], nums[left], nums[right])); 22 while (left < right && nums[left] == nums[left + 1]) { 23 ++left; 24 } 25 while (right > left && nums[right] == nums[right - 1]) { 26 --right; 27 } 28 ++left; 29 --right; 30 } else if (sum + nums[i] < 0) { //如果和小於0,讓和變大一些 31 ++left; 32 } else { //如果和大於0,讓和變小一些 33 --right; 34 } 35 } 36 } 37 return res; 38 } 39 }

LeetCode第15題 三數之和