每天一道LeetCode-----找到序列中第一个没有出现的正整数,要求时间复杂度是O(n),空间复杂度是O(1)
First Missing Positive
原題鏈接First Missing Positive
給定一個序列,找到第一個沒有出現的正整數,要求復雜度是O(n),空間復雜度為O(1)。
這種時間復雜度要求是O(n)的問題一般都是遍歷一遍出結果,但是遍歷一遍的代價是需要使用額外的空間記錄某些信息以達到解決問題的目的,但是這里不可以使用額外的空間。既然不可以,但又非要不可,那么只能用源序列作為記錄的空間。
也就是,在遍歷的過程中修改原序列。
對于數組(vector)而言,有什么方法可以記錄數值大小這種信息呢?下標。
對于某個大于0的元素n,只需要將它放在下標為n-1的位置(考慮到可能越界,所以放到n-1),那么當下次遍歷到第n-1的位置時,直接判斷nums[n-1]和n是否相等,就可以得知在源序列中是否出現過n這個數值。
但是有一點,假設數值n當前的下標為i,那么需要把數值n放到下標為n-1的位置,也就是和nums[n-1]交換位置。此時,數值n已經被放到了下標n-1的位置,位置關系為nums[n-1] == n,nums[i] = m(m是以前在n-1位置的數值)。接著,因為也需要給m找對應的位置,所以仍然從i開始,此時應該和nums[m-1]交換,就這么一直進行下去。最后,重新遍歷一遍序列,第一個不滿足nums[n] == n + 1的位置所代表的數值就是缺少的值。
代碼如下
class Solution { public:int firstMissingPositive(vector<int>& nums) {/* 對每個位置上的大于0的數值都找到對應的位置 */for(int i = 0; i < nums.size(); ++i){/* 如果不滿足n == nums[n - 1],就說明n這個數值沒有放到應該放的位置 *//* 這里要防止越界,通常這種情況說明數組個數比較少,但是元素大小比較大,缺少較小的那些數值 */while(nums[i] > 0 && nums[i] - 1 < nums.size() && nums[i] != nums[nums[i] - 1])swap(nums[i], nums[nums[i] - 1]);}/* 找到第一個不符合位置關系的數值 */for(int i = 0; i < nums.size(); ++i){if(nums[i] != i + 1)return i + 1;}/* 如果都滿足,那么返回下一個數值 */return nums.size() + 1;} };這題主要利用了用下標表示數值的方法,同時利用原數組避免內存開銷,這兩點都是需要注意的地方。
總結
以上是生活随笔為你收集整理的每天一道LeetCode-----找到序列中第一个没有出现的正整数,要求时间复杂度是O(n),空间复杂度是O(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每天一道LeetCode-----找到给
- 下一篇: 每天一道LeetCode-----给定大