超大規模數據場景(思路)——面試高頻算法題目

目錄

用4KB內存尋找重復元素

從40個億中產生不存在的整數【位】

如果只讓用10MB空間存儲?

初次遍歷

二次遍歷

用2GB內存在20億個整數中查找出現次數最多的數【分塊】

從億萬個URL中查找問題【分塊 堆】

40億個非負整數中找出現兩次的數【位 不過多個位哈】

對20GB的文件進行排序【分塊+堆】

超大文本中搜索兩個單詞的最短距離

從10億數字中尋找最小的100萬個數字【堆】


在海量數據中,此時普通的數組、鏈表、Hash、樹等等結構有無效了 ,因為內存空間放不下了。

而常規的遞歸、排序,回溯、貪心和動態規劃等思想也無效了,因為執行都會超時,必須另外想辦法。

這類問題該如何下手呢?這里介紹三種非常典型的思路:

  • 位存儲:使用位存儲最大的好處是占用的空間是簡單存整數的1/8。例如一個40億的整數數組,如果用整數存儲需要16GB左右的空間,而如果使用位存儲,就可以用0.5GB的空間,這樣很多問題就能夠解決了。

  • 分塊:如果文件實在太大 ,無法在內存中放下,則需要考慮將大文件分成若干小塊,先處理每個塊,最后再逐步得到想要的結果,這種方式也叫做外部排序。這樣需要遍歷全部序列至少兩次,是典型的用時間換空間的方法。

  • 堆:如果在超大數據中找第K大、第K小,K個最大、K個最小,則特別適合使用堆來做。而且將超大數據換成流數據也可以,而且幾乎是唯一的方式。

用4KB內存尋找重復元素

給定一個數組,包含從1到N的整數,N最大為32000,數組可能還有重復值,且N的取值不定,若只有4KB的內存可用,該如何打印數組中所有重復元素。

本身是一道海量數據問題,如果去掉“只有4KB”的要求,我們可以先創建一個大小為N的數組,然后將這些數據放進來,但是整數最大為32000。如果直接采用數組存,則應該需要32000*4B=128KB的空間,而題目有4KB的內存限制,我們就必須先解決該如何存放的問題。

如果只有4KB的空間,那么只能尋址8*4*2^10個比特,這個值比32000要大的,因此我們可以創建32000比特的位向量(比特數組),其中一個比特位置就代表一個整數。利用這個位向量,就可以遍歷訪問整個數組。如果發現數組元素是v,那么就將位置為v的設置為1,碰到重復元素,就輸出一下。

public class FindDuplicatesIn32000 {public void checkDuplicates(int[] array) {BitSet bs = new BitSet(32000);for (int i = 0; i < array.length; i++) {int num = array[i];int num0 = num - 1;if (bs.get(num0)) {System.out.println(num);} else {bs.set(num0);}}}class BitSet {int[] bitset;public BitSet(int size) {this.bitset = new int[size >> 5];}boolean get(int pos) {int wordNumber = (pos >> 5);//除以32int bitNumber = (pos & 0x1F);//除以32return (bitset[wordNumber] & (1 << bitNumber)) != 0;}void set(int pos) {int wordNumber = (pos >> 5);//除以32int bitNumber = (pos & 0x1F);//除以32bitset[wordNumber] |= 1 << bitNumber;}}
}

從40個億中產生不存在的整數【位】

給定一個輸入文件,包含40億個非負整數,請設計一個算法,產生一個不存在該文件中的整數,假設你有1GB的內存來完成這項任務。

  • 核心點:我們存儲的并不是這40億個數據本身,而是其對應的位置。

如果數據量很大,采用位方式(俗稱位圖)存儲數據是常用的思路, 我們可以使用 bit map 的方式來表示數出現的情況。

申請一個長度為 4 294 967 295(500MB*8) 的 bit 類型的數組 bitArr(就是boolean類型),bitArr 上的每個位置只可以表示 0 或1 狀態。8 個bit 為 1B,所以長度為 4 294 967 295 的 bit 類型的數組占用 500MB 空間,這就滿足題目給定的要求了。

遍歷這 40 億個無符號數,遇到所有的數時,就把 bitArr 相應位置的值設置為 1。

遍歷完成后,再依次遍歷 bitArr,看看哪個位置上的值沒被設置為 1,這個數就不在 40 億個數中。

如果只讓用10MB空間存儲?

  • 分塊

初次遍歷

40億個數需要500MB的空間,那如果只有10MB的空間,至少需要50個塊才可以。

一般來說,我們劃分都是使用2的整數倍,因此劃分成64個塊是合理的。

因為一共只有 40 億個數,所以,如果統計落在每一個區間上的數有多少,肯定有至少一個區間上的計數少于67 108 864。利用這一點可以找出其中一個沒出現過的數。

第一次遍歷,先申請長度為 64 的整型數組 countArr[0..63],countArr[i]用來統計區間 i 上的數有多少。遍歷 40 億個數,根據當前數是多少來決定哪一個區間上的計數增加。

遍歷完 40 億個數之后,遍歷 countArr,必然會有某一個位置上的值(countArr[i]) 小于 67 108 864,表示第 i 區間上至少有一個數沒出現過。

二次遍歷

假設找到第 37 區間上的計數小于 67 108 864,那么我們對這40億個數據進行第二次遍歷:

  1. 申請長度為 67 108 864 的 bit map,這占用大約 8MB 的空間,記為 bitArr{0..67108863}。

  2. 遍歷這 40 億個數,此時的遍歷只關注落在第 37 區間上的數,記為 num(num滿足num/67 108 864==37),其他區間的數全部忽略。

  3. 如果步驟 2 的 num 在第 37 區間上,將 bitArr{num - 67108864*37}的值設置為 1,也就是只做第 37 區間上的數的 bitArr 映射。

  4. 遍歷完 40 億個數之后,在 bitArr 上必然存在沒被設置成 1 的位置,假設第 i 個位置上的值沒設置成 1,那么 {67 108 864*37+i} 這個數就是一個沒出現過的數。

用2GB內存在20億個整數中查找出現次數最多的數【分塊】

有一個包含 20 億個全是 32 位整數的大文件,在其中找到出現次數最多的數。

  • 分塊

通常的做法是使用哈希表對出現的每一個數做詞頻統計,哈希表的 key 是某一個整數,value 是這個數出現的次數。就本題來說,一共有 20 億個數,哪怕只是一個數出現了 20 億次,用 32 位的整數也可以表示其出現的次數而不會產生溢出,所以哈希表的 key 需要占用 4B,value 也是 4B。那么哈希表的一條記錄(key,value)需要占用 8B,當哈希表記錄數為 2 億個時,需要至少 1.6GB 的內存。

如果 20 億個數中不同的數超過 2 億種,最極端的情況是 20 億個數都不同,那么在哈希表中可能需要產生 20 億條記錄,這樣內存會不夠用,所以一次性用哈希表統計 20 億個數的辦法是有很大風險的。

解決辦法是把包含 20 億個數的大文件用哈希函數分成 16 個小文件,根據哈希函數的性質,同一種數不可能被散列到不同的小文件上,同時每個小文件中不同的數一定不會大于 2 億種, 假設哈希函數足夠優秀。然后對每一個小文件用哈希表來統計其中每種數出現的次數,這樣我們就得到了 16 個小文件中各自出現次數最多的數,還有各自的次數統計。接下來只要選出這16 個小文件各自的第一名中誰出現的次數最多即可。

把一個大的集合通過哈希函數分配到多臺機器中,或者分配到多個文件里,這種技巧是處理大數據面試題時最常用的技巧之一。但是到底分配到多少臺機器、分配到多少個文件,在解題時一定要確定下來。可能是在與面試官溝通的過程中由面試官指定,也可能是根據具體的限制來確定,比如本題確定分成 16 個文件,就是根據內存限制 2GB 的條件來確定的。

從億萬個URL中查找問題【分塊 堆】

有一個包含 100 億個 URL 的大文件,假設每個 URL 占用 64B,請找出其中所有重復的 URL。

補充問題:某搜索公司一天的用戶搜索詞匯是海量的(百億數據量),請設計一種求出每天熱門 Top 100 詞匯的可行辦法。

解答:原問題的解法使用解決大數據問題的一種常規方法:把大文件通過哈希函數分配到機器, 或者通過哈希函數把大文件拆成小文件,一直進行這種劃分,直到劃分的結果滿足資源限制的要求。首先,你要向面試官詢問在資源上的限制有哪些,包括內存、計算時間等要求。在明確了限制要求之后,可以將每條 URL 通過哈希函數分配到若干臺機器或者拆分成若干個小文件, 這里的“若干”由具體的資源限制來計算出精確的數量。

例如,將 100 億字節的大文件通過哈希函數分配到 100 臺機器上,然后每一臺機器分別統計分給自己的 URL 中是否有重復的 URL,同時哈希函數的性質決定了同一條 URL 不可能分給不同的機器;或者在單機上將大文件通過哈希函數拆成 1000 個小文件,對每一個小文件再利用哈希表遍歷,找出重復的 URL;還可以在分給機器或拆完文件之后進行排序,排序過后再看是否有重復的 URL 出現。總之,牢記一點,很多大數據問題都離不開分流,要么是用哈希函數把大文件的內容分配給不同的機器,要么是用哈希函數把大文件拆成小文件,然后處理每一個小數量的集合。

補充問題最開始還是用哈希分流的思路來處理,把包含百億數據量的詞匯文件分流到不同的機器上,具體多少臺機器由面試官規定或者由更多的限制來決定。對每一臺機器來說,如果分到的數據量依然很大,比如,內存不夠或存在其他問題,可以再用哈希函數把每臺機器的分流文件拆成更小的文件處理。處理每一個小文件的時候,通過哈希表統計每種詞及其詞頻,哈希表記錄建立完成后,再遍歷哈希表,遍歷哈希表的過程中使用大小為 100 的小根堆來選出每一個小文件的 Top 100(整體未排序的 Top 100)。每一個小文件都有自己詞頻的小根堆(整體未排序的 Top 100),將小根堆里的詞按照詞頻排序,就得到了每個小文件的排序后 Top 100。然后把各個小文件排序后的 Top 100 進行外排序或者繼續利用小根堆,就可以選出每臺機器上的 Top100。不同機器之間的 Top 100 再進行外排序或者繼續利用小根堆,最終求出整個百億數據量中的 Top 100。對于 Top K 的問題,除用哈希函數分流和用哈希表做詞頻統計之外,還經常用堆結構和外排序的手段進行處理。

40億個非負整數中找出現兩次的數【位 不過多個位哈】

32 位無符號整數的范圍是 0~4 294 967 295,現在有 40 億個無符號整數,可以使用最多 1GB的內存,找出所有出現了兩次的數。

首先,可以用 bit map 的方式來表示數出現的情況。具體地說,是申請一個長度為4 294 967 295x2 的bit 類型的數組bitArr,用 2 個位置表示一個數出現的詞頻,1B 占用 8 個bit, 所以長度為 4 294 967 295x2 的 bit 類型的數組占用 1GB 空間。

遍歷這 40 億個無符號數,如果初次遇到 num,就把bitArr[num*2 + 1]和 bitArr[num*2]設置為 01, 如果第二次遇到 num,就把bitArr[num*2+1]和bitArr[num*2]設置為 10,如果第三次遇到 num, 就把bitArr[num*2+1]和bitArr[num*2]設置為 11。以后再遇到 num,發現此時 bitArr[num*2+1]和 bitArr[num*2]已經被設置為 11,就不再做任何設置。遍歷完成后,再依次遍歷 bitArr,如果發現bitArr[i*2+1]和bitArr[i*2]設置為 10,那么 i 就是出現了兩次的數。

對20GB的文件進行排序【分塊+堆】

假設你有一個20GB的文件,每行一個字符串,請說明如何對這個文件進行排序?

這里給出大小是20GB,我們只能將文件劃分成一些塊,每塊大小是xMB,x就是可用內存的大小,例如1GB一塊,那我們就可以將文件分為20塊。我們先對每塊進行排序,然后再逐步合并。這時候我們可以使用兩兩歸并,也可以使用堆排序策略將其逐步合并成一個。

超大文本中搜索兩個單詞的最短距離

有個超大文本文件,內部是很多單詞組成的,現在給定兩個單詞,請你找出這兩個單詞在這個文件中的最小距離,也就是像個幾個單詞。有辦法在O(n)時間里完成搜索操作嗎?方法的空間復雜度如何?

最直觀的做法是遍歷數組 words,對于數組中的每個word1,遍歷數組words 找到每個word2并計算距離。該做法在最壞情況下的時間復雜度是 O(n^2),需要優化。本題我們少不了遍歷一次數組,找到所有word1 和word2出現的位置,但是為了方便比較,我們可以將其放到一個數組里,例如:

listA:{1,2,9,15,25}
listB:{4,10,19}
合并成
list:{1a,2a,4b,9a,10b,15a,19b,25a}

合并成一個之后更方便查找,數字表示出現的位置,后面一個元素表示元素是什么。然后一邊遍歷一邊比較就可以了。

但是對于超大文本,如果文本太大那這個list可能溢出。如果繼續觀察,我們會發現其實不用單獨構造list,從左到右遍歷數組words,當遍歷到 word1時,如果已經遍歷的單詞中存在word2 ,為了計算最短距離,應該取最后一個已經遍歷到的 word2所在的下標,計算和當前下標的距離。同理,當遍歷到word2時,應該取最后一個已經遍歷到的word1所在的下標,計算和當前下標的距離。

基于上述分析,可以遍歷數組一次得到最短距離,將時間復雜度降低到O(n)。用index1和index2分別表示數組words 已經遍歷的單詞中的最后一個word1的下標和最后一個word2的下標,初始時index1 =index2=?1。遍歷數組words,當遇到word2時,執行如下操作:

  • 如果遇到word1 ,則將index1更新為當前下標;如果遇到word2,則將index2更新為當前下標。

  • 如果index1和index2都非負,則計算兩個下標的距離 ∣index1?index2 ∣,并用該距離更新最短距離。

遍歷結束之后即可得到word1和word2的最短距離。

進階問題如果尋找過程在這個文件中會重復多次,而每次尋找的單詞不同,則可以維護一個哈希表記錄每個單詞的下標列表。遍歷一次文件,按照下標遞增順序得到每個單詞在文件中出現的所有下標。在尋找單詞時,只要得到兩個單詞的下標列表,使用雙指針遍歷兩個下標鏈表,即可得到兩個單詞的最短距離。

從10億數字中尋找最小的100萬個數字【堆】

設計一個算法,給定一個10億個數字,找出最小的100萬的數字。假定計算機內存足以容納全部10億個數字。

首先,為前100萬個數字創建一個大頂堆,最大元素位于堆頂。

然后,遍歷整個序列,只有比堆頂元素小的才允許插入堆中,并刪除原堆的最大元素。

之后繼續遍歷剩下的數字,最后剩下的就是最小的100萬個。

采用這種方式,只需要遍歷一次10億個數字,還可以接受。更新堆的代價是O(nlogn)。堆占用的空間是100萬*4,大約為4MB左右的空間。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76942.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76942.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76942.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

開源身份和訪問管理方案之keycloak(三)keycloak健康檢查(k8s)

文章目錄 開源身份和訪問管理方案之keycloak&#xff08;三&#xff09;keycloak健康檢查啟用運行狀況檢查 健康檢查使用Kubernetes下健康檢查Dockerfile 中 HEALTHCHECK 指令 健康檢查Docker HEALTHCHECK 和 Kubernetes 探針 開源身份和訪問管理方案之keycloak&#xff08;三&…

FATFS備忘

概述 FATFS文件系統可以掛載SD卡也可以掛載FLASH eMMC等設備 SD卡需要格式化為FAT32模式 塊大小默認即可 移植 SD卡 SD卡扇區大小是 512B SD卡 SDIO模式 可以直接在cubeMX里一鍵設置 先設置好SD卡的設置 這個是選擇支持中文 其余是默認 這個是檢測引腳可以留空 當SD卡插入拔出…

唯美社區源碼AM社區同款源碼

源碼介紹 唯美社區源碼AM社區同款源碼 后端修改application.properties文件內容為你的數據庫 前端修改/config/config.js文件內容為你的后端地址 這兩個文件里要修改的地方我已經用中文標注出來了 截圖 源碼免費下載 唯美社區源碼AM社區同款源碼

現代Web應用的多標簽選擇組件:設計哲學與工程實踐

引言&#xff1a;標簽選擇的重要性與挑戰 在信息爆炸時代&#xff0c;標簽系統已成為內容組織的核心基礎設施。研究表明&#xff1a; 使用標簽系統的平臺用戶留存率提高35% 良好的標簽選擇體驗可提升內容發現效率58% 80%的用戶更傾向于使用提供可視化標簽選擇的應用 本文將…

P3799 小 Y 拼木棒

題目背景 上道題中&#xff0c;小 Y 斬了一地的木棒&#xff0c;現在她想要將木棒拼起來。 題目描述 有 n 根木棒&#xff0c;現在從中選 4 根&#xff0c;想要組成一個正三角形&#xff0c;問有幾種選法&#xff1f; 答案對 1097 取模。 輸入格式 第一行一個整數 n。 第…

Perl 條件語句

Perl 條件語句 引言 在編程中&#xff0c;條件語句是執行分支邏輯的關鍵部分。Perl 作為一種強大的腳本語言&#xff0c;提供了豐富的條件語句&#xff0c;使得開發者能夠根據不同的條件執行不同的代碼塊。本文將深入探討 Perl 中的條件語句&#xff0c;包括 if、unless、els…

流量特征分析-蟻劍流量分析

任務&#xff1a; 木馬的連接密碼是多少 這是分析蟻劍流量&#xff0c;可能是網站的&#xff0c;wireshark過濾http 追蹤流http得到 1就是連接密碼 flag{1}黑客執行的第一個命令是什么 取最后的執行命令。base64解密得 除了id不是蟻劍自帶的命令&#xff0c;其他的都是&…

問題1:Sinal 4在開啟PAC檢查的設備崩潰

? 問題信息 硬件不支持PAC(Pointer Authentication),此類錯誤就是signal 11的錯誤,崩潰信息如下: Build fingerprint: google/sdk_gphone64_arm64/emu64a:16/BP22.250221.010/13193326:userdebug/dev-keys Revision: 0 ABI: arm64 Timestamp: 2025-04-06 11:33:13.923…

FreeRTOS移植筆記:讓操作系統在你的硬件上跑起來

一、為什么需要移植&#xff1f; FreeRTOS就像一套"操作系統積木"&#xff0c;但不同硬件平臺&#xff08;如STM32、ESP32、AVR等&#xff09;的CPU架構和外設差異大&#xff0c;需要針對目標硬件做適配配置。移植工作就是讓FreeRTOS能正確管理你的硬件資源。 二、…

【C++11(下)】—— 我與C++的不解之緣(三十二)

前言 隨著 C11 的引入&#xff0c;現代 C 語言在語法層面上變得更加靈活、簡潔。其中最受歡迎的新特性之一就是 lambda 表達式&#xff08;Lambda Expression&#xff09;&#xff0c;它讓我們可以在函數內部直接定義匿名函數。配合 std::function 包裝器 使用&#xff0c;可以…

JavaScript中的Proxy詳解

1. 什么是Proxy&#xff1f; Proxy是ES6引入的一個強大特性&#xff0c;它允許你創建一個對象的代理&#xff0c;從而可以攔截和自定義該對象的基本操作。Proxy提供了一種機制&#xff0c;可以在對象的基本操作&#xff0c;如屬性查找、賦值、枚舉、函數調用等之前或之后執行自…

【git】VScode修改撤回文件總是出現.lh文件,在 ?所有 Git 項目 中全局忽略特定文件

VScode里面powershell被迫關閉 場景解決辦法 場景 系統&#xff1a;Windows IDE&#xff1a;Visual Studio Code 一旦修改代碼&#xff0c;就算撤回也會顯示 解決辦法 第一步&#xff1a;“C:\Users\用戶名字.gitignore_global”&#xff1a;在該路徑下新建.gitignore_glo…

為什么 LoRA 梯度是建立在全量參數 W 的梯度之上

&#x1f9e0; 首先搞清楚 LoRA 是怎么做微調的 我們原來要訓練的參數矩陣是 W W W&#xff0c;但 LoRA 說&#xff1a; 別動 W&#xff0c;我在它旁邊加一個低秩矩陣 Δ W U V \Delta W UV ΔWUV&#xff0c;只訓練這個部分&#xff01; 也就是說&#xff0c;LoRA 用一個…

Nginx負載均衡時如何為指定ip配置固定服務器

大家在用Nginx做負載均衡時&#xff0c;一般是采用默認的weight權重指定或默認的平均分配實現后端服務器的路由&#xff0c;還有一種做法是通過ip_hash來自動計算進行后端服務器的路由&#xff0c;但最近遇到一個問題&#xff0c;就是希望大部分用戶采用ip_hash自動分配后端服務…

Llama 4 家族:原生多模態 AI 創新的新時代開啟

0 要點總結 Meta發布 Llama 4 系列的首批模型&#xff0c;幫用戶打造更個性化多模態體驗Llama 4 Scout 是有 170 億激活參數、16 個專家模塊的模型&#xff0c;同類中全球最強多模態模型&#xff0c;性能超越以往所有 Llama 系列模型&#xff0c;能在一張 NVIDIA H100 GPU 上運…

【硬件開發技巧】如何通過元器件絲印反查型號

目錄 一、在線數據庫查詢 二、官方資料匹配 三、專業軟件輔助 四、實物比對與場景推斷 五、社區與人工支持 注意事項 一、在線數據庫查詢 專業元器件平臺 Digi-Key、Mouser、ICMaster等平臺支持直接輸入絲印代碼檢索&#xff0c;可獲取芯片型號、技術文檔及替代型號。例如…

【算法/c++】利用中序遍歷和后序遍歷建二叉樹

目錄 題目&#xff1a;樹的遍歷前言題目來源樹的數組存儲基本思想存儲規則示例 建樹算法關鍵思路代碼總代碼 鏈表法 題目&#xff1a;樹的遍歷 前言 如果不是完全二叉樹&#xff0c;使用數組模擬樹&#xff0c;會很浪費空間。 題目來源 本題來自 PTA 天梯賽。 題目鏈接: 樹…

李臻20242817_安全文件傳輸系統項目報告_第6周

安全文件傳輸系統項目報告&#xff08;第 1 周&#xff09; 1. 代碼鏈接 Gitee 倉庫地址&#xff1a;https://gitee.com/li-zhen1215/homework/tree/master/Secure-file 代碼結構說明&#xff1a; project-root/├── src/ # 源代碼目錄│ ├── main.c # 主程序入口│ ├…

嵌入式rodata段

在嵌入式軟件開發中&#xff0c;將數據放入只讀數據段&#xff08;.rodata&#xff09;具有以下好處及典型應用示例&#xff1a; 好處 數據保護 .rodata段的內容在程序運行時不可修改&#xff0c;防止意外或惡意篡改&#xff0c;提升系統穩定性。 節省RAM資源 只讀數據可直接…

InfoSec Prep: OSCP靶場滲透

InfoSec Prep: OSCP InfoSec Prep: OSCP ~ VulnHubInfoSec Prep: OSCP, made by FalconSpy. Download & walkthrough links are available.https://www.vulnhub.com/entry/infosec-prep-oscp,508/ 1&#xff0c;將兩臺虛擬機網絡連接都改為NAT模式 2&#xff0c;攻擊機上做…