牛客oj:陣列中重複的數字牛客oj九度oj:未收錄
github**: 051-陣列中重複的數字
csdn題解:劍指offer–051-陣列中重複的數字
九度oj
csdn題解
github**
051-陣列中重複的數字
未收錄劍指offer–051-陣列中重複的數字
051-陣列中重複的數字
題目描述
在乙個長度為n的陣列裡的所有數字都在0到n-1的範圍內。樣例輸入陣列中某些數字是重複的,但不知道有幾個數字是重複的。
也不知道每個數字重複幾次。請找出陣列中任意乙個重複的數字。
例如,如果輸入長度為7的陣列,那麼對應的輸出是重複的數字2或者3。
2, 3, 1, 0, 2, 5, 3樣例輸出2, 1, 3, 1, 4
bool checkvalidity(int *numbers, int length)
// 元素必須在[0, n-1]的範圍
for(int i = 0; i < length; i++)
}return
true;
}
最簡單的思路就是先把輸入的陣列排序。從排序的陣列中找出重複的數字就是個很容易的事情了。只需要從頭向尾掃瞄一遍排序好的陣列即可。
對乙個陣列排序的時間複雜度是o(
nlog
n)
掃瞄乙個排序好的陣列發現重複的數字的時間複雜度是o(
n)
class solution
sort(numbers, numbers + length); // 對陣列進行排序
int i = 0;
bool isdup = false;
*duplication = -1;
// 掃瞄一遍陣列發現重複的數字
for(i = 0; i < length - 1; i++)
}return isdup;
}};
當然我們用hashtabble也可以實現,
hashtable中可以很方便的查詢到某個元素是否存在,時間複雜度o(
n),空間複雜度o(
n)
class solution
set s;
bool isdup = false;
*duplication = -1;
for(int i = 0; i < length; i++)
s.insert(numbers[i]);
}return isdup;
}};
hashtable的方式是在優化查詢的過程,因為hashtable查詢的時間複雜度為o(
1),那麼我們繼而聯想到,如果不設hash,直接用乙個用乙個陣列flag當前標識,記錄某個元素是否出現,
flag[i] =0標識元素i未出現,這樣也可以在o(flag[i] =1標識元素i出現
1)的時間內實現判斷
class solution
int flags[length];
memset(flags, 0, sizeof(flags));
for(int i = 0; i < length; i++)
else
}return
false;
}};
我們採用了乙個以空間換時間的方式, 但是有沒有什麼辦法能夠優化空間上的消耗呢?
因為我們需要的只是乙個標識, 0或者1,那麼我們完全沒必要乙個整數來做標識,
因此可做如下優化
用乙個n位的單元來儲存即可, 每一位都是乙個標識這種方法可以把空間消耗將低, 但是還是需要額外的空間,那麼有沒有不需要空間消耗的方法呢?
我們可以看到陣列中元素的大小都在[0-n)這個區間內, 都是正數,那麼他們的符號位對我們來說就是無關緊要的, 因此我們直接拿符號位當成我們的標識位就行了
numbers[i]符號位為0表示數字i沒有重複numbers[i]符號位為1標識數字i重複
#define set_symbol_bit(num) ((num) |= (1 << 31)) /* 設定符號位為1 */
#define get_origin_num(num) ((num) & (~(1 << 31))) /* 獲取到源資料 */
#define get_symbol_bit(num) (((num) >> 31) & 1) /* 獲取符號位(標識)*/
class solution
for(int i = 0; i < length; i++)
else
};
跟標識法類似, 如果不借助外部輔助空間,那麼我們只能在陣列內部下功夫,又能設定標識,又能恢復資料(不破壞資料)的方式,前面我們用符號位作為標識的方法就是通過符號位,即判斷了是否存在,又可以通過符號位的反轉重新恢復資料,那麼有沒有其他類似的方法呢?
我們想到我們的資料都是[0, n)這個區間的,那麼我們採用類似與移碼的方法,讓資料加上或者減去乙個固定的偏移量,這樣就可以即標識資料,又不損壞資料,為了能夠區分出資料,這個偏移必須大於n,這樣我們的原資料與標識資料存在一一對映關係。
[0, n-1] -=>+偏移n-=> [n, 2n-1]
class solution
for(int i = 0; i < length; i++)
else
}return
false;
}};
劍指offer上提供的方法,這種方法採用交換的方法
我們考慮如果每個數字都置出現一次,那麼此時是最完美的,每乙個下標i對應元素numbers[i],也就是說我們對於陣列中的每個元素numbers[i]都把它放在自己應該在的位置上numbers[numbers[i]]上, 如果我們發現有兩個元素想往同乙個位置上放的時候,說明此元素必然重複
即如下的過程
如果numbers[i] == i, 那麼我們認為number[i]這個元素是在自己的位置上的
否則的話, numbers[i]這個元素就應該在numbers[numbers[i]]這個位置上, 於是我們交換numbers[i]和numbers[numbers[i]]
重複操作1, 直到number[i]== i, 則繼續操作下乙個位置的元素, 或者numbers[i] == numbers[numbers[i],元素重複
class solution
for(int i = 0; i < length; i++)
debug <<"swap numbers["
<"] and numbers["
<"]"
<"numbers["
<"] = "
<" is equal to it's index = "
false;
}};
劍指Offer (陣列)陣列中重複的數字
題目鏈結 題目描述 在乙個長度為n的陣列裡的所有數字都在0到n 1的範圍內。陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意乙個重複的數字。例如,如果輸入長度為7的陣列,那麼對應的輸出是第乙個重複的數字2。解決方法class solution retur...
劍指offer 陣列 陣列中重複的數字
在乙個長度為n的陣列裡的所有數字都在0到n 1的範圍內。陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意乙個重複的數字。例如,如果輸入長度為7的陣列,那麼對應的輸出是第乙個重複的數字2。遍歷每乙個數字,在其後的數字中查詢是否有含有相同的數字 coding...
劍指Offer 陣列中的重複陣列
public boolean duplicate int numbers,int length,int duplication arrays.sort numbers for int i 0 i下面來看看乙個比較,交換的過程 原始陣列 第一次 i 0 陣列第0個元素是2,與下標不等,然後與下標為2的...