469,位運算求最小的2的n次方

2021-02-19 數據結構和算法

Promise yourself to be so strong that nothing can disturb your peace of mind. 

答應自己要堅強,不讓任何事物煩擾內心的平靜。

給一個函數f(x),返回一個不小於x的最小的2的n次方。描述的比較繞口,舉個例子。

f(7)=8

f(9)=16

f(30)=32

f(64)=64

注意:

x是正整數

0<x<Integer.MAX_VALUE

我們看到返回的結果都是2的n次方,並且是不小於x的最小的2的n次方。如果把2的n次方轉換成二進位我們就會發現,只有一個位上是1,其他位上全部是0,隨便舉幾個數字看一下

所以最簡單的一種方式就是通過循環來計算,先用x和1比較,如果大於1,那麼1就往左移一位,繼續比較……,一直這樣下去,直到不小於為止,原理比較簡單,來看下代碼

1public int lowPower(int x) {
2    int n = 1;
3    while (x > n)
4        n <<= 1;
5    return n;
6}

代碼非常簡潔,基本沒什麼難度

再來看下位運算,我們隨便舉個例子,比如53,他的二進位位如下,如果要找到不小於53的最小的2的n次方,我們只需要把53的二進位位中最左邊的1往左移一位,其他的全部變為0即可。

所以一種最簡單的方式就是通過移位運算,把53最左邊的1全部往右邊鋪開,就變成了00111111,然後再加1就變成了了01000000。最後來看下代碼

1public int lowPower(int x) {
2    //這裡把最左邊的1全部往右邊鋪開
3    x |= x >>> 1;
4    x |= x >>> 2;
5    x |= x >>> 4;
6    x |= x >>> 8;
7    x |= x >>> 16;
8    //最後再加1返回
9    return x + 1;
10}

但是這裡有個小問題就是,如果x本來就是2的n次方,比如x是16,運算的結果就會變成32,與我們實際要求不符。所以這裡我們可以先讓x-1,然後再進行運算,所以正確答案應該是下面這樣

1public int lowPower(int x) {
2    //這裡把最左邊的1全部往右邊鋪開
3    //x--;
4    x -= 1;
5    x |= x >>> 1;
6    x |= x >>> 2;
7    x |= x >>> 4;
8    x |= x >>> 8;
9    x |= x >>> 16;
10    //最後再加1返回
11    return x + 1;
12}

或者也可以改成這樣,當然沒有上面的代碼簡潔

1public int lowPower(int x) {
2    if (x == 1)
3        return 1;
4    //這裡把最左邊的1全部往右邊鋪開
5    x -= 1;
6    x |= x >>> 1;
7    x |= x >>> 2;
8    x |= x >>> 4;
9    x |= x >>> 8;
10    x |= x >>> 16;
11    //執行完下面這行代碼,x相當於把
12    //後面的1全部減掉了,只留下最前
13    //面的那個1,也是2的n次方,
14    //只不過這個是小於原來x的最大的
15    //2的n次方
16    x -= x >> 1;
17    //然後我們再把它往左移一位,就變
18    //成了不小於原來x的最小的2的n次方
19    return x << 1;
20}

如果大家經常看源碼可能對這個算法比較了解,這是HashMap中專門計算數組長度的,我們知道HashMap是數組加鍊表的結構,數組的大小就是2的n次方,無論你傳入的大小是多少,他都會通過上面的計算。

長按上圖,識別圖中二維碼之後即可關注。

如果覺得有用就點個"贊"吧

相關焦點

  • C/C++語言中將一個正整數圓整為2的n次方的方法
    問題提出在數位訊號處理領域,常遇到需要將一個正整數向上圓整為2的n次方的數據的情況,如對採集到的時域信號做頻譜分析時,常要求數據點數必須滿足為2的n次方,滿足此種情況才可用傅立葉變換的基2快速算法,以達到較好的運算速度。
  • HashMap的容量為什麼是2的n次方
    i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //通過位運算找到數組中的下標位置,如果數組中對應下標為空,則可以直接存放下去 if ((p = tab[i = (n - 1) & hash]) == null)
  • 怎麼求一個數的n次方?
    怎麼求一個數的n次方?有興趣的朋友可以了解一下!一、前言excel是我們工作中經常使用的一款表格製作工具,它不僅僅只是用來製作表格,而在表格數據的處理方面也顯得非常突出。excel為我們提供了很多函數,對於一些常用簡單的函數我們應該要了解,這能大大提高我們的工作效率。
  • 快速冪與位運算
    以2^n為例,對於普通辦法,即使是long long類型的,求到2^31次方即會溢出。最末位為0表示該數是偶數,最末位為1表示該數為奇數| 運算:1個為1即為100111 |  11111 =11100X|1的結果就是把X二進位最末位強行變為1如果需要把二進位最末位變成0,對這個數X |
  • LeetCode-50.求X的N次方(Pow(x, n))
    = 1/4 = 0.25說明:-100.0 < x < 100.0n 是 32 位有符號整數,其數值範圍是 [−2^31, 2^31 − 1] 。 def helper(self, x: float, n: int) -> float: if n == 0: return 1.0 half = self.helper(x, n // 2) if n & 1 == 1: return half * half * x
  • x的n次方-1的因式分解及應用
    下面公式為初等數學中常用的2個在初高中大部分老師對於第二個公式都是直接讓記住,但如果不經常使用,勉強記住不僅容易記錯而且很容易忘記,還是理解了再記憶更加容易。今天小編介紹的是x的n次方-1的通用分解因式和他的證明,以及公式在等比數列前n項和and某個高等數學等價無窮小的證明中的使用。先上公式那麼這個公式有什麼用呢?1,求等比數列的前N項和雖然在初等數學教科書中用了倍差法推出了前n項和公式,但是我們也可以用上面的公式求。
  • 根號十的負二次方等於多少 √10的負2次方
    根號十的負二次方等於十分之一。根號10等於10的2分之1次方,10的2分之1次方的負2次方等於10的負1次方,等於10分之1。  根號  根號是一個數學符號,根號是用來表示對一個數或一個代數式進行開方運算的符號。
  • [洛穀日報第79期]二進位與位運算
    簡單來說,二進位基數為 2 ,只有 1 和 0二進位轉十進位對於一個二進位數,他的十進位數為從左往右的每一位乘上該位數的 2 次方(從第0位開始),例如 十進位轉二進位把上面的操作反過來,將十進位數除以 2 直到其為 0 ,每位的餘數即二進位的每一位。
  • 辦公小技巧:三種不同方法 求取單元格方根值
    Excel表格單元格計算常常會涉及到求取平方根或n次方根的情況,其中有的方根次數是已知的,例如求平方根或立方根,而有時求幾次方要根據上一級參數的值來決定,是個變量。那麼,到底用什麼方法在單元格中進行「方根」求取運算更合適呢?這要分情況而定。 1.
  • 歐拉猜想:n個整數的n次方之和等於另一個整數的n次方
    費馬大定理的具體的描述是:整數n >2時,關於x, y, z的方程 x^n + y^n = z^n 沒有正整數解。>如果n=4的情況下,費馬大定理是成立,那麼也就證明了n=8.n=12,n=16.......的情況下也是成立的。
  • 3,4,5的大表哥歐拉猜想:n個整數的n次方之和是另一個整數的n次方...
    費馬說在整數n>2時,A,B,C 沒有正整數解,他進一步推廣,並猜想了許多的相關等式都不成立,特別是那句著名的梗:我有一個絕妙的證明但太長了寫不下,深深的印在我們的腦海裡。也就是n=4,的倍數時的情形,比如說n=8,12,16.以此類推意思就是說只要證明了n=4的情況,也就證明了n=8,12,16等等,你明白額了嗎?但一個數學家在對付費馬大定理其中一個等式時會怎麼去嘗試呢?
  • 求極限小結
    關於求極限的詳述沒想到大家對求極限的關注的相對於其他的知識點多了很多,這也難怪,畢竟求極限是高數中最基礎也最重要的一部分
  • 別忽視對數運算中的小公式,關鍵時刻有大用處
    高考數學複習,別忽視對數運算中的小公式,關鍵時刻有大用處。對數公式(1)的用法是:真數的指數可以移到對數前面作為對數的係數,反過來,對數的係數也可以移到真數的頭上作為真數的指數,在對數運算中,這兩種用法都常常會用到。
  • 基本初等函數1 - 指數函數 - 指數與指數冪的運算2
    【3】無理數:無限不循環小數,如π、√2 (根號2)、√3 (根號3)等。(2)根式一般地,如果x^n=a,那麼x叫做a的n次方根,其中n>1,且n∈ N*(正整數)。當n是奇數時,正數的n次方根是一個正數,負數的n次方根是一個負數。
  • 根號是幾次方 根號是幾次方呢
    根號是1/n次方。根號表示的是對一個數或一個代數式進行開方運算。如果aⁿ=b,那麼a就是b的1/n次方。以平方根為例,一個數的算式平方根是這個數的1/2次方。1525年,路多爾夫在他的代數著作中,首先採用了根號,比如他寫4是2,9是3,但是這種寫法未得到普遍的認可與採納。直到十七世紀,法國數學家笛卡爾第一個使用了現今用的根號「√ ̄」。立方根符號出現得很晚,一直到十八世紀,才在一書中看到符號 的使用,比如25的立方根用 表示。以後,諸如√ ̄等等形式的根號漸漸使用開來。
  • 2的0次方為什麼等於1?
    、10、1又分別可以使用10^3(10的3次方)、10^2、10^1、10^0來表示,所以十進位計數法的數位都是10^n的形式,n從右往左分別為0、1、2、3、4.....,10稱作十進位計數法的基數或底,n稱作指數。
  • 數據的表示和運算
    前言◆ ◆ ◆ ◆這期本來是想寫hashMap的,但是裡面哈希和擴容之類的,很多都是位運算,不太熟悉的同學看著會很難受,所以先補充一些計算機組成的知識。進位轉換◆ ◆ ◆ ◆計算機中,二進位是最廣泛的一種數制,以高低電平來表示二進位。
  • C語言丨關於位運算的使用,只需掌握這4個簡單示例!
    位運算是指按二進位進行的運算。在系統軟體中,常常需要處理二進位位的問題。C語言提供了6個位操作運算符。這些運算符只能用於整型操作數,即只能用於帶符號或無符號的char,short,int與long類型。
  • 數學學霸的解題思路1「降低次方和次元」
    解題思路1「降低次方和次元」所謂次方,就是例子當中x上面的n:x n同理,x 3 就是3次方x 4 就是4次方。降低次方的目的之一,就是讓運算變得更輕鬆。比如說,我們將(a+b) n 進行展開:可以看出,隨著次方的升高,整個運算就變得更加複雜。反過來,如果能夠降低次方,那麼複雜的問題一下子就變得簡單了。到底在怎樣的情況下能夠降低次方呢?我們拿「1開3次方」來舉例子。
  • 基本初等函數1 - 指數函數 - 指數與指數冪的運算
    2.1.1 指數與指數冪的運算為可更好地學好本節的內容,先複習初中關於乘方的相關知識。(1)知識回顧:【1】乘方:求n個相同因數(a)乘積的運算叫乘方,即 a×a×a×……×a(共n個a相乘),記做:a^n(沒法列印用此代替,按課本寫法)。