找出陣列中是否有重複的數

2022-05-21 01:46:49 字數 3434 閱讀 2507

題目是這樣的, 陣列是無序的, 可能沒有重複的數,但最多隻可能有乙個重複的數,要求用最快的方法找到是否有重複的數。

乍一想,挺難的,但是其實非常的簡單。

解決辦法:

陣列a[n],1

至n-1

這n-1

個數存放在

a[n]

中,其中某個數

重複一次

。寫乙個函式,找出被重複的數字。

時間複雜度必須為o(

n)函式原型:

int do_dup(int a,int n)

××××××××××××××××××××××××××××××××××

假金條的數學思想

此演算法題

借鑑了假金條的思想

,不過比那個過程簡單,存放1至

n-1,就相當於

依次從各個袋中取出1至

n-1個金條

,但是有乙個是重的,計算這

n個數的和將相當於稱總重量,減去1至

n-1的和(用數學方法求)就可求出來重複的數。總之

要充分利用數學知識

const int n = 5;

int a[n]=;

int tmp1 = 0;

int tmp2 = 0;

for (int i=0; i

printf("

重複的數

:%d\n",n-(tmp1-tmp2));

上述方法求

1~n的和,減去陣列總和,即為

n-x

的差值,

x為待找的數

可以優化的是

1-n的和不用程式算

,數學方法直接算了

可定義乙個巨集

,#define sum(x) (x(x+1)/2)

當然乘法操作是比較複雜的,當

n較小時加幾個數的效率可能更高

××××××××××××××××××××××××××××××××××

標誌陣列法

申請乙個長度為

n-1且均為

'0'組成的字串。然後從頭遍歷

a[n]

陣列,取每個陣列元素

a[i]

的值,將其對應的字串中的

相應位置置

1,如果已經置過

1的話,那麼該數就是重複的數。

就是用位圖來實現的。

其實,只要數還是

0 -- n-1

裡面的數,那麼可以用這樣的方法判斷所有的重複數的位置和值。

比如這樣的乙個陣列

我們生成乙個字串

"000";

然後開始遍歷,

a[0] = 2;

所以,字串的第二位為

"0",

那麼我們將其置為

"1"字串為

"010"

重複,字串為

"011",,,,,"111"

然後,判斷

a[3] = 2

那麼第二位為

"1"所以,

a[3]

為重複數,並且位置為第4位。

上述map

等各方法的

思路是一致的,即訪問過後做標記

,再次訪問時即可知道是否重複。如果考慮空間複雜度的話,其空間o(

n)int do_dup(int arr,int num)

}××××××××××××××××××××××××××××××××××

固定偏移標誌法

利用標記法單純寫個

o(n)

的方法並不難,關鍵是如何保證兩點:

不改變a

的初始值

函式內不開闢另外的

o(n)

記憶體空間

.很明顯上述方法申請了

o(n)

記憶體空間,當

n過大時,效能降低了

因此應利用

a[n]

本身中值和下標的關係來做標記,處理完成後再清除標記即可

a[n]

,裡面是1至

n-1。原陣列

a[i]

最大是n-1

,若a[i]=k

在某處出現後,將

a[k]

加一次n

,做標記,當某處

a[i]=k

再次成立時,檢視

a[k]

即可知道

k已經出現過。

a[i]

在程式中最大也只是

n-1+n=2n-1

(溢位了怎麼辦啊???

),此為乙個限制條件

int do_dup(int arr,int num)

else

}printf("

無重複");

return -1;

}上面就是時間複雜度

o(n),

空間複雜度

o(1)

的演算法!

××××××××××××××××××××××××××××××××××

符號標誌法

上述方法將元素加乙個固定的

num來做標記,可能會造成溢位。下列方法中利用符號位來做標記,因為

1~n都為正值,所以就無限制了。基本思想是用

int陣列的符號位作雜湊表

。(反正不是

unsigned int

符號位閒著也是閒著)

bool dup(int array,int n)

else

}else // |array[i]|

代表的值已經出現過一次了

else }}

return -1;//

沒有重複}//

用於修復陣列

void restorearray(int array,int n)

}時間複雜度o(

n)空間複雜度o(

1)不過時間複雜度o(

n)空間複雜度o(

1)不只乙個重複利用此法也是可以實現的

//附上我修改後的演算法

bool do_dup_mal(int arr, int n, int *pre, int *back)

char *arrayflag = new char[max+1] ;

if (null == arrayflag)

return -1;

//while(i++ < max) arrayflag[i] = '\0';

memset(arrayflag, 0, max+1 ); // '\0' == 0

for(i=0; i

找出陣列中是否有重複的數

2010 09 09 23 03 59 分類 c c 標籤 c 字型大小大中小 訂閱 陣列a n 1至n 1這n 1個數存放在a n 中,其中某個數重複一次。寫乙個函式,找出被重複的數字。時間複雜度必須為o n 函式原型 int do dup int a,int n 假金條的數學思想 此演算法題借鑑...

PHP 判斷陣列中是否有重複值並找出重複值

可以用來測試需要唯一憑據號碼的,是否有重複值,不過一般直接使用uuid了,簡單粗暴就解決問題,這個就簡單的測試生成的資料是否有重複值吧 author wyy date 2019 01 09 13 34 16 email 2752154874 qq.com last modified by wyy l...

找出陣列重複的數

1 在乙個長度為 n 的陣列裡的所有數字都在 0 n 1 的範圍內,找出任意乙個重複的數。簡明思路 按照題目要求,如果這個陣列裡面的數恰好沒有重複的數,則陣列下標跟對應的值相等。否則,當掃瞄到下標為 i 的數字時,比較這個下標的值 m 是不是等於 i 如果是,說明這個值就在它對應的下標下,繼續掃瞄 ...