給定乙個長度為 n+1 的陣列nums,陣列中所有的數均在 1∼n 的範圍內,其中 n≥1。
請找出陣列中任意乙個重複的數,但不能修改輸入的陣列。
給定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。
返回 2 或 3。
如果只能使用 o(1) 的額外空間,該怎麼做呢?
class solution ; //用此陣列類儲存重複的數字。 n個數,哪個重複 nums2[n]++
for(auto x: nums)
}}};
class solution
return r;
}};
(分治,抽屜原理) o(nlogn)o(nlogn)
這道題目主要應用了抽屜原理和分治的思想。
抽屜原理:n+1 個蘋果放在 n 個抽屜裡,那麼至少有乙個抽屜中會放兩個蘋果。
用在這個題目中就是,一共有 n+1 個數,每個數的取值範圍是1到n,所以至少會有乙個數出現兩次。
然後我們採用分治的思想,將每個數的取值的區間[1, n]劃分成[1, n/2]和[n/2+1, n]兩個子區間,然後分別統計兩個區間中數的個數。
注意這裡的區間是指 數的取值範圍,而不是 陣列下標。
劃分之後,左右兩個區間裡一定至少存在乙個區間,區間中數的個數大於區間長度。
這個可以用反證法來說明:如果兩個區間中數的個數都小於等於區間長度,那麼整個區間中數的個數就小於等於n,和有n+1個數矛盾。
因此我們可以把問題劃歸到左右兩個子區間中的乙個,而且由於區間中數的個數大於區間長度,根據抽屜原理,在這個子區間中一定存在某個數出現了兩次。
依次類推,每次我們可以把區間長度縮小一半,直到區間長度為1時,我們就找到了答案。
複雜度分析
時間複雜度:每次會將區間長度縮小一半,一共會縮小 o(logn)o(logn) 次。每次統計兩個子區間中的數時需要遍歷整個陣列,時間複雜度是 o(n)o(n)。所以總時間複雜度是 o(nlogn)o(nlogn)。
空間複雜度:**中沒有用到額外的陣列,所以額外的空間複雜度是 o(1)o(1)。
找出陣列重複的數
1 在乙個長度為 n 的陣列裡的所有數字都在 0 n 1 的範圍內,找出任意乙個重複的數。簡明思路 按照題目要求,如果這個陣列裡面的數恰好沒有重複的數,則陣列下標跟對應的值相等。否則,當掃瞄到下標為 i 的數字時,比較這個下標的值 m 是不是等於 i 如果是,說明這個值就在它對應的下標下,繼續掃瞄 ...
求陣列中的第二大的數 不改變陣列的順序
如果用氣泡排序對數值排序,那麼演算法的效率比較低。一開始我考慮的先求出陣列的最大值和陣列的最小值,然後再迴圈陣列,求出陣列的第二大的值,這個演算法的時間複雜度是o n private static void secondarray int bb aa 0 最大值 int cc aa 0 最小值 fo...
AcWing 13 找出陣列中重複的數字
題目描述 給定乙個長度為 n 的整數陣列nums,陣列中所有的數字都在 0 n 1的範圍內。陣列中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出陣列中任意乙個重複的數字。注意 如果某些數字不在 0 n 1的範圍內,或陣列中不包含重複數字,則返回 1 樣例給定 nums...