以前做過一道題(191. number of 1 bits )講的是給定乙個數,求它二進位制下的1的個數。如果是對於乙個數,那麼可以用位運算黑魔法:(對末尾做與1的與運算)
class
solution
(object):
defhammingweight
(self, n):
ans=0
while n:
if n&1==1:
ans+=1
n=n>>1
return ans
今天碰到了乙個高階版的題目,(338. counting bits )題目要求是在o(
n)的時間和空間裡計算出[0
,n] 區間裡所有整數的二進位制下的1的個數(hamming weight - wikipedia)。o(
n)的時間要求是有點小苛刻的,首先遍歷一次[0
,n] 區間裡所有整數就需要o(
n),那麼每次小操作需要在o(
1)內才是可以的,首先想到的是能不能用上面leetcode191的做法來套用呢?不妨分析一下複雜度。
容易看出對於乙個數
n ,這樣的操作(主要是移位操作)時間複雜度是o(
log2
n),那麼利用斯特林公式可以估算區間[0
,n] 區間裡所有整數就需要大約 t(
n)=∑
i=1n
log2
i=lo
g2n!
∼log
2nn=
nlog
2n很遺憾的是並不能直接滿足題目中所要求的o(
n)複雜度,如果消耗一點空間換時間,利用上述的方法還是有機會降到o(
n)的動態規劃的思路:用r
es表示最終的結果,改寫上述方法為乙個一維的遞推式: re
s(n)
=res
([n2
])+n
&1也就是說一直維護這樣的乙個一維陣列,每次都記錄其結果,顯然時間複雜度是o(
n),空間也是o(
n),滿足題目要求。不過這並不是我首先想到的思路,我首先想到的是,直接從n的p進製下的數碼之和角度入手。
class
solution
(object):
defcountbits
(self, num):
ans=[0]
for x in range(1,num+1):
ans+=[ans[x>>1]+(x&1)]
return ans
用sp
(n) 表示n的p進製下的數碼之和,用ap
表示n!
的標準分解中
p 的冪次,即pa
p∤n!
,但pap
+1|n
! 。首先寫出表示式: n=
akpk
+...
+a1p
+a0=
(ak.
..a1
a0)p
容易得出每一項係數的準確公式: ai
=[np
i]−p
[npi
+1]
接著進行一下數學推導:sp
(n)=
∑i=0
kai=
∑i=0
k[np
i]−p
∑i=0
k[np
i+1]
=n+∑
i=1k
[npi
]−p∑
i=0k
[npi
+1]=
n−(p
−1)∑
i=1k
[npi
]−p[
npk+
1]=n
−(p−
1)∑i
=1∞[
npi]
−0=n
−(p−
1)ap
這個推導需要用到勒讓德公式,即n!
中p的冪次為∑∞
i=1[
npi]
,顯然這種辦法主要複雜度回耗在勒讓德公式上,可以觀察到
p 的冪次i達到
logp
n 時候,勒讓德公式後面的每一項均為0,即對於二進位制而言,完成一次勒讓德運算需要o(
log2
n),那麼對於原問題一共需要o(
nlog
2n) 的時間。
N數之和的問題
leetcode n個數之和問題 三數之和 給你乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c 使得 a b c 0 請你找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組。示例 給定陣列 nums 1,0,1,2,1,4 滿足要求的三元組集合...
N數碼解的存在問題
推廣二維n n的棋盤 n n的棋盤,n為奇數時,與八數碼問題相同。n為偶數時,空格每上下移動一次,奇偶性改變。稱空格位置所在的行到目標空格所在的行步數為空格的距離 不計左右距離 若兩個狀態的可相互到達,則有,兩個狀態的逆序奇偶性相同且空格距離為偶數,或者,逆序奇偶性不同且空格距離為奇數數。否則不能。...
關於 n 的p進製下有多少個後導零 的問題
給定數n,求n 的p進製下有多少個後導零。為了簡化問題,p保證為素數。如果用大整數寫法,解法可能會超時。易知,如果乙個數可以另外乙個數被整除,那麼成為這個數的幾倍數的數也可以被整除。利用這個思路,可以推出 如果可以被p整除,那麼這個數的幾倍數的數也可以被整除 即 如果可以使p進製下形成乙個後導0,那...