**自:
題目:
#面試題#給定乙個無序的整數陣列,怎麼找到第乙個大於0,並且不在此陣列的最小整數。比如[1,2,0] 返回 3, [3,4,-1,1] 返回 2。最好能o(1)空間和o(n)時間。
**解法:直接考慮這個問題是比較困難的。不如先換個簡單的問題。
問題1
給定乙個陣列,長度為n,除a[0]以外,其他元素都是a[i] == i。那麼請找出第乙個大於0,且不在此陣列中的最小整數。
答案就是: n + (a[0] == n);
問題2
給定乙個陣列,長度為n,某幾個位置的元素滿足 a[x] < 0 或者 a[x] > n,餘下的元素都滿足a[i] == i。那麼請找出第乙個大於0,且不在此陣列中的最小整數。
答:很明顯:當x的值限定為0時。就變成了問題1。
除此之外,這個問題的解也容易求得。
情況1: 首先從1~n開始掃瞄,當發現i != a[i]時,直接返回i。此時的i必定是最小的未出現的整數。
情況2: 當掃瞄完1~n之後,那麼就回歸至問題1了。
1for (i = 1; i < n; ++i)
4return (n + (n == a[0]));
問題3
當給出問題2之後,就需要考慮如何把原題目轉換成為問題2了。
實際上要完成的任務就變成了,如何把乙個陣列中的元素元神歸位。也就是讓a[i] == i。如果能讓這些元素元神歸位,那麼就轉換成為問題2了。就很容易求解了。
演算法如下:
我們從後往前掃瞄,i = n - 1 to 0;
step1如果發現a[i] < 0 || a[i] > n; 則 continue;
step2 如果發現a[i] == a[a[i]]; 則continue;
step3 如果發現0 < a[i] < n
說明需要將a[i]元神歸位。也就是放到a[a[i]]上去。
swap(a[i], a[a[i]]).
再跳轉至step2。
note: 需要注意一種有重複數的情況,比如a[11] = 2, a[2] = 2。這時候,就不用進行交換了。直接處理下乙個元素。
可以給出**:
1int i =n, t, temp;
2if (!a || n <= 0) return -1;3
4while ((--i) >= 0
) 12 }
好吧,到現在為止,原題已經變得很簡單了。可以直接給出**了。
原題解答
1int find(int *a, int
n) 13}14
15for (i = 1; i < n; ++i)
16if (a[i] != i) return
i;17
18return (n + (a[0] ==n));
19 }
演算法複雜度分析
這裡再加上對演算法複雜度的分析。演算法的複雜度在下面這段**看起來。唔~~很難說清楚到底複雜底是多少。
我們不妨回歸到問題本身。把一些條件分析清楚:
條件1、對於給定的乙個陣列。元神歸位數目是有限的。假定為k。這個k表示的是,當處理完成之後,a[i] == i的數目。
k的範圍是固定的: 0 <= k < n。
條件2、對於每個元素而言,while (0 < a[i] && a[i] < n && i != a[i]) 這個while 迴圈裡面,每交換一次,就會使得乙個元神歸位。如果交換了xi次,就會使得xi個元神歸位。
這個是很容易搞清楚的。因為每次交換的效果,都是讓某個元神歸了位。
比如a[11] = 5, a[5] = 2, a[2] = 0;
第一次交換: a[11] = 2, a[5] = 5, a[2] = 0;
第二次交換: a[11] = 0, a[5] = 5, a[2] = 2;
條件3、對於整個陣列而言,元神歸位的數目k應該是滿足:
x0 + x1 + x2 + x3 + ..... + xn-1 = k
這也就是說交換k次。
注意啊: 不是每個i都會交換k次。而是所有的i交換次數的總和,應該是k次。
可以想象一種極端的情況,比如,當i=n-1的時候,置換次數最多。剛好把所有的元神都歸位了。那麼從i = n - 2開始,就再也不會進入到裡面的while迴圈中去了。
再例如:如果i=n-1的時候,使得2個元神歸了位。那麼從 i = n-2 ~ 0,則只需要讓k-2個元神歸位了。因為已經歸位的,是不用再去處理的。
想到這裡,你應該明白了,下面這段**的複雜度是o(n) + o(k)。由於0<=k < n。所以複雜度是o(n)。也就是線性時間完成了任務。
面試題整理 最小沒出現的整數
題目 面試題 給定乙個無序的整數陣列,怎麼找到第乙個大於0,並且不在此陣列的最小整數。比如 1,2,0 返回 3,3,4,1,1 返回 2。最好能o 1 空間和o n 時間。解法 直接考慮這個問題是比較困難的。不如先換個簡單的問題。問題1給定乙個陣列,長度為n,除a 0 以外,其他元素都是a i i...
40億個非負整數中找到沒出現的數
要求這裡的非負整數是32位也就是0 2 32 1。最多用1gb的記憶體。如果只能用10mb的空間呢,只需要找到乙個沒有出現的數即可。首先先分析一下,40億個4b約為16gb這裡只用1gb,這裡要求注意是找出沒出現,這就和網頁過濾系統類似,出現與不出現兩個狀態 0和1 那麼我們就可以用bit陣列來確定...
陣列中未出現的最小正整數
陣列中未出現的最小正整數 給定乙個無序陣列arr,找到陣列中未出現的最小正整數 例如arr 1,2,3,4 返回1 arr 1,2,3,4 返回5 要求 時間複雜度為o n o n o n 空間複雜度為o 1 o 1 o 1 輸入描述 第一行為乙個整數n。表示陣列長度。接下來一行n個整數表示陣列內的...