你們好今天給你們分享下一道 LeetCode 中等難度 的題目 三數之和javascript
這裏主要是分享思路和註釋,供你們更好的理解題目解法,代碼部分是參考LeetCode 轉寫成javascript 代碼,前端
給你一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?請你找出全部和爲 0 且不重複的三元組。java
注意:答案中不能夠包含重複的三元組。算法
示例 1: 輸入:nums = [-1,0,1,2,-1,-4] 輸出:[[-1,-1,2],[-1,0,1]] 示例 2: 輸入:nums = [] 輸出:[] 示例 3: 輸入:nums = [0] 輸出:[] 複製代碼
1.爲了去重須要排序+使用Set數組
2.由於暴力法是3層迭代,時間複雜度是O(n^3),因此想辦法找到k同時減低複雜度是關鍵markdown
一種有三種解法網絡
1.暴力法 O(n^3)oop
2.Set值的方式減小時間複雜度,由於set查詢爲O(1)學習
3.雙指針內夾 O(n^2)ui
思路
1.三層遍歷數組 判斷每一種可能性
2.添加set 來防止重複
3.必定要排序,否則會統計到重複的數據
*/
var threeSum = function (nums) {
const set = new Set();
const res = [];
// 必定要排序 否則組合很差統計 例如 [[-1,0,1],[-1,2,-1],[0,1,-1]]
nums.sort((a, b) => a - b);
// 第一層能夠是 nums.length - 2, 由於給 j 和k 留2個位置,同理以下
for (let i = 0; i < nums.length - 2; i++) {
// 第二層的起點是 j=i+1,由於是題目不能同一個位置上的同一個元素不能選擇2次,同理以下
for (let j = i + 1; j < nums.length - 1; j++) {
for (let k = j + 1; k < nums.length; k++) {
const key = nums[i] + "_" + nums[j] + "_" + nums[k];
if (nums[i] + nums[k] + nums[j] === 0 && !set.has(key)) {
res.push([nums[i], nums[k], nums[j]]);
set.add(key);
}
}
}
}
return res;
};
/* 複雜度 時間 O(n^3) 空間 O(1) */
複製代碼
代碼借鑑 leetcode-cn.com/problems/3s…
1.排序 避免重複,
2.由於不能有重複的三元組,因此利用Set 來去重
3.採用遍歷的方式, 看下是否能獲取 三個元素相加爲0 的狀況
4.暴力法不一樣的地方在於, 再也不採用第三層遍歷,而是使用Set的方法來判斷是否存在 v= -nums[i] - nums[j],
由於set的查詢時間複雜度爲O(1) 因此總的複雜度爲O(n^2)
*/
var threeSum = function (nums) {
const res = [];
// 去重使用
const uniqueSet = new Set();
nums.sort((a, b) => a - b);
for (let i = 0; i < nums.length - 1; i++) {
// 存放 nums[j]的值
const set = new Set();
for (let j = i + 1; j < nums.length; j++) {
// 須要求得的值
const v = -nums[i] - nums[j];
// 三元數組的惟一標識,放入set中防止重複取值
const str = nums[i] + "_" + v + "_" + nums[j];
if (set.has(v) && !uniqueSet.has(str)) {
res.push([nums[i], v, nums[j]]);
uniqueSet.add(str);
} else {
set.add(nums[j]);
}
}
}
return res;
};
/* 複雜都 時間 O(n^2) 空間 O(n) */
複製代碼
代碼借鑑 leetcode-cn.com/problems/3s…
思路
1.排序防止重複
2.遍歷一次元素,獲取一個三個元素中的一個,nums[i],
3.再次遍歷一次數組,利用雙指針 左邊放置一個指針j 右邊放置一個指針k,往中間內夾
令 sum = nums[i]+nums[j]+nums[k],由於數組有序
若是sum>0 則左邊k對應的值大了 因此應該k--,若是sum<0 ,j--
*/
var threeSum = function (nums) {
const res = [];
// 老規矩 排序防止重複的狀況發生
nums.sort((a, b) => a - b);
// 遍歷
for (let i = 0; i < nums.length; i++) {
// 若是nums[i]都已經大於0了, 那麼其餘元素相加不可能再等於零 因此直接break
if (nums[i] > 0) break;
// 說明有重複, 可是不能判斷 nums[i]===nums[i+1]的時候就continue 由於會錯過元素例如(-1,-1,2) 這種狀況就會被錯過
if (i > 0 && nums[i - 1] === nums[i]) continue;
for (let j = i + 1, k = nums.length - 1; j < k; ) {
const sum = nums[i] + nums[j] + nums[k];
// 說明nums[k]大了, 因此須要k--
if (sum > 0) {
k--;
// 說明nums[j]小了, 因此須要j++
} else if (sum < 0) {
j++;
} else {
// 說明找到了答案了
res.push([nums[i], nums[j], nums[k]]);
while (j < k && nums[j] === nums[j + 1]) j++;
while (j < k && nums[k] === nums[k - 1]) k--;
j++;
k--;
}
}
}
return res;
};
/* 複雜度 時間 O(n^2) 空間 O(1) */
複製代碼
這道題 ,考察你們對雙指針 和 Set的理解,由於他們能夠很好的下降時間複雜度
你們能夠看看我分享的一個專欄(前端搞算法)裏面有更多關於算法的題目的分享,但願可以幫到你們,我會盡可能保持天天晚上更新,若是喜歡的麻煩幫我點個贊,十分感謝
文章內容目的在於學習討論與分享學習算法過程當中的心得體會,文中部分素材來源網絡,若有侵權,請聯繫刪除,郵箱 182450609@qq.com
今天頗有幸的去支持了下鴻星爾克和蜜雪冰城,不得不說爲中國的良心企業點贊,爲個人祖國感到驕傲,鄭州加油!河南加油!中國加油!