LeetCode 41. First Missing Positive
這個題目雖然是Hard,但是隻要想到解法之後,就很簡單了。
題目要求:找到最小的、沒有出現在陣列中的整數,陣列未排序。
初看起來,這個至少得排個序才能搞定。但是題目說了,時間複雜度O(n),空間複雜度O(1)。
如果能把數字n填寫到第n-1個,那不就能在O(n)時間內看出來缺失數字了嗎?把數字n填寫到第n-1個,完全就是遍歷一遍所有的數字就可以了啊。
思路就這樣出來了:
- 遍歷所有數字,將數字n放到第n-1個位
- 遍歷陣列,第一個不滿足nums[i]!=i+1的i+1即為缺失的數字
程式碼如下:
class Solution { public int firstMissingPositive(int[] nums) { for (int i = 0; i < nums.length;) { if (nums[i] > 0 && nums[i] <= nums.length) { if (nums[nums[i] - 1] == nums[i]) { // 兩者相等就沒有必要交換了,next i++; continue; } int tmp = nums[nums[i] - 1]; nums[nums[i] - 1] = nums[i]; nums[i] = tmp; // 交換完成之後,我們並不能確保當前的nums[i]在該在的位置上了 // 所以不能貿然處理下一個 // 這是一個坑 } if (nums[i] <= 0 || nums[i] > nums.length || nums[i] == i + 1) { // 要麼這個數字不在0-n內,要麼這個數字已經在該在的位置上了 // 總而言之,next i++; } } for (int i = 0; i < nums.length; i++) { if (nums[i] != i + 1) { // 所有在範圍內的數字都已經到對應位置了 // 但這個位置沒有對應的數字,所以這個數字是缺失了的 return i + 1; } } // 從0-n都有,所以缺失了n+1 return nums.length + 1; } }
第一個for迴圈,雖然i並不一定在每次迴圈的時候遞增,但是總的時間複雜度還是O(n):
對於所有的數字,要不交換到對應位置,要麼不交換:即O(n)。