列舉查詢的劣勢簡直無需多言,有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 取乙個數中某些指定位。如想要取乙個整數...