點擊關注上方“五分鐘學算法”,
設爲“置頂或星標”,一起成長
今天分享的題目來源於 LeetCode 上的劍指 Offer 系列 面試題03. 數組中重複的數字。
題目鏈接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/
一、題目描述
找出數組中重複的數字。
在一個長度爲 n 的數組 nums 裏的所有數字都在 0~n-1 的範圍內。數組中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出數組中任意一個重複的數字。
示例 1:
輸入:
[2, 3, 1, 0, 2, 5, 3]
輸出:2 或 3
限制:
2 <= n <= 100000
二、題目解析
注意題目描述:一個長度爲 n 的數組 nums 裏的所有數字都在 0~n-1 的 範圍內,這個 範圍 恰好與數組的下標可以一一對應。
所以我們可以執行某種操作,使索引與值一一對應,即索引 0 的值爲 0,索引 1 的值爲 1。而一旦某個索引的值不只一個,則找到了重複的數字,也即發生了 哈希衝突。
三、動畫描述
四、圖片描述
五、參考代碼
class Solution {
public int findRepeatNumber(int[] nums) {
//設索引初始值爲 i = 0
int i = 0;
//遍歷整個數組 nums
while(i < nums.length) {
//索引 i 的值爲 i,無需執行交換操作,查看下一位
if(nums[i] == i) {
i++;
continue;
}
//索引 nums[i] 處的值也爲 nums[i],即找到一組相同值,返回 nums[i] 即可
if(nums[nums[i]] == nums[i]) return nums[i];
//執行交換操作,目的是爲了使索引與值一一對應,即索引 0 的值爲 0,索引 1 的值爲 1
int tmp = nums[i];
nums[i] = nums[tmp];
nums[tmp] = tmp;
}
//如果遍歷整個數組都沒有找到相同的值,返回 -1
return -1;
}
}
六、複雜度分析
時間複雜度
遍歷數組需要 O(N) 時間。
注意參考代碼裏面的關鍵字 continue,這表示在 while
的一次循環裏面,只有這次循環將 索引(i) 與 索引值(num[i]) 匹配到了,纔會執行下一次循環。
在每一次的循環過程中,索引(i) 與 索引值(num[i]) 匹配到後,在後續的循環過程中不會操作它們,所以雖然一開始的循環過程中,執行的交換操作較多,但在後續的循環過程中根本不需要再執行操作了。
根據均攤複雜度分析 ,總的時間複雜度爲 O(N) ,N 爲數組的長度。
空間複雜度
使用常數複雜度的額外空間,爲 O(1)。
七、相關標籤
數組
哈希
原地哈希
推薦閱讀
• C++是如何從代碼到遊戲的?• 告訴你一個學習編程的訣竅(建議收藏)• 自學編程的八大誤區!克服它!• 新手如何有效的刷算法題(LeetCode)• 10款VS Code插件神器,第7款超級實用!• 在拼多多上班,是一種什麼樣的體驗?我tm心態崩了呀!• 寫給小白,從零開始擁有一個酷炫上線的網站!
歡迎關注我的公衆號“五分鐘學算法”,如果喜歡,麻煩點一下“在看”~