位運算和位元陣列

2021-09-25 07:45:41 字數 1751 閱讀 4335

列舉查詢的劣勢簡直無需多言,有n個元素,那複雜度就是o(n),查詢乙個元素是如此地費勁!倘若我需要你做m次查詢,複雜度就是o(n*m)。當然,我們可以用對分查詢來優化,但是對分查詢需要乙個有序的陣列,通過每次對折一半的方法,最終的複雜度是o(logn),小於線性。但是這還是不能讓我們滿意。

在解決圖論問題時,我們用到了dfs。dfs要求不能經過重複的點,所以我們需要建立乙個陣列來記錄走過的點,那麼我們dfs到乙個點時會用查詢演算法麼…

寫乙個for迴圈…遍歷整個陣列?還是說,加入乙個元素就來乙個排序,最後用對分?線段樹?

別看這名字專業,其實這是乙個很常用的技巧。

使用這種方法,可以使查詢乙個元素的複雜度變為o(1)。真的是o(1)!!!

在做dfs的時候,為了標記這個點有沒有被搜尋過,我們會用乙個bool型別的陣列vis來記錄搜到的每乙個點,我們如果搜到了點5,那就記錄vis[5]=true(初始化都是false)。所以我們下次搜到乙個點,比如搜到了點5,我們只需要if(vis[5])就好了。如果是true,就說明被搜過。

這是典型的犧牲空間換時間的做法(回憶一下桶排序)

當然,代價是你需要很大的空間來滿足。

因此真正的雜湊雜湊表還會對存入的元素取模,這裡不細講,但是,不論他怎麼取模,都不會勝過我們接下來要講的神奇的陣列——位元陣列!

在此之前,先普及乙個知識:位運算

我給你乙個提綱吧。

每乙個數都有自己的二進位制,計算機中,乙個1或者0的二進位制位都是佔1byte(位元)的。乙個int變數最大可以存到21億,所以她的二進位制位差不多有32個,佔4kb左右。比如乙個int型別的1,它在計算機的二進位制裡就是00000000000000000000000000000001,前面有31個0!

設二進位制數a=1101,b=1001

這個陣列也是乙個int型別陣列,然而它乙個單位可以儲存31個數。比如說a[1]可以存31個數字!

我們已經知道,乙個int可以存32個2進製位,那麼我們可以把每乙個2進製位都利用起來儲存資料!比如乙個int的第24個二進位制位我們設定為1,就代表存在24這個數了,是不是跟上文的vis很像呢?

我們這麼儲存乙個資料:

void

addnum

(int x)

正如我們所言,每乙個data對應的儲存單位都可以達到31個。

當我們讀入40的時候,它會存在data[1]中,存在data[1]中的第八位。那麼他就左移8位,也就是把這個1放到第八位上。然後取或運算,保留了原來的資料,原來裡面存的1還是1。

然後我們這樣讀取乙個資料:

bool find

(int x)

確切的說是詢問這個數存在與否。例如我們詢問40,那麼他就會找到data[1],右移那麼多位然後與乙個1,如果真的存在這個數,那與的結果必然是1,也就是返回了true了。

完整**:

#include

using namespace std;

#define maxm 10001

int data[maxm]

,n,m,num;

void

addnum

(int x)

bool find

(int x)

intmain()

if(find

(m)) cout<<

"yes"

;else cout<<

"no"

;return0;

}

Python位運算 338 位元位計數

參考鏈結 又是刷題找演算法盲點的時候了 題目在此 給定乙個非負整數 num。對於 0 i num 範圍中的每個數字 i 計算其二進位制數中的 1 的數目並將它們作為陣列返回。示例 1 輸入 2 輸出 0,1,1 示例 2 輸入 5 輸出 0,1,1,2,1,2 高階 要求演算法的空間複雜度為o n ...

leetcode 338 位元位計算(位運算)

目錄 題目描述 lowbit函式介紹 題目解析 c 完整 題目 力扣 leetcode 給定乙個非負整數 num。對於 0 i num 範圍中的每個數字 i 計算其二進位制數中的 1 的數目並將它們作為陣列返回。示例 1 輸入 2 輸出 0,1,1 示例 2 輸入 5 輸出 0,1,1,2,1,2 ...

位運算子和位運算

一 按位與 運算子 1 運算規則 參加運算的兩個 資料,按二進位進行 與 運算,如果兩個相應的二進位都為1,則該位的結果值為1,否則為0,即 0 0 0,0 1 0,1 0 0,1 1 1.2 用途 1 清零 運算物件 原來的數中為1的位,新數中相應位為0。2 取乙個數中某些指定位。如想要取乙個整數...