1. 程式人生 > >leetcode 第15題 3Sum

leetcode 第15題 3Sum

        這個題我主要是卡在了兩個地方,我首先想到的是先固定兩個數字,然後再去遍歷最後一個數字尋找符合條件的陣列,後來發現這種方法有點複雜,有一種方法比較的巧妙,程式碼中也是用到了這種思想,其實,我也想到了一點點,就是採用兩頭夾逼得方式進行遍歷,但是想了想這些數又毫無順序,然後就沒有繼續思考了,這種方法的巧妙之處就在於它首先將數的大小進行排序然後進行遍歷,厲害吧~

        主要思路如下:

1、先升序排序,這裡可以直接使用vector容器中的sort函式,然後從頭開始遍歷確定第一個數字,這是第一重迴圈;

2、在第二重迴圈中,第二個數和第三個數分別從陣列兩端往中間夾逼,再次注意,現在這個陣列中的數字是升序排列的:

       如果三個數相加正好等於零,符合題目要求,輸出即可;

       如果三個數相加小於零,說明第二個數字小了,將第二個數字右移;

       如果三個數相加大於零,說明第三個數字大了,將第三個數字左移。

3、需要注意的是,這裡面會有重複的數字,可以通過判斷是否有重複的數字來跳過重複元素。網上說還可以用map來實現,我並沒有看懂,懂的大神能否實現一下呢~

4、它的時間複雜度是O(n^2)。

class Solution{
public:
    vector<vector<int>> threeSum(vector<int>& nums){
		vector<vector<int>> ret;
		int size = nums.size();
		sort(nums.begin(), nums.end());
		for(int i = 0; i < size; i++){
			//skip same i
			while(i > 0 && i < size && nums[i] == nums[i-1])
				i++;
			int j = i + 1;
			int k = size - 1;
			while(j < k){
				int sum = nums[i] + nums[j] + nums[k];
                if(sum == 0){
					vector<int> cur(3);
					cur[0] = nums[i];
					cur[1] = nums[j];
					cur[2] = nums[k];
					ret.push_back(cur);
					j++;
					k--;
					//skip same j
					while(j<k && nums[j] == nums[j-1])
						j++;
					//skip same k
					while(k>j && nums[k] == nums[k+1])
						k--;
				}
                else if(sum < 0){
					j++;
					//skip same j
					while(j < k && nums[j] == nums[j-1])
						j++;
				}
                else{
					k--;
					//skip same k
					while(k > j && nums[k] == nums[k+1])
						k--;
				}				
			}
		}
		return ret;
	}
};