.net 遍歷陣列找重複值寫入一個新陣列_尋找陣列中的重複數字
技術標籤:.net 遍歷陣列找重複值寫入一個新陣列delphi7儲存過程傳入陣列hdfs中與file陣列類似的陣列jquery交換陣列元素位置遍歷陣列找重複值
前言
前面一系列文章分享了資料結構與演算法的基礎知識,接下來分享一些演算法題的解題思路與實現。歡迎各位感興趣開發者閱讀。
問題描述
有一個數組,現要找出陣列中任意一個重複的元素。它的規則如下:
- 給定一個長度為n的陣列,陣列中每個元素的取值範圍為:0~n-1
- 陣列中某些數字是重複的,但是不知道哪些數字重複了,也不知道重複了幾次
- 求陣列中任意一個重複的數字
實現思路
這個問題的實現思路有三種:
- 排序方法實現
- 雜湊表輔助實現
- 動態排序法實現
接下來,我們來一一講解下這三種實現思路。
排序方法實現
用排序方法實現分為兩步:
- 先用快速排序對陣列進行排序
- 遍歷排序好的陣列,如果其相鄰的兩個元素相等就代表陣列中有重複的數字,將其返回即可。
接下來,我們通過一個例子來驗證下上述思路。
宣告一個數組:[8, 1, 2, 3, 4, 3, 3, 4, 5]
- 用快速排序對上述陣列進行排序,排序好的陣列為:
[1, 2, 3, 3, 3, 4, 4, 5, 8]
- 遍歷陣列,判斷i號位置的元素與i+1位置的元素是否相等。
- i = 0時,i號位置的元素為1,i+1位置的元素是2,
1 !== 2
,繼續下一輪遍歷 - i = 1時,i號位置的元素為2,i+1位置的元素是3,
2 !== 3
- i = 2時,i號位置的元素為3,i+1位置的元素是3,
3 === 3
,陣列中有重複數字,儲存i號位置的元素,退出迴圈。
- i = 0時,i號位置的元素為1,i+1位置的元素是2,
- 返回找到的重複數字
時間複雜度分析:呼叫快速排序其時間複雜度為
O(nlog(n))
,陣列排序完成後只需遍歷陣列找到相鄰的就退出,因此總的時間複雜度為O(nlog(n))
空間複雜度分析:空間複雜度分析:由於沒有宣告新的空間,因此空間複雜度為
O(1)
使用排序方法我們可以解決這個問題,但是需要對陣列進行排序,時間複雜度偏高。
雜湊表輔助實現
我們可以額外宣告一個雜湊表,然後遍歷陣列,判斷陣列中的元素是否已存在於雜湊表中,如果不存在就將其放入雜湊表中,否則就代表陣列中有重複元素,將其返回即可。
- 宣告一個空的雜湊表
- 從頭到尾遍歷陣列,如果當前遍歷到的元素不存在與雜湊表中,就把它加入雜湊表,否則就返回這個元素
接下來,我們通過一個例子來驗證下上述思路。
宣告一個數組:[8, 1, 2, 3, 4, 3, 3, 4, 5]
- 宣告一個雜湊表:
const hashMap = new HashMap()
- 遍歷陣列,判斷陣列中的元素是否在雜湊表中。
- i = 0時,i號位置的元素為8,不在雜湊表中,將其放入雜湊表。
- i = 1時,i號位置的元素為1,不在雜湊表中,將其放入雜湊表。
- i = 2時,i號位置的元素為2,不在雜湊表中,將其放入雜湊表。
- i = 3時,i號位置的元素為3,不在雜湊表中,將其放入雜湊表。
- i = 4時,i號位置的元素為4,不在雜湊表中,將其放入雜湊表。
- i = 5時,i號位置的元素為3,在雜湊表中,儲存i號位置的元素,終止迴圈。
- 返回找到的重複數字
時間複雜度分析:遍歷陣列,判斷雜湊表中是否包含當前遍歷到的元素時,都可以用
O(1)
的時間複雜度完成,所有元素遍歷完就需要n個O(1),因此總的時間複雜度為O(n)
空間複雜度分析:由於需要一個額外的雜湊表來儲存資料,情況最壞時陣列的所有元素都會放進雜湊表中,因此總的空間複雜度為:
O(n)
使用雜湊表輔助實現時,我們將時間複雜度降低了,但是代價是用了O(n)
的空間儲存雜湊表,我們用空間換取了時間。
動態排序法實現
根據題意可知,陣列中元素的取值範圍在0~n-1,那麼就可以得到如下結論:
- 如果陣列中沒有重複元素,那麼第i號元素的值一定是當前下標(i)
- 如果陣列中有重複元素,那麼有些位置可能存在多個數字,有些位置可能沒有數字
根據上述結論,我們可以得出下述實現思路:
- 從頭到尾遍歷陣列,儲存第i號位置的元素,用m表示
- 如果m的值等於當前下標(i),則繼續遍歷。
- 否則就判斷m的值是否等於陣列下標為m處的值。
- 如果等於代表重複將其返回。
- 如果不等於,就交換陣列i號位置的元素和m號位置的元素,更新m的值
- 繼續判斷m的值是否等於陣列下標為m處的元素。
接下來,我們通過一個例子來驗證下上述思路。
宣告一個數組:[8, 1, 2, 3, 4, 3, 3, 4, 5]
- 從頭到尾遍歷陣列,儲存i號位置的元素,用m表示。
- 當下標為0時,m = 8。
- 此時,m的值為8,
8 != 0
,陣列8號位置的元素為5,8 != 5
,則交換array[0]
和array[8]
的位置,更新m的值。交換位置後的陣列為:[5, 1, 2, 3, 4, 3, 3, 4, 8]
- 此時,m的值為5,
5 != 0
,陣列5號位置的元素為3,3 != 5
,則交換array[0]
和array[5]
的位置,更新m的值。交換位置後的陣列為:[3, 1, 2, 3, 4, 5, 3, 4, 8]
- 此時,m的值為3,
3!=0
,陣列3號位置的元素為3,3 === 3
,元素重複,返回m。 - 問題解決,重複數字為3。
時間複雜度分析:每個數字最多隻要交換2次就能找到它的位置,因此總的時間複雜度為O(n)
空間複雜度分析:所有操作都在原陣列進行,沒有用到額外的空間,所以空間複雜度為O(1)
使用動態排序法實現時,我們只是改變了陣列的元素順序,沒有使用額外的空間,因此空間複雜度降低了,同時時間複雜度又保持在了O(n)
。所以,這種解法相對與前面兩種而言是最優的。
實現程式碼
接下來,我們來看看如何將其實現,此處我們使用TypeScript將其實現,我們先來看看如何設計這個類。
根據題意可知,並非所有陣列都能使用上面的方法來求解。因此我們在設計類的時候,要判斷呼叫者傳入的引數是否滿足題意。
- 新建一個ts檔案,命名為:
ArrayRepeatedNumber.ts
- 建立
ArrayRepeatedNumber
類,宣告類內需要用到的輔助變數和建構函式。我們在建構函式中,對呼叫者傳入的引數進行校驗。
exportclassArrayRepeatedNumber{
privatesort:Sort<number>;
privatereadonlyisTrue:boolean;
constructor(privatearray:number[]){
this.isTrue=true;
//判斷引數是否滿足規則
if(array==null||array.length<=0){
this.isTrue=false;
console.log("陣列不能為空");
}
for(leti=0;iif(array[i]0||array[i]>array.length-1){
this.isTrue=false;
console.log("陣列中元素的取值範圍為0~n-1");
}
}
this.sort=newSort(array);
}
}
接下來,我們來看看上述三種實現思路的程式碼。
- 使用排序的方法解決
getRepeatedToSort():number|void{
if(this.isTrue){
//排序陣列
constsortArray=this.sort.quickSort();
//重複的數字
letval=-1;
for(leti=0;i//排序完成後,相鄰的兩個數字相等就代表陣列中有重複數字,將其返回
if(sortArray[i]==sortArray[i+1]){
val=sortArray[i];
break;
}
}
returnval;
}
}
- 使用雜湊表解決
getRepeatedToHashMap():number|void{
if(this.isTrue){
consthashMap=newHashMap();
letval=-1;
for(leti=0;ithis.array.length;i++){
//如果雜湊表中存在當前元素就將其返回
if(hashMap.get(this.array[i])!=null){
val=this.array[i];
break;
}
//不存在,將其加入雜湊表
hashMap.put(this.array[i],0);
}
returnval;
}
}
- 使用動態排序法解決
getRepeated():number|void{
if(this.isTrue){
for(leti=0;ithis.array.length;i++){
//儲存陣列i號位置的元素
letm=this.array[i];
//判斷m的值是否與當前下標一樣,一樣則繼續下一輪迴圈
while(m!==i){
//判斷m的值是否等於陣列m號位置的元素
if(m===this.array[m]){
//如果相等,代表重複,返回這個元素
returnm;
}
//交換陣列的i號位置的元素和m號位置的元素
[this.array[i],this.array[m]]=[this.array[m],this.array[i]];
//交換完畢,更新m的值
m=this.array[i];
}
}
//未找到
return-1;
}
}
程式碼地址
完整程式碼,請移步:ArrayRepeatedNumber.ts
編寫測試程式碼
我們用上面舉的例子來驗證下上述程式碼是否正確執行。
constarrayRepeatedNumber=newArrayRepeatedNumber([8,1,2,3,4,3,3,4,5]);
constresult=arrayRepeatedNumber.getRepeatedToSort();
if(result!==-1&&result!=null){
console.log("ArrayRepeatedNumbertoSort:"+result);
}
constarrayRepeatedNumber=newArrayRepeatedNumber([8,1,2,3,4,3,3,4,5]);
constresult=arrayRepeatedNumber.getRepeatedToSort();
if(result!==-1&&result!=null){
console.log("ArrayRepeatedNumbertoHashMap:"+result);
}
constarrayRepeatedNumber=newArrayRepeatedNumber([8,1,2,3,4,3,3,4,5]);
constresult=arrayRepeatedNumber.getRepeated();
if(result!==-1&&result!=null){
console.log("ArrayRepeatedNumber:"+result);
}
寫在最後
- 公眾號無法外鏈,文中連結可點下方閱讀原文進行檢視。