一、題目
給定一個整數陣列 a,其中1 ≤ a[i] ≤ n (n為陣列長度), 其中有些元素出現兩次而其他元素出現一次。
找到所有出現兩次的元素。
你可以不用到任何額外空間並在O(n)時間複雜度內解決這個問題嗎?
示例:
輸入:
[4,3,2,7,8,2,3,1]
輸出:
[2,3]
二、題解
- 解法1:雜湊表
遍歷給定陣列時,可以檢視該元素是否存在於雜湊表中,若不存在,則將該元素存到雜湊表中,反之則是重複的元素。
但這個方法用到了額外空間,所以看看就好咯。
時間複雜度:O(n),空間複雜度:O(n)
func findDuplicates(nums []int) []int {
len := len(nums);
if len <= 1 {
return nil
}
hashMap := make(map[int]int)
result := []int{}
for _, v := range nums {
_, exist := hashMap[v];
if (exist) {
result = append(result, v)
} else {
hashMap[v] = v
}
}
return result
}
- 解法2:交換法——原地雜湊
因為題目說了,陣列裡的所有數字都在 1 ~ n 的範圍內(n是陣列長度),但陣列的下標是從 0 開始,所以可以遍歷陣列,使陣列的索引和值建立對應的關係,也就是索引為 0 時,值為 1,索引為 1 時,值為 2,以此類推。
遍歷元素時,
當 a[i] != i+1 時,就將位置 i 和 a[i]-1 上的兩個值交換,反之則 i 移動到下一位。
當 a[i] == a[a[i]-1]時,表示 a[i] 有重複,記錄重複數字,並把下標 i 上的數字置為 0。
當 i 上的數字是 0 時,i++
遍歷到陣列末尾,結束?
時間複雜度:O(n),空間複雜度:O(1)
func findDuplicates(nums []int) []int {
len := len(nums)
if len <= 1 {
return nil
}
result := []int{}
i := 0
for i < len {
if i == nums[i] - 1 || nums[i] == 0{
i++
continue
}
if nums[i] == nums[nums[i] - 1] {
result = append(result, nums[i])
nums[i] = 0
i++
} else {
nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]
}
}
sort.Ints(result)
return result
}