三數之和
題目鏈接三數之和
兩數之和思路
這道題我們先想兩數之和怎麼做呢?兩數相加等於0,兩重for循環暴力解答。怎麼樣可以更快一點呢?可以用哈希把時間複雜度從O(n^2)轉爲O(n)。先把每個元素想要的target值存入哈希表中,複雜度爲O(n),再用一個O(n)的時間複雜度從哈希表中查找即可。
三數之和思路
還是運用雙指針的思想,這回不是快慢指針的思想了。
- 首先考慮數組長度小於3的,直接返回null
- 對數組進行排序
- 遍歷排序後的數組
當前nums[i]>0,後面的數就都大於0了,於是直接break;
跳過重複元素,避免重複解
令左指針=i+1,右指針=n-1,在L<R的情況下進行循環
nums[i]+nums[L]+nums[R]==0時,判斷L++和R–是否和之前的一樣,不同的話就返回
如果nums[i]+nums[L]+nums[R]>0,則右指針的值太大,R–
如果nums[i]+nums[L]+nums[R]<0,則左指針的值太小,L++
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
if (nums.size()<3) return ans;
sort(nums.begin(), nums.end());
if (nums[0]>0) return ans;
int i = 0;
while (i<nums.size()) {
int left = i + 1, right = nums.size() - 1;
while (left< right) {
if (nums[i]>0) break;
// 轉換爲long long避免加法過程中溢出
long long y = static_cast<long long>(nums[i]);
long long x = static_cast<long long>(nums[left]);
long long z = static_cast<long long>(nums[right]);
if (x + y >0 - z)
right--;
else if (x + y <0 - z)
left++;
else {
ans.push_back({ nums[i], nums[left], nums[right] });
// 相同的left和right不應該再次出現,因此跳過
while (left<right&&nums[left] == nums[left + 1])
left++;
while (left<right&&nums[right] == nums[right - 1])
right--;
left++;
right--;
}
}
// 避免nums[i]作爲第一個數重複出現
while (i + 1<nums.size() && nums[i] == nums[i + 1])
i++;
i++;
}
return ans;
}
};
啓發是對數組進行排序,就可以根據和來調整左右指針了,並且對正值後面都不用判斷了省了不少時間!