[算法] 举一反三之n重复数组中找唯一m重复异类数
n重復數組,是指數組中的數字都出現n次;
唯一m重復異類數,是指存在唯一一個沒出現n次,只出現了m次的數;
這里我簡記它為nX+my問題,求解y,其中m < n,數組中都是整數;
?
3X+y問題
一直沒有精力刷leetcode,今天查問題無意中看到了leetcode 137:給定一個非空整數數組,除了某個元素只出現一次以外,其余每個元素均出現了三次;找出那個只出現了一次的元素。要求時間復雜度O(n),空間復雜度O(1);
沒有在第一時間想到思路,于是花時間研究了一下;
這是一個3X+y的問題;先給出最優解:
a, b = 0, 0for num in nums:a = (a ^ num) & ~bb = (b ^ num) & ~areturn a?
在2X+y問題中,方法是使用異或操作一遍全數組,最終結果就是那個異類數,但從未深入想過為什么異或會對2X+y問題有效,因而也就無法想通為什么直接異或會對3X+y問題無效;
再看一遍異或的特點:
0 ^ 0 = 0 1 ^ 0 = 1 0 ^ 1 = 1 1 ^ 1 = 0仔細看看,這是因為異或可以讓一個信息位(前面的那個1bit數),在接收到有效信息量(后面的那個1bit數,值為1時為有效)的時候,產生二態變化;
因而如果要解決3X+y問題,就需要有一個可以產生三態變化的操作符,單純的異或是肯定不行的,因為要對一個信息位保存三種狀態,至少需要兩個信息位,因而在原本的數字變量空間上操作是不夠的;
假定這個三態異或操作用符號^3表示;然后用兩個信息位(b, a)保存狀態,于是三態異或在接收到有效信息量(1)時的運算特點如下(接收到無效信息量0時不產生變化):
(0, 0) ^3 1 = (0, 1) (0, 1) ^3 1 = (1, 0) (1, 0) ^3 1 = (0, 0)這個三態變化過程,其實是正常的兩位二進制數進位加法的一個修改,修改處在于,對于二進制10,再加1時,直接跳過11回到00;
因而這個狀態變化過程可描述為:
可見a與b的變化規律相似,都要求對方為0時自己進行二態變化,對方為1時自己為0,于是上面的最優解的計算過程就很容易寫出來了:
a = (a ^ num) & ~bb = (b ^ num) & ~a3X+2y問題
等等,為什么是return a,而不是return b呢?
首先,上面這段代碼里的a、b各是一個數字,它位的每個二進制位組合起來,保存了對整個數組^3操作過程中每個二進制位的狀態變化;
因為這個^3操作過程中,低位a在第一狀態有效,因而要求3X+y問題,需要return a;
因而,如果題目改為:給定一個非空整數數組,除了某個元素只出現兩次以外,其余每個元素均出現了三次;找出那個只出現了兩次的元素。
求解這個3X+2y問題,答案也就出來了,計算過程同上,而因為高位b在第二狀態有效,因而return b即可;
4X+2y問題
再發散思維,改題目:給定一個非空整數數組,除了某個元素只出現兩次以外,其余每個元素均出現了四次;找出那個只出現了兩次的元素。
沿著上面的思路,需要做一個四態異或操作符^4,同樣需要兩個信息位進行狀態存儲,它對于有效信息(1)的運算特點如下:
(0, 0) ^4 1 = (0, 1) (0, 1) ^4 1 = (1, 0) (1, 0) ^4 1 = (1, 1) (1, 1) ^4 1 = (0, 0)這就是標準的兩位二進制數加法,狀態變化過程可描述為:
于是計算過程可寫為:
old_a = aa = (a ^ num)b = b ^ ((old_a ^ a) & ~a)其中(old_a ^ a) & ~a,意義為a由1變為0;
由于這個b的計算核心算子是異或,異或與否合用有危險,不把(old_a ^ a)引進來會出現bug;
因為要求的y出現2次,所以需要找第二狀態時的有效位,return b;
4X+3y問題
狀態數同時為4,計算過程同4X+2y,返回時找第三狀態時的有效位,因而也return b;
5X+4y問題
題目修改為:給定一個非空整數數組,除了某個元素只出現4次以外,其余每個元素均出現了5次;找出那個只出現了4次的元素。
狀態數上升到5,需要做一個五態異或操作符^5,需要3個信息位(c, b, a)做狀態存儲,對有效信息(1)的運算特點如下:
(0, 0, 0) ^5 1 = (0, 0, 1) (0, 0, 1) ^5 1 = (0, 1, 0) (0, 1, 0) ^5 1 = (0, 1, 1) (0, 1, 1) ^5 1 = (1, 0, 0) (1, 0, 0) ^5 1 = (0, 0, 0)狀態變化過程可描述為:
計算過程可寫為:
old_a = aa = (a ^ num) & ~cb = (b ^ ((old_a ^ a) & ~a)) & ~cc = (c ^ num) & ~b & ~a由于y出現的次數是4,高位c在狀態4時有效,因而返回c;
-----------------------------
測試代碼:
def X3_y1(nums):a, b = 0, 0for num in nums:a = (a ^ num) & ~bb = (b ^ num) & ~areturn adef X3_y2(nums):a, b = 0, 0for num in nums:a = (a ^ num) & ~bb = (b ^ num) & ~areturn bdef X4_y2(nums):a, b = 0, 0for num in nums:old_a = a a = (a ^ num)b = b ^ ((old_a ^ a) & ~a) return bdef X4_y3(nums):return X4_y2(nums)def X5_y4(nums):a, b, c = 0, 0, 0for num in nums:old_a = a a = (a ^ num) & ~cb = (b ^ ((old_a ^ a) & ~a)) & ~cc = (c ^ num) & ~b & ~areturn cprint (X3_y1([2, 3, 2, 2])) # 3 print (X3_y2([2, 3, 2, 3, 2])) # 3print (X4_y2([2, 2, 3, 2, 3, 2])) # 3 print (X4_y3([2, 2, 3, 2, 3, 3, 4, 3, 4, 4, 2])) #4 print (X4_y3([5, 5, 8, 5, 8, 8, 5])) # 8print (X5_y4([5, 5, 8, 5, 8, 8, 5, 8, 5])) # 8?
執行結果:
3 3 3 4 8 8?
轉載于:https://www.cnblogs.com/ZisZ/p/10442182.html
總結
以上是生活随笔為你收集整理的[算法] 举一反三之n重复数组中找唯一m重复异类数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 索要 2.3 亿元赎金!富士康遭遇黑客攻
- 下一篇: 面试官问单表数据量大一定要分库分表吗?我