1. 程式人生 > >leetcode -- 15. 3Sum 【問題轉化2sum + 避免重複計算的方法(規定次序)】

leetcode -- 15. 3Sum 【問題轉化2sum + 避免重複計算的方法(規定次序)】

題目

Given an array S of n integers, are there elements abc in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

題意

在給定的陣列S中尋找3個數的和為0的情況。

分析及解答

  • 【轉化】 將 3sum 轉化為2sum的問題進行處理,即 固定一個 數,然後去按照2sum的方式進行處理。
  • 【避免重複計算】為了避免一些不必要的元素重複加入到結果集中,我們需要適當的限定遍歷的次序。(程式碼中標號3的註釋部分)

程式碼

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
     
        //1.排序。
    	Arrays.sort(nums);
    	//2.選取c(不同於上次所選),然後 尋找a,b 滿足 a + b = -c。
    	//3.a,b,c記錄放入的集合S.(如何做到不重複放入呢?規定次序:只能在c的右邊空間中尋找)
    	List<List<Integer>> results = new ArrayList<>();
    	int c = 0;
    	for(int i = 0 ; i < nums.length ; i++){
    		if(i == 0){
    			c = nums[i];
    		}else if(nums[i] == c){
    			continue;
    		}else{
    			c = nums[i];
    		}
    		
    		for(int p1 = i+1,p2= nums.length -1 ;p1 < p2;){
    			if(nums[p1] + nums[p2] + c == 0){
    				//加入結果集中。
    				List<Integer> result = new ArrayList<>(3);
    				result.add(c);
    				result.add(nums[p1]);
    				result.add(nums[p2]);
    				results.add(result);
    				while(p1 < p2 && nums[p1] == nums[++p1]){ // 這裡出現了一些bug,注意。
    				}
    				while(p1 < p2 && nums[p2] == nums[--p2]){
    				}
    			}else if(nums[p1] + nums[p2] + c < 0){
    				p1++;
    				
    			}else if(nums[p1] + nums[p2] + c > 0){
    				p2--;
    			}
    		}
    	}
    	return results;
    }
}