next number:輸入乙個正整數num
,求和num
的二進位制表示中1
的數量相同的最接近的兩個數。
為了讓num
變大,要保證將左邊的乙個0
翻轉為1
,並將右邊的1
翻轉為0
。因為只讓num
變大一點點,所以應該翻轉最右邊的0
,同時還要保證0
的右邊有1
,所以應該翻轉的是第2
個0
序列最右邊的0
。使用c0
儲存第1
個0
序列的長度,使用c1
儲存第1
個1
序列的長度,則應該將第c0 + c1
位翻轉為1
,同時將c1 - 1
個1
放在末尾。當第1
個1
序列向左延伸到第31
位時,不存在大一點的數。
為了讓num
變小,要保證將左邊的乙個1
翻轉為0
,並將右邊的0
翻轉為1
。因為只讓num
變小一點點,所以應該翻轉最右邊的1
,同時還要保證1
的右邊有0
,所以應該翻轉的是第2
個1
序列最右邊的1
。使用c1
儲存第1
個1
序列的長度,使用c0
儲存第1
個0
序列的長度,則應該將第c1 + c0
位翻轉為0
,同時將c1 + 1
個1
放在該位後。當第1
個0
序列向左延伸到第32
位時,不存在小一點的數。
更巧妙的是使用算術計算的方法。在class
solution;}
private
:int
nextcloset
(int num)
while
((n &
0x1)==1
)if(c1 + c0 ==31)
return-1
;int mask =
1<<
(c0 + c1)
; num |
= mask;
num &=~
(mask -1)
; num |=(
1<<
(c1 -1)
)-1;
return num;
}int
prevcloset
(int num)
if(n ==0)
return-1
;while
((n &
0x1)==0
)int mask =
1<<
(c0 + c1 +1)
; num &=~
(mask -1)
; mask =((
1<<
(c1 +1)
)-1)
<<
(c0 -1)
; num |
= mask;
return num;}}
;
nextcloset()
中,通過+ 2 ^ c0 - 1
實現0
序列轉1
序列,再+ 1
實現c1 + c0
位和1
序列翻轉,最後再+ 2 ^ (c1 - 1) - 1
實現末尾轉1
序列。在prevcloset()
中,通過- (2 ^ c1 - 1)
實現1
序列轉0
序列,再- 1
實現c0 + c1
位和0
序列翻轉,最後再- (2 ^ (c0 - 1) - 1)
實現末尾轉0
序列。
class
solution;}
private
:int
nextcloset
(int num)
while
((n &
0x1)==1
)if(c1 + c0 ==31)
return-1
;return num +(1
<< c0)+(
1<<
(c1 -1)
)-1;
}int
prevcloset
(int num)
if(n ==0)
return-1
;while
((n &
0x1)==0
)return num -(1
<< c1)-(
1<<
(c0 -1)
)+1;
}};
程式設計師面試金典
1.有個小孩正在上樓梯,樓梯有n階台階,小孩一次可以上1階 2階 3階。請實現乙個方法,計算小孩有多少種上樓的方式。為了防止溢位,請將結果mod 1000000007 給定乙個正整數intn,請返回乙個數,代表上樓的方式數。保證n小於等於100000。int countways int n retu...
程式設計師面試金典 2 2
return kth to last 返回單鏈表中倒數第k個元素。下面會分別使用遞迴和非遞迴的方法來解決這道題,一般來說遞迴的方法寫起來更容易,但是效率一般不是最好的,比如這道題遞迴解法的 量大約是非遞迴解法的一半,但是時間複雜度依然是o n 遞迴解法。這種方法的本質是先遍歷到鍊錶尾部,最後再返回的...
程式設計師面試金典 2 4
partition 編寫 將鍊錶中小於x的元素放在鍊錶的前半部分,大於x的元素放在鍊錶的後半部分,沒有順序要求。如果是陣列的話,根據x對陣列進行劃分的方法類似於快排。對於鍊錶會更簡單一些,可以直接將原始鍊錶拆分為兩個鍊錶,乙個中所有元素比x小,乙個中所有元素比x大,最後再進行連線。通過在鍊錶中使用b...