本題源自leetcode 442
給定一個整數數組 a,其中1 ≤ a[i] ≤ n (n爲數組長度), 其中有些元素出現兩次而其他元素出現一次。
找到所有出現兩次的元素。
你可以不用到任何額外空間並在O(n)時間複雜度內解決這個問題嗎?
示例:
輸入:
[4,3,2,7,8,2,3,1]
輸出:
[2,3]
第一種,遍歷整個數組,將數組中的i插入i-1的位置,然後遍歷數組,如果nums[i]!=i+1也就是nums[i]本身,輸出
時間複雜度O(2n)~O(n)
var findDuplicates = function(nums) {
for(let i = 0;i<nums.length;){
if(nums[i]!== nums[nums[i] - 1]){
const c = nums[i];
nums[i] = nums[c-1];
nums[c-1] = c;
}else{
i++
}
}
const res = [];
for(let i = 0; i < nums.length; i++){
if(nums[i] !== i+1)
res.push(nums[i]);
}
return res;
};
//[7,3,2,4,8,2,3,1] i = 0
//[2,3,2,4,8,7,3,1] i = 0
//[3,2,3,4,8,2,7,1] i = 0 a[0] === a[2] i+1
//[3,2,3,4,8,2,7,1] i = 1 a[1] === a[1] i++
//[3,2,3,4,8,2,7,1] i = 2 a[2] === a[2] i++
//[3,2,3,4,8,2,7,1] i = 3 a[3] === a[4-1] i++
//[3,2,3,4,8,2,7,1] i = 4 a[4] !== a[8-1]
//[3,2,3,4,1,2,7,8] i = 4 a[4] !== a[1-1]
//[1,2,3,4,3,2,7,8] i = 4 a[4] ===a[3-1] i++
//[1,2,3,4,3,2,7,8] i = 5 a[5] ===a[2-1] i++
//[1,2,3,4,3,2,7,8] i = 7 a[7] ===a[7-1]
第二種,nums[i] 的絕對值作爲角標,如果nums[nums[i]]>0,取nums[nums[i]]爲相反數,這樣訪問過的數nums[nums[i]]變成負數,當遇到相同的數時,nums[nums[i]]會去訪問 nums[i]的絕對值,就會找到已經置爲相反數,此時爲負數。然後就可以將nums[i]添加進入重複的數中
let result = [];
for (let i = 0; i < nums.length; i++) {
let num = Math.abs(nums[i]);
if (nums[num - 1] > 0) {
nums[num - 1] *= -1;
} else {
result.push(num);
}
}
//let nums = [4,3,2,7,8,2,3,3,1]
//[4,3,2,-7,8,2,3,3,1]
//[4,3,2,-7,8,2,3,3,1]
//[4,3,-2,-7,8,2,3,3,1]
//[4,-3,-2,-7,8,2,3,3,1] nums[7-1]
//[4,-3,-2,-7,8,2,3,-3,1]
//[4,-3,-2,-7,8,2,3,-3,-1] i=4 nums[8-1]
//[4,-3,-2,-7,8,2,3,-3,-1] i=5 nums[2-1] nums[1] = -3 res[2]
//[4,-3,-2,-7,8,2,3,-3,-1] i=6 nums[3-1] nums[2] = -2 res[2,3]
//[4,-3,-2,-7,8,2,3,-3,-1] i=7 nums[3-1] nums[2] = -2 res[2,3,3]
//[4,-3,-2,-7,8,2,3,-3,-1] i=8 nums[1-1] nums[0] = 4 res[2,3,3]
以上方案都是針對,數據最多隻出現兩次,若出現三次,返回的結果就會重複。
找出數組中重複的數字。
在一個長度爲 n 的數組 nums 裏的所有數字都在 0~n-1 的範圍內。數組中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出數組中任意一個重複的數字。
示例 1:
輸入:
[2, 3, 1, 0, 2, 5, 3]
輸出:2 或 3
限制:
2 <= n <= 100000
鴿巢原理/抽屜原理
你有11個蘋果,需要放進10個抽屜,勢必會有一個抽屜出現一個以上的蘋果。
還是將i放進i的角標的空間裏
var findRepeatNumber = function(nums) {
for(let i = 0;i<nums.length;i++){
while(nums[i]!==i){
if(nums[nums[i]] !== nums[i]){
const temp = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = temp;
}else{
return nums[i]
}
}
}
return -1;
};
//let arr = [0, 1, 2, 3, 4, 11, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
// [0, 1, 2, 3, 4, 11, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] i = 0,1,2,3,4
// [0, 1, 2, 3, 4, 11, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] i = 5 nums[5] = 11 nums[11]===nums[5] return nums[11]
let arr = [0, 1, 2, 3, 4, 11, 6, 7, 8, 9, 10, 12, 11, 13, 14, 15];
// [0, 1, 2, 3, 4, 11, 6, 7, 8, 9, 10, 12, 11, 13, 14, 15] i = 0,1,2,3,4
// [0, 1, 2, 3, 4, 11, 6, 7, 8, 9, 10, 12, 11, 13, 14, 15] i = 5 nums[5] = 11 nums[11]!==nums[5] 交換
// [0, 1, 2, 3, 4, 12, 6, 7, 8, 9, 10, 11, 11, 13, 14, 15] i = 6 nums[6]=6,7,8,9,10,11
// [0, 1, 2, 3, 4, 12, 6, 7, 8, 9, 10, 11, 11, 13, 14, 15] i = 12 nums[12] = 11 nums[11] === nums[12] return nus[11]