筆試面試中常見的位運算用法
本文是準備找工作過程中關於位運算的一些積累和記錄的整理。注意:部分位運算的處理結果依賴於變數所屬型別的字長,使用時請結合具體環境修改。
1.XOR應用
性質:滿足交換率、結合律,一個數與其自身異或結果為0。
(1)不用中間變數,交換兩數
a = a^b; b = b^a; //b = b^(a^b),thus b becomes the earlier a a = a^b; //a = (a^b)^a,thus a becomes the earlier b
擴充套件:不用異或,同樣也能不用中間變數,交換兩數
a = a - b; b = a + b; // b = (a - b)+ b, thus b becomes the earlier aa = b - a; // a = a - (a - b), thus a becomes the earlier b
但是這種方式引入了一個陷阱,如果a是一個很大的正數而b是一個很小的負數,那麼a-b就會溢位。雖然在b=a+b時可能會通過再一次溢位從而獲得真實的a的值,不推薦這種利用未定義行為的解法。
如何理解這種解法?其實第一行是a=a-b還是a=a+b再或者是a=a*b都可以,對應地在第二行把b通過這個式子和b本身的運算求出a即可,再在第三行利用ab的組合值以及原先的a求解b。明顯地,使用*比+或-更容易溢位。理解後,完全不必死記硬背這三個式子,看成是解方程就不難了。
(2)尋找只出現1次的一個數,其他數出現偶數次(或尋找唯一一個出現奇數次的數,其他數出現偶數次)
解法:全部數做XOR,最後的結果就是要找的數。
擴充套件:尋找出現奇數次的數,其他不必尋找的數只出現偶數次。
常見的面試題擴充套件,思路還是原來的思路,先全部XOR一遍,在獲得的結果上,對每一位為1(即可能有兩個不同的數,二進位制標識中該位不同)進行分組,構造出所有待找出的數。
這麼概括很抽象,看一道具體的筆試題吧,通過解題就容易理解了。
(小米2013校招筆試題)一個數組裡,除了三個數是唯一出現的,其餘的都出現偶數個,找出這三個數中的任一個。比如陣列元素為【1, 2,4,5,6,4,2】,只有1,5,6這三個數字是唯一出現的,我們只需要輸出1,5,6中的一個就行。
(3)NIM遊戲的狀態分析
請參考《程式設計之美》1.12 NIM(2) “拈”遊戲分析。其核心是,兩種完全不同的狀態(安全狀態和不安全狀態)的XOR值恰為0和1。
2.加法,不用+-*/做加法(《劍指Offer》面試題47)
迭代版本(《劍指Offer》面試題47)
int Add(int num1,int num2) { int sum,carry; do { sum = num1^num2; carry= (num1 & num2)<<1; num1 = sum; num2 = carry; } while (num2!=0) return num1; }
遞迴版本(CareerCup 20.1)
int add_no_arithm(int num1,int num2) { if(num2 == 0) return num1; int sum = a^ b; int carry = (a&b)<<1; return add_no_arithm(sum,carry); }
3.求兩數的平均數 ,不用-、*、/求兩數的平均數
似乎是出自《程式設計師面試寶典》,但是我在第三版第12章沒找到原題。用下面的程式碼就能“神奇地”獲得兩個整型的平均值
int average(int x,int y) { return ( (x&y) + ( (x^y)>>1 ) ); }
4.不用*和/做除法(《演算法設計手冊》面試題1-28)
縱觀第2、3、4條可以發現,如果問題限制不允許使用某種四則運算子以及%,就可以在位運算上打主意了。
5.二進位制中1的個數
不要覺得很trick,這是K&R提到過的。值得注意的是,如果使用C實現,為了避免實現定義不同造成的結果不同,需要把該變數轉化為無符號型。
int bitcount(unsigned x) { int b; for(b=0;x|=0;x>>=1) if(x&01) b++; return b; }
事實上K&R習題2-9提到了一種更快的演算法:
int bitcount(unsigned x) { int b; for(b=0;x!=0;x&= x-1) b++; return b; }
6.從無符號型x的第p位開始,取n位(K&R)
//最低位是第0位 unsigned getbits(unsigned x,int p, int n) { return (x>>(p+1-n)) & ~(~0<<n); }
7.利用同餘的性質和位運算加速的輾轉相減求最大公約數法(《C語言參考手冊》第七章)
unsigned binary_gcd(unsigned x, unsigned y) { unsigned temp; unsigned common_power_of_two = 0; if(x==0) return 0; if(y==0) return 0; /*find the largest power of two that divides both x and y*/ while(((x|y)&1)==0) { x >>= 1; y >>= 1; ++common_power_of_two; } while((x &1) == 0) x >>= 1; while(y) { /*x is odd and y is nonzero here*/ while((y&1)==0) y >>= 1; /*x and y are odd here*/ temp = y; if (x>y) y = x - y; else y = y-x; x = temp; /*Now x has the old value of y,which is odd. y is even,because it is the difference of two odd numbers therefore it will be right-shifted at least once on the next iteration.*/ } return (x<<common_power_of_two); }
8.不用大於小於號,求兩數較大值(CareerCup 19.4)
int getMax(int a,int b) { int c = a - b; int k = (c>>31)&0x1; int max = a-k*c; return max; }
在不允許使用>、<以及任何判斷語句時,使用移位判斷一個數的正負性是常用技巧,如《深入理解計算機系統》2.3.7節習題2.42中求補碼對給定2的冪的商的解法。這個問題以及求解涉及到補碼的表示和運算的知識,在此不進行詳述,有興趣的讀者可以自行查閱。
9.實現位向量
10.其他
相關推薦
筆試面試中常見的位運算用法
本文是準備找工作過程中關於位運算的一些積累和記錄的整理。注意:部分位運算的處理結果依賴於變數所屬型別的字長,使用時請結合具體環境修改。 1.XOR應用 性質:滿足交換率、結合律,一個數與其自身異或結果為0。 (1)不用中間變數,交換兩數 a = a^b; b = b^a; //b =
java 演算法題 - 面試中常見的位操作演算法題
前言 上一篇部落格 聊一聊 Android 中巧妙的位操作 中,我們講解了 java 中常用的位運算及常用應用場景,今天,讓我們一起來看一下,面試中常見的位操作的演算法題。 兩個只出現一次的數字 【題目描述】一個整型數組裡除了兩個數字之外,其他的數字都出現了兩次。請寫程
程式設計中位運算用法總結
位運算應用口訣清零取反要用與,某位置一可用或 若要取反和交換,輕輕鬆鬆用異或 移位運算 要點 1 它們都是雙目運算子,兩個運算分量都是整形,結果也是整形。 2 "<
Java中的位運算符
post 得出 進制數 運算 運算符 ring 位運算 邏輯 異或 (轉載聲明: 出處:http://blog.csdn.net/vebasan/article/details/6193916 作者:vebasan ) 位運算符主要針對二進制,它包括了:“與”、
位運算和enum中的位運算
bsp AR 分享 lin audition tis ati com pre 1、位邏輯非運算 ~ 位邏輯非運算是單目的,只有一個運算對象。位邏輯非運算按位對運算對象的值進行非運算,即:如果某一位等於0,就將其轉變為1;如果某一位等於1,就將其轉變為0。 比如,對二
C語言結構體中冒號(位域)用法
位域出現的原因是由於某些資訊的儲存表示只需要幾個bit位就可以表示而不需要一個完整的位元組,同時也是為了節省儲存空間和方便處理。 typedef struct bit_struct { int &n
Python 中的位運算(部分)
真值表: >>> 1 & 1 1 >>> 1 & 0 0 >>> 0 & 1 0 >>> 0 & 0 0 >>> 1 | 1 1 >>> 1 |
面試中常見的陣列的操作:遍歷,最值,反轉,氣泡排序,二分查詢(附程式碼)
陣列:儲存同一種資料型別的多個元素的容器;陣列中的索引從0開始,最大編號是陣列的長度-1(減1); 下面給大家列出陣列常見的幾種操作: A 遍歷 /** * 遍歷 */ public static void printArray(int
java中的位運算總結
轉自:https://www.cnblogs.com/liaopeng/p/8436155.html 1.^(亦或運算) ,針對二進位制,相同的為0,不同的為1 public static void main(String[] args) { System.out.println
js中的位運算
不變 應該 困難 ring 比較 裝逼 個數 exp symbol 我們可能很少在編程中用位運算,如果沒深入學習,可能也很難理解。平時的數值運算,其實是要先轉換成二進制再進行運算的,而位運算就是直接進行二進制運算,所以位運算的執行效率肯定是更高的。下面通過一些實例來加深對位
那些年,面試中常見的資料結構基礎和演算法題(下)
前言 這是 資料結構和演算法面試題系列的下半部分,這部分主要是演算法類 包括二分查詢、排序演算法、遞迴演算法、隨機演算法、揹包問題、數字問題等演算法相關內容。本系列完整程式碼在 github 建了個倉庫,所有程式碼都重新整理和做了一些基本的測試,程式碼倉庫地址在這裡: shishujuan/dsalg
java中的位運算
由於位運算是二進位制運算,不要與一些八進位制數搞混,java中二進位制數沒有具體的表示方法。 public class BitMath{ public static void main(String[] args){ System.out.println
面試中常見JS開發測試題
在前端很少有機會接觸到演算法,大多都互動性的操作,然而從各大公司面試來看,演算法依舊是考察的一方面。下面這篇文章就給大家總結了在前端JS面試中常見的測試題問題,有需要的朋友們可以參考借鑑,下面來一起看看吧。 前言 學習資料結構與演算法對於工程師去理解和分析問題都
連結串列專題——面試中常見的連結串列問題
宣告:連結串列定義如下: //Java: class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } //C++: typedef struct
程式設計師面試中常見的雜湊表,到底是什麼?
作者 | 倪升武責編 | 胡巍巍我所寫的這些資料結構,都是比較經典的,也是面試中經常會出現的,這
#Java面試中常見的11道題,你會了幾道?
大家在平常面試java的過程中都會遇到哪些難題呢?還有一些即將去面試java的童鞋們,你們想知道技術面試中會涉及到哪些點嗎? 如果有想學習java的程式設計師,可來我們的java學習扣qun:943111692,免費送java的視訊教程噢!我整理了一份適合18年學習的java乾貨,送給每
面試中常見的字串庫函式程式設計
下面對一些常見的關於字元的庫函式進行實現,這些也是通常面試中所問的一些問題,需要注意的是有些看起來很簡單,但是一定要考慮一些邊界條件,否則很容易出錯. strcpy實現 char* strcpy(char* dst,const char* src){
校招面試中常見的 MySQL 考察難點和熱點
基本架構 MySQL是典型的三層架構模式,在平常使用中對MySQL問題排查和優化,也應該針對具體問題,從對應的層解決問題 服務層:經典的C/S架構,主要是處理連線和安全驗證。 核心層:處理MySQL核心業務。 查詢分析,優化,快取和內建函式 。 內建的檢視,儲存過程,觸發器。 儲存引擎層:儲存引擎
嵌入式面試中常見的問答題(執行緒程序、TCP等)
以下內容源於網路資料的學習整理,如有侵權,請告知刪除。 一、執行緒、程序的區別聯絡 個人理解:程序相當於一個執行中的程式,執行緒相當於程式中的某些函式。(實際程式設計也是如此) (1)這些函式都有獨立的執行入口、順序執行序列、出口。 (2)但這些函式不能獨立存
c++中的位運算相關規律總結和口訣
位運算應用口訣清零取反要用與,某位置一可用或若要取反和交換,輕輕鬆鬆用異或 左移與右移--<<與>> a<<n <=> a*(2^n) 例如:a<<1 <=> a*2 a>>n <=