15 | 二分查找(上):如何用最省内存的方式实现快速查找功能?
思考題:假設(shè)有 1000 萬個(gè)整數(shù)數(shù)據(jù),每個(gè)數(shù)據(jù)占 8 個(gè)字節(jié),如何設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)和算法,快速判斷某個(gè)整數(shù)是否出現(xiàn)在這 1000 萬數(shù)據(jù)中?希望不要占用太多的內(nèi)存空間,最多不要超過 100MB
二分思想
| 查找算法 | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?特點(diǎn) |
| 二分查找 | 1、二分查找針對(duì)的是一個(gè)有序的數(shù)據(jù)集合,查找思想有點(diǎn)類似分治思想。每次都通過跟區(qū)間的中間元素對(duì)比,將待查找的區(qū)間縮小為之前的一半,直到找到要查找的元素,或者區(qū)間被縮小為 0。 2、時(shí)間復(fù)雜度O(logn)的 查找速度 |
對(duì)數(shù)時(shí)間復(fù)雜度在大數(shù)據(jù)量級(jí)的情況下有時(shí)候比常量級(jí)別查找速度O(1)還要高效
二分查找的實(shí)現(xiàn)
假設(shè)數(shù)組中不存在重復(fù)的元素:
public int bsearch(int[] a, int n, int value) {int low = 0;int high = n - 1;while (low <= high) {int mid = (low + high) / 2;if (a[mid] == value) {return mid;} else if (a[mid] < value) {low = mid + 1;} else {high = mid - 1;}}return -1; }二分查找的應(yīng)用局限性
| 查找算法 | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 局限性 |
| 二分查找 | 1、依賴數(shù)組,如果數(shù)據(jù)存在鏈表上,不能使用 2、依賴數(shù)組,對(duì)內(nèi)存空間有要求,如果剩余連續(xù)空間過小,數(shù)據(jù)量大,也不能用二分查找 3、動(dòng)態(tài)變化的數(shù)據(jù)不適合用二分查找(還是因?yàn)閿?shù)據(jù)結(jié)構(gòu)的特點(diǎn)對(duì)插入、刪除操作不友好,維護(hù)成本太高) 4、對(duì)于插入、刪除操作較少(或者是歷史靜態(tài)數(shù)據(jù)),一次排序多次查找適合二分查找 |
?
回答開篇
內(nèi)存限制是 100MB,每個(gè)數(shù)據(jù)大小是 8 字節(jié),最簡(jiǎn)單的辦法就是將數(shù)據(jù)存儲(chǔ)在數(shù)組中,內(nèi)存占用差不多是 80MB,符合內(nèi)存的限制。借助今天講的內(nèi)容,我們可以先對(duì)這 1000 萬數(shù)據(jù)從小到大排序,然后再利用二分查找算法,就可以快速地查找想要的數(shù)據(jù)了。
用散列表和二叉樹是無法解決的原因:
- 散列表、二叉樹這些支持快速查找的動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)。用散列表和二叉樹實(shí)際上是不行的。大部分情況下用二分查找可以解決的問題,用散列表、二叉樹都可以解決。但是,不管是散列表還是二叉樹,需要比較多的額外內(nèi)存空間。
- 如果用散列表或者二叉樹來存儲(chǔ)這 1000 萬的數(shù)據(jù),用 100MB 的內(nèi)存肯定是存不下的。而二分查找底層依賴的是數(shù)組,除了數(shù)據(jù)本身之外,不需要額外存儲(chǔ)其他信息,是最省內(nèi)存空間的存儲(chǔ)方式,所以剛好能在限定的內(nèi)存大小下解決這個(gè)問題
總結(jié)
以上是生活随笔為你收集整理的15 | 二分查找(上):如何用最省内存的方式实现快速查找功能?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python3编写方程计算器_pytho
- 下一篇: 近世代数——Part2 群:基础与子群