題目描述:
給定乙個未排序的整數陣列,找出其中沒有出現的最小的正整數。
示例 1:
輸入:[1
,2,0
]輸出:
3
示例 2:
輸入:[3
,4,-
1,1]
輸出:2
示例 3:
輸入:[7
,8,9
,11,12
]輸出:
1
方法 1:索引作為雜湊表。
資料預處理
首先我們可以不考慮負數和零,因為不需要考慮。同樣可以不考慮大於 n 的數字,
因為首次缺失的正數一定小於或等於 n + 1 。
缺失的正數為 n + 1 的情況會單獨考慮。
為了不考慮這些數,又要保證時間複雜度為 o(n) ,因此
不能將這些元素彈出。我們可以將這些數用 1 替換。
為了確保缺失的第乙個正數不是 1,先要在這步操作前確定 1 是否存在。
如何實現就地演算法
現在我們有乙個只包含正數的陣列,範圍為 1 到 n,
現在的問題是在o(n) 的時間和常數空間內找出首次缺失的正數。
如果可以使用雜湊表,且雜湊表的對映是 正數 -> 是否存在 的話,這其實很簡單。
「髒工作環境」 的解決方法是將乙個字串 hash_str 分配 n 個 0,並且用類似於雜湊表的方法,如果在陣列**現數字 i 則將字串中 hash_str[i] 修改為 1 。
我們不使用這種方法,但是借鑑這種 使用索引作為雜湊鍵值 的想法。
最終的想法是 使用索引作為雜湊鍵 以及 元素的符號作為雜湊值 來實現是否存在的檢測。
例如,nums[2] 元素的負號意味著數字 2 出現在 nums 中。nums[3]元素的正號表示 3 沒有出現在 nums 中。
為了完成此操作,我們遍歷一遍陣列(該操作在資料預處理使得陣列中只有正數的操作後),檢查每個元素值 elem 以及將nums[elem] 元素的符號變為符號來表示數字 elem 出現在 nums 中。注意,當數字出現多次時需要保證符號只會變化 1 次。
演算法
現在可以開始寫演算法了。
檢查 1 是否存在於陣列中。如果沒有,則已經完成,1 即為答案。
如果 nums = [1],答案即為 2 。
將負數,零,和大於 n 的數替換為 1 。
遍歷陣列。當讀到數字 a 時,替換第 a 個元素的符號。
注意重複元素:只能改變一次符號。由於沒有下標 n ,使用下標 0 的元素儲存是否存在數字 n。
再次遍歷陣列。返回第乙個正數元素的下標。
如果 nums[0] > 0,則返回 n 。
如果之前的步驟中沒有發現 nums 中有正數元素,則返回n + 1。
**(官方題解,看不懂。。。)
class
solution}if
(contains==0)
return1;
if(n==1)
return2;
// 用 1 替換負數,0,
// 和大於 n 的數
// 在轉換以後,nums 只會包含
// 正數
for(
int i=
0;i)// 使用索引和數字符號作為檢查器
// 例如,如果 nums[1] 是負數表示在陣列**現了數字 `1`
// 如果 nums[2] 是正數 表示數字 2 沒有出現
for(
int i =
0; i < n; i++
)// 現在第乙個正數的下標
// 就是第乙個缺失的數
for(
int i =
1; i < n; i++)if
(nums[0]
>0)
return n;
return n +1;
}}
leetcode 41 缺失的第乙個正數
給定乙個未排序的整數陣列,找出其中沒有出現的最小的正整數。示例 1 輸入 1,2,0 輸出 3 示例 2 輸入 3,4,1,1 輸出 2 示例 3 輸入 7,8,9,11,12 輸出 1 說明 你的演算法的時間複雜度應為o n 並且只能使用常數級別的空間。題目規定了時間複雜度為o n 空間複雜度為常...
LeetCode 41 缺失的第乙個正數
給定乙個未排序的整數陣列,找出其中沒有出現的最小的正整數。示例 1 輸入 1 2,0 輸出 3示例 2 輸入 3 4,1,1 輸出 2示例 3 輸入 7 8,9 11,12 輸出 1說明 這題確實挺坑的,首先對陣列排個序,當時想用陣列標記的,沒想到還有int max級別的數,不過vector應該是裝...
Leetcode 41 缺失的第乙個正數
給定乙個未排序的整數陣列,找出其中沒有出現的最小的正整數。示例 1 輸入 1,2,0 輸出 3示例 2 輸入 3,4,1,1 輸出 2示例 3 輸入 7,8,9,11,12 輸出 1說明 你的演算法的時間複雜度應為o n 並且只能使用常數級別的空間。這個題第乙個想法是排序,然後遍歷即可,但是時間複雜...