15. 三數之和
比較容易想到的就是,求三數之和等於0,可以等價於求兩個數的和,然後看這個和的相反數是否在nums
裡面。
但是 t_t這樣的話複雜度太高了,會超時,捂臉,最後三個case,怎麼改都超時……
bool find(vector
nums, int nums_sz, int target, int m, int n)
return
false;
}vector
> threesum(vector
& nums) }}
int s_sz = s.size();
for (set
>::iterator it = s.begin(); it != s.end(); it++)
return res;
}
最後沒辦法去網上找了下人家的sol,還有這篇(沒有優化),發現是我之前的思路不夠好,而且沒有優化到很好的地步。
總體思路是先排序(從小到大),然後以每乙個數為起始,在它的右邊不斷縮小範圍看是否有符合條件的數。
首先需要將原陣列排序,這裡可以用c++的sort介面就行:sort(nums.begin(), nums.end());
這麼排序我覺得個好處是當找到滿足條件的三元組時,不需要判斷結果的二維vector中是否已經包含了當前要放進去的子陣列;
然後對於當前的數nums[i]
,在他的右邊用下標left
和right
進行縮小範圍的遍歷;
如果sum = nums[i] + nums[left] + nums[right]; > 0
,那麼說明nums[right]
大了,因此right--
;如果sum<0
,那麼說明nums[left]
小了,因此left++
;
1-3為基本的想法,然後在此之上還要有優化,跳過一些不必要的迴圈,還有提前退出(見**)
// 優化2: 當nums[i] > 0 ,那麼nums[i]加上後面的比它大的兩個數肯定也大於0,甚至是後面的數([i+1], [i+2]……)作為起始數時肯定也大於0(陣列已經排過序),
// 因此可以跳過;
// 當 nums[i] + nums[left] + nums[left+1]>0,說明nums[i]與後面的範圍中任取兩個數並且這兩個數是最小值,他們的和都大於0,後面的數([i+1], [i+2]……)作為起始數時sum也大於0,
// 因此也可以跳過;
if (nums[i] > 0 || (nums[i] + nums[left] + nums[left+1])>0)
// 優化3: 當nums[i] + nums[right] + nums[right - 1] < 0時,說明nums[i]與後面的範圍中任取兩個數並且這兩個數是最大值,得到的sum < 0,說明nums[i]這個起始數選小了
// 因此跳過進入下一層迴圈;
if (nums[i] + nums[right] + nums[right - 1] < 0)
while (left < right)
while (left < right && nums[right] == nums[right + 1])
tmp.clear();
tmp.resize(num);
}else
if (sum < 0)
}else
if (sum > 0)}}
}return res;
}以後做題一定要多想想有沒有更好的辦法,還得多注意下能不能優化的。切記切記!
LeetCode 15 三數之和
15.給定乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c 使得 a b c 0 找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組 方法一,個人解法正確,但是效率太低,時間複雜度o n 3 時間超時,無法提交至leetcode public s...
leetcode 15 三數之和
給定乙個包含 n 個整數的陣列nums,判斷nums中是否存在三個元素 a,b,c 使得 a b c 0 找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組。例如,給定陣列 nums 1,0,1,2,1,4 滿足要求的三元組集合為 1,0,1 1,1,2 class solutio...
leetcode15 三數之和
給定乙個包含 n 個整數的陣列nums,判斷nums中是否存在三個元素 a,b,c 使得 a b c 0 找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組。例如,給定陣列 nums 1,0,1,2,1,4 滿足要求的三元組集合為 1,0,1 1,1,2 先找兩數之和,然後再用un...