數組中未出現的最小正整數

數組中未出現的最小正整數

題目來源《程序員代碼面試指南》第八章

題目描述

給定一個無序數組arr,找到數組中未出現的最小正整數

arr = [-1, 2, 3, 4]。返回1

arr = [1, 2, 3, 4]。返回5

[要求]

時間複雜度爲O(N)O(N),空間複雜度爲O(1)O(1)

思路

理想情況:一個N長度的有序數組存放[1,2,...,N]這樣的數組,要找出缺少的最小正整數只需要從頭開始遍歷,發現data[l] != l + 1的即爲所求。

按照理想情況來推,在遍歷的過程中將數組恢復到[1,...,N]的理想情況

設置兩個變量lrl表示已經搜索到的正數範圍[1,l]r表示理想情況下能搜索到的最大範圍[1,r]。假設數組的長度爲N

l初始化爲0,因爲剛開始沒有正數,r初始化爲N,因爲一個N長度的數組,理想情況下存放[1,...,N]這樣N個正數。

假設遍歷到data[l]後,分情況討論:

  1. data[l] == l + 1,也就是按照理想情況這個數放置的位置是正確的,已知的正數範圍變爲[1,l]l++
  2. data[l] <= l,這種情況說明出現了數組裏已經出現過了該數或者負數和0,那麼r表示的範圍也需要縮小變爲r-1
  3. data[l] > r,這種情況說明數組裏出現了無效數據,理想情況下r表示的是[1,r]的範圍,但此時由於出現了無效數據(例如一個長度爲5的數組裏出現data[i]==79,那麼該數組的理想情況表示範圍變成了[1,4]),因此從原來的[1,r]變爲[1, r-1]。在減少r之前,首先需要把data[r]的數據拷貝到data[l]上做一次新的判斷(否則就漏了一個數)
  4. 如果data[data[l]-1] == data[l],說明數組中出現了重複數據,那麼r的表示範圍也需要縮小變爲r-1
  5. 上述情況都不屬於的情況下,說明這個數據是一個合理將ldata[l]-1(理想情況下的位置)中的數據交換

迭代停止的條件爲l == r,因此最後搜索到的能表示的正數範圍爲[1, l],所求的是未出現的最小正整數,即爲l+1

時間複雜度O(N)O(N),空間複雜度O(1)O(1)

示例

示例1

輸入爲: 3 5 1 4 2

l = 0r = 5

數組 l r data[l] 狀態
初始 [3, 5, 1, 4, 2] 0 5
[1, 5, 3, 4, 2] 0 5 3 swap(0, 2)
[1, 5, 3, 4, 2] 1 5 1 data[l] == l+1
[1, 2, 3, 4, 5] 1 5 5 swap(1, 4)
[1, 2, 3, 4, 5] 2 5 2 data[l] == l+1
[1, 2, 3, 4, 5] 3 5 3 data[l] == l+1
[1, 2, 3, 4, 5] 4 5 4 data[l] == l+1
[1, 2, 3, 4, 5] 5 5 5 data[l] == l+1

示例2

輸入爲: [9, 1, 4, 4, -3, 8, 2]

l = 0r = 7

數組 l r data[l] 狀態
初始 [9, 1, 4, 4, -3, 8, 2] 0 7
[2, 1, 4, 4, -3, 8, 2, 2] 0 6 9 data[l] > r
[1, 2, 4, 4, -3, 8, 2, 2] 0 6 2 swap(0, 1)
[1, 2, 4, 4, -3, 8, 2, 2] 1 6 1 data[l] == l + 1
[1, 2, 4, 4, -3, 8, 2, 2] 2 6 2 data[l] == l + 1
[1, 2, -3, 4, 4, 8, 2, 2] 2 6 4 swap(2, 3)
[1, 2, 8, 4, 4, 8, 2, 2] 2 5 -3 data[l] <= l
[1, 2, 4, 4, 4, 8, 2, 2] 2 4 8 data[l] > r
[1, 2, 4, 4, 4, 8, 2, 2] 2 3 4 data[data[l] - 1] == data[l]
[1, 2, 4, 4, 4, 8, 2, 2] 2 2 4 data[data[l] - 1] == data[l]

實現

public static int disappearMinPositiveNum(int[] data) {
	int l = 0, r = data.length;
    while (l < r) {
        if (data[l] == l + 1) {
           l += 1;
        } else if (data[l] <= l || data[l] > r || data[data[l] - 1] == data[l]) {
           data[l] = data[--r];
        } else {
           swap(data, l, data[l] - 1);
        }
    }
    return l + 1;
}

/**
* 交換
**/
public static void swap(int[] data, int x, int y) {
    int tmp = data[x];
    data[x] = data[y];
    data[y] = tmp;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章