本章主要學習了多種的數據查找方法,以及各類查找方法的評價指標。 經過學習,知道了查找分爲兩種,一種是靜態查找,一種是動態查找。靜態查找,就是僅僅做查詢和檢索的功能,而動態查找則是在靜態查找的基礎上增添了增長數據和刪除數據的功能。經過查找算法的評價指標(ASL),咱們能比較各算法的優劣。ASL是指找到(找不到)查找表中記錄平均須要的關鍵字比較次數。 在線性表的查找中,學習了三種查找方法:順序查找、二分查找、分塊查找。順序查找就是咱們最初的簡單算法,將數組遍歷一遍查找數據,二分查找則是順序查找的改進,每一次取中間值進行比較,從效率上看,時間複雜度從順序查找的O(n)變爲了O(log2n),效率大大提升。分塊查找就是將數據分爲一個一個的有序塊,是一種介於順序查找和二分查找查找方法。 除了線性表的查找外,查找的方法還有跟咱們這學期所學的樹有關——樹表。樹表的查找是利用每層能夠存放2的n-1次個數(n爲結點所在層數),使得數據的比較次數減小到樹的高度。 總的來講,這章的內容並不算很難,算法思路很好理解,主要是樹表的代碼實現上會有一些難度。
本週要求挑3道題目寫設計思路、調試過程。設計思路用僞代碼描述。題目選作要求:c++
原則上題目選擇越難,代碼量越大分值越高。面試
在一棵樹T中兩個結點u和v的最近公共祖先(LCA),是樹中以u和v爲其後代的深度最大的那個結點。現給定某二叉搜索樹(BST)中任意兩個結點,要求你找出它們的最近公共祖先。
//設計思路 查找兩個結點的結果只有兩種狀況:節點存在,找獲得公共祖先;結點不存在,不存在公共祖先一說。 節點存在的狀況有一下幾種:兩個結點分別在左右子樹、全在左子樹、全在右子樹、有一個結點爲對方的父親結點。總的來講,代碼實現上能夠分紅兩塊,一塊是有一個結點爲對方的父親結點的狀況,另外一塊是兩結點分別在所遍歷結點的左右子樹的狀況。不管兩個數據是全在該遍歷的結點的左子樹,仍是右子樹,都不符合最近的要求,只有出現了上面那兩種狀況的時候,該遍歷結點纔是最近的公共祖先。
//僞代碼(LCA函數) if 樹爲空 then 返回 ERROR end if if u或v不存在在樹中 then 返回 ERROR end if if u或v是該遍歷是的結點時 then //代表其中一個爲對方的父親 返回 該結點的Key值 end if if u、v分別在該遍歷結點的左右子樹時 then 返回 該結點的Key值 end if if 該結點的Key值小於u的值 then 調用遞歸,進入該結點的右孩子結點 else 調用遞歸,進入該結點的左孩子結點 end if
寫博客的時候,忽然想到不用判斷結點存在好像也是能夠的,直接找不到結點就經過T==NULL這個條件判斷不就行了,而後就改了代碼去PTA上提交了一下,好像 不行的樣子。在一思索,好像是不行,網一樹裏就有那麼一個點恰好符合最近祖先的條件,可是樹尚未遍歷到樹的最後一層,無法證實它存不存在,仍是要寫一個函數來判斷數據是否存在。算法
實現QQ新賬戶申請和老賬戶登錄的簡化版功能。最大挑戰是:聽說如今的QQ號碼已經有10位數了。
//設計思路 利用map容器的 鍵+值且鍵不能重複的特色,保證帳號不會重複,用法與哈希表類似,查找的時間複雜度爲O(1)。
//僞代碼 定義int型變量n,表示操做次數;User型數組user,存放帳號密碼;map型變量QQ,char型變量choice,用於表示操做類型 for i=0 to n do 輸入操做類型,QQ號、密碼; if 操做類型爲L then//登錄 if 帳號不存在 then 輸出「ERROR: Not Exist」 else if 帳號對應的密碼不正確 then 輸出"ERROR: Wrong PW" else 輸出"Login: OK" end if end if else//註冊 if 帳號不存在 then 輸出"New: OK" 將這組帳號密碼存入map容器QQ中 else 輸出"ERROR: Exist" end if end if end for
很多航空公司都會提供優惠的會員服務,當某顧客飛行里程累積達到必定數量後,可使用里程積分直接兌換獎勵機票或獎勵升艙等服務。現給定某航空公司全體會員的飛行記錄,要求實現根據身份證號碼快速查詢會員里程積分的功能。
//設計思路 利用map容器的特色,用法與哈希表相似
//僞代碼 定義字符型數組id[20];long long型變量distance; for i=0 to n do 輸入身份證號和航行距離 if 航行距離小於最小航行距離 then 令distance等於最小航行距離 end if if 沒有乘坐記錄 then 將id、distance的值存入map容器中 else 修改map容器中身份證號對應的稱做距離的值 end if end for 定義int型變量m,查找數目 輸入m for i=0 to m do 輸入id號 if 該身份證號不在存檔中 then 輸出"No Info" else 輸出該身份證號所對應的里程 end if end for
找一份和查找運算相關代碼,談談你對這個代碼認識體會。數組
考研題種關於查找、二叉搜索樹內容。
ACM、PTA天梯賽、leecode面試刷題網站,找查找相關題目閱讀分析。
請按照下面內容填寫代碼閱讀內容。請未必認真完成,若是發現應付,沒有介紹代碼思路、體會等扣分。函數
給定一個按照升序排列的整數數組 nums,和一個目標值 target。找出給定目標值在數組中的開始位置和結束位置。 你的算法時間複雜度必須是 O(log n) 級別。 若是數組中不存在目標值,返回 [-1, -1]。 - 示例 1: 輸入: nums = [5,7,7,8,8,10], target = 8 輸出: [3,4] - 示例 2: 輸入: nums = [5,7,7,8,8,10], target = 6 輸出: [-1,-1] 做者:LeetCode 連接:https://leetcode-cn.com/problems/two-sum/solution/zai-pai-xu-shu-zu-zhong-cha-zhao-yuan-su-de-di-yi-/ 來源:力扣(LeetCode)
首先,咱們對 nums 數組從左到右作線性遍歷,當遇到 target 時停止。若是咱們沒有停止過,那麼 target 不存在,咱們能夠返回「錯誤代碼」 [-1, -1] 。若是咱們找到了有效的左端點座標,咱們能夠坐第二遍線性掃描,但此次從右往左進行。這一次,第一個遇到的 target 將是最右邊的一個(由於最左邊的一個存在,因此必定會有一個最右邊的 target)。咱們接下來只須要返回這兩個座標。 時間複雜度:O(n);空間複雜度:O(1)
整體算法工做過程與線性掃描方法相似,除了找最左和最右下標的方法。這裏咱們僅僅作幾個微小的調整,用這種修改過的二分查找方法去搜索這個排過序的數組。首先,爲了找到最左邊(或者最右邊)包含 target 的下標(而不是找到的話就返回 true ),因此算法在咱們找到一個 target 後不能立刻中止。咱們須要繼續搜索,直到 lo == hi 且它們在某個 target 值處下標相同。 另外一個改變是 left 參數的引入,它是一個 boolean 類型的變量,指示咱們在遇到 target == nums[mid] 時應該作什麼。若是 left 爲 true ,那麼咱們遞歸查詢左區間,不然遞歸右區間。考慮若是咱們在下標爲 i 處遇到了 target ,最左邊的 target 必定不會出如今下標大於 i 的位置,因此咱們永遠不須要考慮右子區間。當求最右下標時,道理一樣適用。 時間複雜度:O(log2n);空間複雜度:O(1)
方法一
學習
方法二
網站