欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

匯總幾個(gè)在算法題以及工程開(kāi)發(fā)中常用的位運(yùn)算技巧

算法與數(shù)據(jù)結(jié)構(gòu) ? 來(lái)源:labuladong ? 2023-03-13 09:16 ? 次閱讀

位操作(Bit Manipulation)可以有很多技巧,有一個(gè)叫做 Bit Twiddling Hacks 的網(wǎng)站收集了幾乎所有位操作的黑科技玩法

但是這些技巧大部分都過(guò)于晦澀,我覺(jué)得可以作為字典查閱,沒(méi)必要逐條深究。但我認(rèn)為那些有趣的、有用的位運(yùn)算技巧,是我們每個(gè)人需要掌握的。

所以本文由淺入深,先展示幾個(gè)有趣(但沒(méi)卵用)的位運(yùn)算技巧,然后再匯總幾個(gè)在算法題以及工程開(kāi)發(fā)中常用的位運(yùn)算技巧。

幾個(gè)有趣的位操作

利用或操作`|`和空格將英文字符轉(zhuǎn)換為小寫

('a'|'')='a'
('A'|'')='a'

利用與操作`&`和下劃線將英文字符轉(zhuǎn)換為大寫

('b'&'_')='B'
('B'&'_')='B'

利用異或操作`^`和空格進(jìn)行英文字符大小寫互換

('d'^'')='D'
('D'^'')='d'

以上操作能夠產(chǎn)生奇特效果的原因在于 ASCII 編碼。ASCII 字符其實(shí)就是數(shù)字,恰巧空格和下劃線對(duì)應(yīng)的數(shù)字通過(guò)位運(yùn)算就能改變大小寫。有興趣的讀者可以查 ASCII 碼表自己算算,本文就不展開(kāi)講了。

不用臨時(shí)變量交換兩個(gè)數(shù)

inta=1,b=2;
a^=b;
b^=a;
a^=b;
//現(xiàn)在a=2,b=1

加一

intn=1;
n=-~n;
//現(xiàn)在n=2

減一

intn=2;
n=~-n;
//現(xiàn)在n=1

判斷兩個(gè)數(shù)是否異號(hào)

intx=-1,y=2;
booleanf=((x^y)

如果說(shuō)前 6 個(gè)技巧的用處不大,這第 7 個(gè)技巧還是比較實(shí)用的,利用的是補(bǔ)碼編碼的符號(hào)位。整數(shù)編碼最高位是符號(hào)位,負(fù)數(shù)的符號(hào)位是 1,非負(fù)數(shù)的符號(hào)位是 0,再借助異或的特性,可以判斷出兩個(gè)數(shù)字是否異號(hào)。

當(dāng)然,如果不用位運(yùn)算來(lái)判斷是否異號(hào),需要使用 if else 分支,還挺麻煩的。你可能想利用乘積來(lái)判斷兩個(gè)數(shù)是否異號(hào),但是這種處理方式容易造成整型溢出,從而出現(xiàn)錯(cuò)誤。

index & (arr.length - 1) 的運(yùn)用

我在單調(diào)棧解題套路中介紹過(guò)環(huán)形數(shù)組,其實(shí)就是利用求模(余數(shù))的方式讓數(shù)組看起來(lái)頭尾相接形成一個(gè)環(huán)形,永遠(yuǎn)都走不完:

int[]arr={1,2,3,4};
intindex=0;
while(true){
//在環(huán)形數(shù)組中轉(zhuǎn)圈
print(arr[index%arr.length]);
index++;
}
//輸出:1,2,3,4,1,2,3,4,1,2,3,4...

但模運(yùn)算%對(duì)計(jì)算機(jī)來(lái)說(shuō)其實(shí)是一個(gè)比較昂貴的操作,所以我們可以用&運(yùn)算來(lái)求余數(shù):

int[]arr={1,2,3,4};
intindex=0;
while(true){
//在環(huán)形數(shù)組中轉(zhuǎn)圈
print(arr[index&(arr.length-1)]);
index++;
}
//輸出:1,2,3,4,1,2,3,4,1,2,3,4...

簡(jiǎn)單說(shuō),& (arr.length - 1)這個(gè)位運(yùn)算能夠替代% arr.length的模運(yùn)算,性能會(huì)更好一些。

那問(wèn)題來(lái)了,現(xiàn)在是不斷地index++,你做到了循環(huán)遍歷。但如果不斷地index--,還能做到環(huán)形數(shù)組的效果嗎?

答案是,如果你使用%求模的方式,那么當(dāng)index小于 0 之后求模的結(jié)果也會(huì)出現(xiàn)負(fù)數(shù),你需要特殊處理。但通過(guò)&與運(yùn)算的方式,index不會(huì)出現(xiàn)負(fù)數(shù),依然可以正常工作:

int[]arr={1,2,3,4};
intindex=0;
while(true){
//在環(huán)形數(shù)組中轉(zhuǎn)圈
print(arr[index&(arr.length-1)]);
index--;
}
//輸出:1,4,3,2,1,4,3,2,1,4,3,2,1...

我們自己寫代碼一般用不到這個(gè)技巧,但在學(xué)習(xí)一些其他代碼庫(kù)時(shí)可能會(huì)經(jīng)??吹?,這里留個(gè)印象,到時(shí)候就不會(huì)懵逼了。

n & (n-1) 的運(yùn)用

n & (n-1)這個(gè)操作在算法中比較常見(jiàn),作用是消除數(shù)字n的二進(jìn)制表示中的最后一個(gè) 1

看個(gè)圖就很容易理解了:

26848936-c01d-11ed-bfe3-dac502259ad0.png

其核心邏輯就是,n - 1一定可以消除最后一個(gè) 1,同時(shí)把其后的 0 都變成 1,這樣再和n做一次&運(yùn)算,就可以僅僅把最后一個(gè) 1 變成 0 了。

1、計(jì)算漢明權(quán)重(Hamming Weight)

這是力扣第 191 題「位 1 的個(gè)數(shù)」:

2697b114-c01d-11ed-bfe3-dac502259ad0.png

就是讓你返回n的二進(jìn)制表示中有幾個(gè) 1。因?yàn)閚 & (n - 1)可以消除最后一個(gè) 1,所以可以用一個(gè)循環(huán)不停地消除 1 同時(shí)計(jì)數(shù),直到n變成 0 為止。

inthammingWeight(intn){
intres=0;
while(n!=0){
n=n&(n-1);
res++;
}
returnres;
}

2、判斷一個(gè)數(shù)是不是 2 的指數(shù)

力扣第 231 題「2 的冪」就是這個(gè)問(wèn)題。

一個(gè)數(shù)如果是 2 的指數(shù),那么它的二進(jìn)制表示一定只含有一個(gè) 1:

2^0=1=0b0001
2^1=2=0b0010
2^2=4=0b0100

如果使用n & (n-1)的技巧就很簡(jiǎn)單了(注意運(yùn)算符優(yōu)先級(jí),括號(hào)不可以省略):

booleanisPowerOfTwo(intn){
if(n<=?0)?return?false;
????return?(n?&?(n?-?1))?==?0;
}

a ^ a = 0 的運(yùn)用

異或運(yùn)算的性質(zhì)是需要我們牢記的:

一個(gè)數(shù)和它本身做異或運(yùn)算結(jié)果為 0,即a ^ a = 0;一個(gè)數(shù)和 0 做異或運(yùn)算的結(jié)果為它本身,即a ^ 0 = a。

1、查找只出現(xiàn)一次的元素

這是力扣第 136 題「只出現(xiàn)一次的數(shù)字」:

26af6e26-c01d-11ed-bfe3-dac502259ad0.png

對(duì)于這道題目,我們只要把所有數(shù)字進(jìn)行異或,成對(duì)兒的數(shù)字就會(huì)變成 0,落單的數(shù)字和 0 做異或還是它本身,所以最后異或的結(jié)果就是只出現(xiàn)一次的元素:

intsingleNumber(int[]nums){
intres=0;
for(intn:nums){
res^=n;
}
returnres;
}

2、尋找缺失的元素

這是力扣第 268 題「丟失的數(shù)字」:

26cc5d60-c01d-11ed-bfe3-dac502259ad0.png

給一個(gè)長(zhǎng)度為n的數(shù)組,其索引應(yīng)該在[0,n),但是現(xiàn)在你要裝進(jìn)去n + 1個(gè)元素[0,n],那么肯定有一個(gè)元素裝不下嘛,請(qǐng)你找出這個(gè)缺失的元素。

這道題不難的,我們應(yīng)該很容易想到,把這個(gè)數(shù)組排個(gè)序,然后遍歷一遍,不就很容易找到缺失的那個(gè)元素了嗎?

或者說(shuō),借助數(shù)據(jù)結(jié)構(gòu)的特性,用一個(gè) HashSet 把數(shù)組里出現(xiàn)的數(shù)字都儲(chǔ)存下來(lái),再遍歷[0,n]之間的數(shù)字,去 HashSet 中查詢,也可以很容易查出那個(gè)缺失的元素。

排序解法的時(shí)間復(fù)雜度是 O(NlogN),HashSet 的解法時(shí)間復(fù)雜度是 O(N),但是還需要 O(N) 的空間復(fù)雜度存儲(chǔ) HashSet。

這個(gè)問(wèn)題其實(shí)還有一個(gè)特別簡(jiǎn)單的解法:等差數(shù)列求和公式。

題目的意思可以這樣理解:現(xiàn)在有個(gè)等差數(shù)列0, 1, 2,..., n,其中少了某一個(gè)數(shù)字,請(qǐng)你把它找出來(lái)。那這個(gè)數(shù)字不就是sum(0,1,..n) - sum(nums)嘛?

intmissingNumber(int[]nums){
intn=nums.length;
//雖然題目給的數(shù)據(jù)范圍不大,但嚴(yán)謹(jǐn)起見(jiàn),用long類型防止整型溢出
//求和公式:(首項(xiàng)+末項(xiàng))*項(xiàng)數(shù)/ 2
longexpect=(0+n)*(n+1)/2;
longsum=0;
for(intx:nums){
sum+=x;
}
return(int)(expect-sum);
}

不過(guò),本文的主題是位運(yùn)算,我們來(lái)講講如何利用位運(yùn)算技巧來(lái)解決這道題。

再回顧一下異或運(yùn)算的性質(zhì):一個(gè)數(shù)和它本身做異或運(yùn)算結(jié)果為 0,一個(gè)數(shù)和 0 做異或運(yùn)算還是它本身。

而且異或運(yùn)算滿足交換律和結(jié)合律,也就是說(shuō):

2^3^2=3^(2^2)=3^0=3

而這道題索就可以通過(guò)這些性質(zhì)巧妙算出缺失的那個(gè)元素,比如說(shuō)nums = [0,3,1,4]:

26e32ce8-c01d-11ed-bfe3-dac502259ad0.jpg

為了容易理解,我們假設(shè)先把索引補(bǔ)一位,然后讓每個(gè)元素和自己相等的索引相對(duì)應(yīng):

26f2ff92-c01d-11ed-bfe3-dac502259ad0.jpg

這樣做了之后,就可以發(fā)現(xiàn)除了缺失元素之外,所有的索引和元素都組成一對(duì)兒了,現(xiàn)在如果把這個(gè)落單的索引 2 找出來(lái),也就找到了缺失的那個(gè)元素。

如何找這個(gè)落單的數(shù)字呢,只要把所有的元素和索引做異或運(yùn)算,成對(duì)兒的數(shù)字都會(huì)消為 0,只有這個(gè)落單的元素會(huì)剩下,也就達(dá)到了我們的目的:

intmissingNumber(int[]nums){
intn=nums.length;
intres=0;
//先和新補(bǔ)的索引異或一下
res^=n;
//和其他的元素、索引做異或
for(inti=0;i
270699d0-c01d-11ed-bfe3-dac502259ad0.jpg

由于異或運(yùn)算滿足交換律和結(jié)合律,所以總是能把成對(duì)兒的數(shù)字消去,留下缺失的那個(gè)元素。

到這里,常見(jiàn)的位運(yùn)算差不多都講完了。這些技巧就是會(huì)者不難難者不會(huì),也不需要死記硬背,只要有個(gè)印象就完全夠用了。





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 計(jì)算機(jī)
    +關(guān)注

    關(guān)注

    19

    文章

    7549

    瀏覽量

    88737
  • ASCII
    +關(guān)注

    關(guān)注

    5

    文章

    172

    瀏覽量

    35219
  • Hash算法
    +關(guān)注

    關(guān)注

    0

    文章

    43

    瀏覽量

    7421

原文標(biāo)題:必知必會(huì)位運(yùn)算技巧手冊(cè)

文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【「從算法到電路—數(shù)字芯片算法的電路實(shí)現(xiàn)」閱讀體驗(yàn)】+內(nèi)容簡(jiǎn)介

    。本書力求從算法、芯片設(shè)計(jì)、軟件開(kāi)發(fā)等多個(gè)角度解讀基礎(chǔ)算法電路的設(shè)計(jì),涵蓋了溢出保護(hù)、有符號(hào)運(yùn)算、浮點(diǎn)運(yùn)算、
    發(fā)表于 11-21 17:14

    運(yùn)算

    運(yùn)算為了節(jié)省內(nèi)存空間,系統(tǒng)軟件中常將多個(gè)標(biāo)志狀態(tài)簡(jiǎn)單地組合在一起,存儲(chǔ)到一個(gè)字節(jié)(或字)中。C語(yǔ)言是為研制系統(tǒng)軟件而設(shè)計(jì)的,所以她提供了實(shí)現(xiàn)將標(biāo)志狀態(tài)從標(biāo)志字節(jié)中分離出來(lái)的
    發(fā)表于 03-10 15:07

    嵌入式開(kāi)發(fā)中常用的總線與接口匯總

    盤點(diǎn)嵌入式開(kāi)發(fā)中常用的總線與接口
    發(fā)表于 02-01 07:25

    Matlab編程中常用的優(yōu)化技巧

    用過(guò)Matlab的同學(xué)應(yīng)該都知道,Matlab的慢是出了名的,但是再慢也有優(yōu)化的方式,下面我們給出幾個(gè)Matlab編程中常用的優(yōu)化技巧。??講優(yōu)化方法之前,首先要說(shuō)的就是Matlab中用tic
    發(fā)表于 02-19 06:40

    算法類型在運(yùn)動(dòng)控制中常用的有哪些

    算法類型在運(yùn)動(dòng)控制中常用的加減速控制算法有指數(shù)、直線、S型曲線和三角函數(shù)加減速控制算法。PS:S型曲線加減速關(guān)注度指數(shù),近年在上升。沖擊類型和加加速度解釋剛性沖擊:速度發(fā)生突變,加速度
    發(fā)表于 09-03 08:57

    介紹開(kāi)發(fā)ESP8266開(kāi)發(fā)中常見(jiàn)的一些問(wèn)題

    ESP8266 wifi模塊開(kāi)發(fā)匯總 ESP8266 wifi模塊開(kāi)發(fā)匯總本文檔主要介紹開(kāi)發(fā)
    發(fā)表于 11-10 07:31

    嵌入式開(kāi)發(fā)過(guò)程中常用的庫(kù)函數(shù)有哪些

    嵌入式開(kāi)發(fā)過(guò)程中常用的庫(kù)函數(shù)有哪些?有何優(yōu)勢(shì)?
    發(fā)表于 02-25 07:07

    c語(yǔ)言常用算法

    非常實(shí)用的《c語(yǔ)言常用算法程序集》針對(duì)工程中常用的行之有效的算法而編寫,其主要內(nèi)容包括多項(xiàng)式的計(jì)算、復(fù)數(shù)
    發(fā)表于 04-11 16:41

    單片機(jī)常用PID濾波算法資料匯總

    單片機(jī)常用PID濾波算法資料匯總
    發(fā)表于 05-21 11:45 ?26次下載

    幾個(gè)Matlab編程中常用的優(yōu)化技巧

    用過(guò)Matlab的同學(xué)應(yīng)該都知道,Matlab的慢是出了名的,但是再慢也有優(yōu)化的方式,下面我們給出幾個(gè)Matlab編程中常用的優(yōu)化技巧。
    的頭像 發(fā)表于 02-08 15:18 ?3792次閱讀

    算法類型以及準(zhǔn)備策略

    今天就和大家聊聊大公司的面試環(huán)節(jié)經(jīng)常涉及的算法類型以及準(zhǔn)備策略。 問(wèn)題難度首先大家比較關(guān)心的就是面試時(shí)候出現(xiàn)的算法的難度,從我的個(gè)人經(jīng)驗(yàn)
    的頭像 發(fā)表于 09-02 10:50 ?1539次閱讀

    PCB中常用的快捷鍵匯總

    PCB中常用的快捷鍵匯總
    發(fā)表于 09-28 10:12 ?40次下載

    Vivado中常用TCL命令匯總

    Vivado是Xilinx推出的可編程邏輯設(shè)備(FPGA)軟件開(kāi)發(fā)工具套件,提供了許多TCL命令來(lái)簡(jiǎn)化流程和自動(dòng)化開(kāi)發(fā)。本文將介紹Vivado中常用的TCL命令,并對(duì)其進(jìn)行詳細(xì)說(shuō)明,
    的頭像 發(fā)表于 04-13 10:20 ?3939次閱讀

    STM32開(kāi)發(fā)中的運(yùn)算以及帶操作

    STM32開(kāi)發(fā)中的運(yùn)算以及帶操作? 運(yùn)算是計(jì)算
    的頭像 發(fā)表于 02-02 14:38 ?1803次閱讀

    分享幾個(gè)嵌入式中常用的GUI

    交互,完成各種操作,可提高工作效率以及用戶體驗(yàn)。接下來(lái)看一下我們開(kāi)發(fā)中常用的GUI框架有哪些吧~二、開(kāi)源輕量級(jí)顯示框架LVGLLVGL(LightandVersat
    的頭像 發(fā)表于 04-06 08:09 ?1783次閱讀
    分享<b class='flag-5'>幾個(gè)</b>嵌入式<b class='flag-5'>中常用</b>的GUI