【題目】
給定陣列a,大小為n,陣列元素為1到n的數字,不過有的數字出現了多次,有的數字沒有出現。請給出演算法和程式,統計哪些數字沒有出現,哪些數字出現了多少次。能夠在o(n)的時間複雜度,o(1)的空間複雜度要求下完成麼?
【分析】
我們知道原陣列是沒有排序的。如果排序了,很簡單的。o(1)的空間含義,可以使用變數,但不能開闢陣列或者map等來計數。
這個題目,很直接的解法就是兩層遍歷,o(n^2)的複雜度,o(1)的空間。空間滿足了,但是時間沒有。
很多類似的題目,都會用xor的方法,大家仔細想一下,這個題目,可以麼?或者這個題目和可以用xor的題目的差異在哪兒?最直接的就是,每乙個數字的重複的次數是不同的。
還有就是以空間換時間的方法,例如用hash map或者陣列來計數。時間滿足了,但是空間沒有滿足。
那怎樣才能有時間複雜度o(n),空間複雜度o(1)的演算法呢?不能開闢新的空間,那麼只剩下,重複利用陣列a。那麼該如何利用陣列a呢?
(1)首先,我們介紹一種三次遍歷陣列的方法,我們都考慮陣列從0開始:
第一次遍歷:對於每乙個a[i] = a[i] * n
第二次遍歷:對於每乙個i,a[a[i]/n]++
第三次遍歷:對於每乙個i,a[i] % n就是出現次數
a[i]應該出現在a中的a[i]位置,乘以n、再除以n,很容易的來回變換;第二次遍歷,對於a[i]本來所在的位置不斷增1,但絕對不對超出n的,那每乙個i出現的次數,就是a[i]對n取餘。
(2)還有一種兩次遍歷的方法,也是上面的思路:題目中陣列是1到n,為了方便演算法考慮,以及陣列儲存方便,我們考慮0-n-1,結果是相同的。 考慮a[i],現在位置是i,如果採用a來計數,它的位置應該是a[i] % n,找到計數字置,該如何處理這個位置呢?加1麼? 顯然不可以,這裡有乙個技巧,就是加n,有兩個原因
加n可以保證a[i] % n是不變的
a陣列,最後每乙個元素表示為a[i] = x + k*n,其中x這樣,大家也能夠明白,為什麼a[i]在a中的位置,表示為a[i] % n了吧。
【**】
#include #include #include using namespace std;
//統計陣列重複元素個數
void arraynumcount(int array,int n)
for(i = 0;i < n;i++)
for(i = 0;i < n;i++)
for(i = 0;i < n;i++)
//輸出
//array[0]儲存值為n的個數
int element;
for(i = 0;i < n;i++)
else
printf("element:%d count:%d\n",element,array[i]);
}}int main() ;
arraynumcount(array,10);
return 0;
}
**2:
#include #include #include using namespace std;
//統計陣列重複元素個數
void arraynumcount(int array,int n)
for(i = 0;i < n;i++)
//輸出
//array[0]儲存值為n的個數
int element,count;
for(i = 0;i < n;i++)
printf("element:%d count:%d\n",element,count);
}}int main() ;
arraynumcount(array,11);
return 0;
}
經典面試題 統計陣列
題目 給定陣列a,大小為n,陣列元素為1到n的數字,不過有的數字出現了多次,有的數字沒有出現。請給出演算法和程式,統計哪些數字沒有出現,哪些數字出現了多少次。能夠在o n 的時間複雜度,o 1 的空間複雜度要求下完成麼?分析 我們知道原陣列是沒有排序的。如果排序了,很簡單的。o 1 的空間含義,可以...
面試題 統計陣列中數字的個數
輸入 10個整數,如 9 9 0 7 8 6 5 7 3 9 輸出 統計每個數字出現的次數,並按數字的大小排序 0 13 1 5 16 1 7 28 1 9 3一 c 版本 include include using namespace std intmain map iterator m iter...
面試題之陣列統計
題目 給定陣列a,大小為n,陣列元素為0到n 1的數字,不過有的數字出現了多次,有的數字沒有出現。請給出演算法和程式,統計哪些數字沒有出現,哪些數字出現了多少次。要求在o n 的時間複雜度,o 1 的空間複雜度下完成。解法一 直接用兩層遍歷,o n 2 的時間複雜度,o 1 的空間複雜度 inclu...