【回溯】B059_LC_三數之和(雙指針 + 二分思想)

一、Problem

Given an array nums of n integers, are there elements a, b, c in nums 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.

Given array nums = [-1, 0, 1, 2, -1, -4],

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

二、Solution

嘗試一:雙指針

生套滑窗是不行的,因爲窗口中的數字有可能被重用。

class Solution {
    public List<List<Integer>> threeSum(int[] a) {
    	Set<List<Integer>> st = new HashSet<>();
    	int n = a.length, l = 0, r = 0, sum = 0;
    	LinkedList<Integer> cur = new LinkedList<>();
    	while (r < n) {
            sum += a[r];
            cur.add(a[r]);
    		r++;
    		while (sum == 0) {
    			st.add(new ArrayList(cur));
    			sum -= a[l];
    			l++;
                cur.pollFirst();
    		}
    	}
        List<List<Integer>> ans = new LinkedList<>();
        for (List<Integer> b : st) {
            ans.add(b);
        }
    	return ans;
    }
}

這題沒有對答案的數字數字要求爲按照 nums 中的數字順序,所以可以用排序來簡化去重操作。


方法二:排序 + 二分思想

  • 選定一個頂點 ii,再選定一個需要枚舉的區間 [l,r][l, r]
  • 在區間中,我們需要考慮:
    • 三數之和 sum 的值:大於 0、小於 0、等於 0
      • 等於 0:如果當前窗口的兩端的相鄰元素是相同的,那麼這些元素構成的子集會產生重複,所以這些重複數不可要。
      • 大於 0:要讓 sum 變小,只能讓 rr 向左移動。
      • 小於 0:要讓 sum 變大,只能讓 ll 向右移動。
class Solution {
    public List<List<Integer>> threeSum(int[] a) {
    	Arrays.sort(a);
    	List<List<Integer>> ans = new LinkedList<>();
    	int n = a.length;

    	for (int i = 0; i < n; i++) {
            if (a[i] > 0)
                break;
    		if (i > 0 && a[i-1] == a[i])
    			continue;
    		int l = i + 1, r = n - 1;
    		while (l < r) {
    			int sum = a[i] + a[l] + a[r];
    			if (sum == 0) {
    				ans.add(Arrays.asList(a[i], a[l], a[r]));
    				while (l < r && a[l] == a[l+1]) l++;
    				while (l < r && a[r] == a[r-1]) r--;
                    l++; r--;
    			}else if (sum < 0) l++;
    			 else              r--;
    		}
    	}
    	return ans;
    }
}

複雜度分析

  • 時間複雜度:O(n2)O(n^2)
  • 空間複雜度:O(1)O(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章