題目:給定數組A,大小為n,數組元素為0到n-1的數字,不過有的數字出現了多次,有的數字沒有出現。請給出算法和程序,統計哪些數字沒有出現,哪些數字出現了多少次。要求在O(n)的時間復雜度,O(1)的空間復雜度下完成。 解法一: 直接用兩層遍歷,O(n^2)的時間復雜度,O(1)的空間復雜度
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i, j, count = 0; //n is The length of the Array
while (scanf("%d", &n) != EOF)
{
int *a = malloc(sizeof(int) * n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
for (i = 0; i < n; i++)
{
count = 0;
for (j = 0; j < n; j++)
{
if (i == a[j])
{
count++;
}
}
if (count == 0)
printf("%d does not appear in the array!\n", i);
else
printf("%d appear in the array for %d times\n", i, count);
}
}
}
解法二: 以空間換時間的辦法,用一個map數組來存放元素的計數。時間復雜度為O(n),空間復雜度為O(n)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n, i, j, count = 0; //n is The length of the Array
while (scanf("%d", &n) != EOF)
{
int *a = malloc(sizeof(int) * n);
int *map = malloc(sizeof(int) *n);
memset(map, 0, sizeof(map));
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
for (i = 0; i < n; i++)
{
map[a[i]]++;
}
for (i = 0; i < n; i++)
{
if (map[i] == 0)
printf("%d does not appear in the array!\n", i);
else
printf("%d appear in the array for %d times\n", i, map[i]);
}
}
}
但上述解法都不滿足題目對時間復雜度和空間復雜度的要求,因此我們想到重復利用數組A。 解法三: 三次遍歷數組的方法: 第一次遍歷:對於每一個A[i] = A[i] * n 第二次遍歷:對於每一個i, A[A[i]/n]++ 第三次遍歷:對於每一個i,A[i]%n就是i出現的次數 解釋:A[i]應該出現在A中的A[i]位置,乘以n、再除以n,很容易來回變換;第二次遍歷,對於A[i]本來所在的位置不斷增1,但絕不超出n,那麼每一個i出現的次數,就是A[I]對n取余。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i; //n is The length of the Array
while (scanf("%d", &n) != EOF)
{
int *a = malloc(sizeof(int) * n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
for (i = 0; i < n; i++)
a[i] = a[i] * n;
for (i = 0; i < n; i++)
a[a[i]/n]++;
for (i = 0; i < n; i++)
{
if (a[i] % n == 0)
printf("%d does not appear in the array!\n", i);
else
printf("%d appear in the array for %d times\n", i, a[i]%n);
}
}
}
解法四: 兩次遍歷數組的方法:考慮A[i],現在的位置為i,如果采用A來計數,它的位置應該是A[i]%n,找到計數位置,處理這個計數位置的辦法就是加n. 第一次遍歷:對A[i]的計算位置加n,加n可以保證A[i]%n的是不變的 第二次遍歷:A數組,最後每一個元素表示為A[i] = x + k * n; 其中x<n,並且k就是我們要統計的頻率
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i; //n is The length of the Array
while (scanf("%d", &n) != EOF)
{
int *a = malloc(sizeof(int) * n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
for (i = 0; i < n; i++)
a[a[i] % n] += n;
for (i = 0; i < n; i++)
{
if (a[i] / n == 0)
printf("%d does not appear in the array!\n", i);
else
printf("%d appear in the array for %d times\n", i, a[i]/n);
}
}
}