Given an integer array nums of length n where all the integers of nums are in the range [1, n] and each integer appears once or twice, return an array of all the integers that appears twice.
You must write an algorithm that runs in O(n) time and uses only constant auxiliary space, excluding the space needed to store the output.
給定一個長度為 n 的整數陣列 nums,在此陣列nums中所有的整數都在 [1, n] 的範圍內,且每個整數都有可能出現一次或兩次,請回傳一個陣列其包含了所有出現兩次的整數。
你必須寫一個算法其時間複雜度為 O(n) ,且只能只用常數的輔助空間,不包含儲存輸出的所需空間。
(意思就是可以把要結果利用新的陣列回傳,但是在搜尋陣列nums中重覆出現的正整數時,必須使用in-place(原地)進行處理。
其實這題跟昨天的題目處理方式一樣,也是使用Cyclic Sort(循環排序法),講到這我現在才發現,昨天的文章標題竟然把題目名稱寫錯了,昨天的題目應該是 Leetcode 41. First Missing Positive
啊!在這邊更正一下!
寫到這題,我發現其實跟Cyclic Sort(循環排序法)相關的題目,難不是難在要應用或實現Cyclic Sort(循環排序法),而是難在要去想到可以使用Cyclic Sort(循環排序法)解題,基本上只要解題時思路方向有正確導向Cyclic Sort(循環排序法),離後面解題就不遠了。
解題思路
上一題要找不存在的最小正整數,而這一題要找重覆出現兩次的整數,題目很佛心,一開始就告訴你陣列nums中所有的整數都 大於1 且 最多出現兩次。所以,只要使用Cyclic Sort(循環排序法)把各整數放到對應的索引位置後,再把跟索引值不同的整數「揪」出來(表示他肯定已經出現過了),回傳就大功告成了!
步驟
程式碼
var findDuplicates = function(nums) {
for (let i = 0; i < nums.length; i++){
let correctIndex = nums[i] - 1;
if (nums[i] !== nums[correctIndex] ){
[nums[i], nums[correctIndex]] = [nums[correctIndex], nums[i]];
i--; //只交換一次有可能還是沒有交換到正確的位置上,所以要先i - 1,反覆交換到正確的位置上為止
}
}
let res = [];
for (let i = 0; i < nums.length; i++){
if (nums[i] !== i + 1){
res.push(nums[i]);
}
}
return res;
};