DS博客做業07--查找

1.本週學習總結(0--2分)

1.思惟導圖

2.談談你對查找運算的認識及學習體會。

本章主要學習了多種的數據查找方法,以及各類查找方法的評價指標。
經過學習,知道了查找分爲兩種,一種是靜態查找,一種是動態查找。靜態查找,就是僅僅做查詢和檢索的功能,而動態查找則是在靜態查找的基礎上增添了增長數據和刪除數據的功能。經過查找算法的評價指標(ASL),咱們能比較各算法的優劣。ASL是指找到(找不到)查找表中記錄平均須要的關鍵字比較次數。
在線性表的查找中,學習了三種查找方法:順序查找、二分查找、分塊查找。順序查找就是咱們最初的簡單算法,將數組遍歷一遍查找數據,二分查找則是順序查找的改進,每一次取中間值進行比較,從效率上看,時間複雜度從順序查找的O(n)變爲了O(log2n),效率大大提升。分塊查找就是將數據分爲一個一個的有序塊,是一種介於順序查找和二分查找查找方法。
除了線性表的查找外,查找的方法還有跟咱們這學期所學的樹有關——樹表。樹表的查找是利用每層能夠存放2的n-1次個數(n爲結點所在層數),使得數據的比較次數減小到樹的高度。
總的來講,這章的內容並不算很難,算法思路很好理解,主要是樹表的代碼實現上會有一些難度。

2.PTA實驗做業(6分)

本週要求挑3道題目寫設計思路、調試過程。設計思路用僞代碼描述。題目選作要求:c++

原則上題目選擇越難,代碼量越大分值越高。面試

2.1 6-3 二叉搜索樹中的最近公共祖先

在一棵樹T中兩個結點u和v的最近公共祖先(LCA),是樹中以u和v爲其後代的深度最大的那個結點。現給定某二叉搜索樹(BST)中任意兩個結點,要求你找出它們的最近公共祖先。

2.1.1設計思路(僞代碼)

//設計思路
查找兩個結點的結果只有兩種狀況:節點存在,找獲得公共祖先;結點不存在,不存在公共祖先一說。
節點存在的狀況有一下幾種:兩個結點分別在左右子樹、全在左子樹、全在右子樹、有一個結點爲對方的父親結點。總的來講,代碼實現上能夠分紅兩塊,一塊是有一個結點爲對方的父親結點的狀況,另外一塊是兩結點分別在所遍歷結點的左右子樹的狀況。不管兩個數據是全在該遍歷的結點的左子樹,仍是右子樹,都不符合最近的要求,只有出現了上面那兩種狀況的時候,該遍歷結點纔是最近的公共祖先。
//僞代碼(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

2.1.2代碼截圖(注意,截圖,截圖,截圖。不要粘貼博客上。)

2.1.3本題PTA提交列表說明。

  • Q1:這道題老師上課的時候講過,因此作起來挺簡單的,而後
  • A1:而後PTA下面的編譯器輸出部分一堆的error,認認真真地看完後……全部的Key都寫成了key,而後一個左括號變成了*……,不認真看題,很差好看打了什麼內容的下場。
    n條几乎如出一轍的錯誤提示……

  • Q2:所有k改爲K後,想着終於搞定了,結果答案錯誤,提示我空樹的時候答案錯誤
  • A2:當時在想,空樹的狀況我不是考慮了嗎?爲何還會錯,後來檢查了一遍代碼,好吧,寫順手了……
  • 寫博客的時候,忽然想到不用判斷結點存在好像也是能夠的,直接找不到結點就經過T==NULL這個條件判斷不就行了,而後就改了代碼去PTA上提交了一下,好像 不行的樣子。在一思索,好像是不行,網一樹裏就有那麼一個點恰好符合最近祖先的條件,可是樹尚未遍歷到樹的最後一層,無法證實它存不存在,仍是要寫一個函數來判斷數據是否存在。算法

    2.2 7-1 QQ賬戶的申請與登錄

實現QQ新賬戶申請和老賬戶登錄的簡化版功能。最大挑戰是:聽說如今的QQ號碼已經有10位數了。

2.2.1設計思路(僞代碼)

//設計思路
利用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

2.2.2代碼截圖(注意,截圖,截圖,截圖。不要粘貼博客上。)


2.2.3本題PTA提交列表說明。

  • Q1:一開始的時候,沒想那麼多,就想着調用個函數,而後利用順序查找的方法來作,簡單粗暴,結果以下圖所示
  • A1:很好,乖乖想算法吧。而後老師上課的時候介紹了map容器,跟用哈希表差很少,還更簡單,因而瘋狂改代碼
  • Q2:改完代碼,VS上運行正確,到PTA上一提交,編譯錯誤???
  • A2:好吧,繼續個人編譯器輸出查看路程,我少了一個 } (黑人問號.jpg)檢查了兩邊,主函數沒少大括號啊……
  • 算了,從頭開始看吧,而後,而後,個人結構體的下半部分呢……
    而後,難過,發生了什麼,我VS運行的好好的,複製黏貼一下,結構體給我弄沒了。。。一半
  • 改回去以後,皆大歡喜。

2.3 7-2 航空公司VIP客戶查詢

很多航空公司都會提供優惠的會員服務,當某顧客飛行里程累積達到必定數量後,可使用里程積分直接兌換獎勵機票或獎勵升艙等服務。現給定某航空公司全體會員的飛行記錄,要求實現根據身份證號碼快速查詢會員里程積分的功能。

2.3.1設計思路(僞代碼)

//設計思路
利用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

2.3.2代碼截圖(注意,截圖,截圖,截圖。不要粘貼博客上。)


2.3.3本題PTA提交列表說明。

  • Q1:這道題,看題目超簡單,跟前面的QQ那道題是相似的,就多了一個map值的變化,然鵝,編譯錯誤。
  • A1:一看編譯器輸出,好吧,忘記換成c++的了
  • Q2:改回c++編譯器以後,部分正確,一看錯誤提示,還運行超時……思路沒毛病,代碼好像有點點問題,map容器那塊的函數有點錯,修修改改,感受有無數次的多種錯誤,運行超時,運行超時,運行超時的……而後,找了同窗要代碼,跟她的思路同樣,就比她多了個結構體而已,不知所措。
  • 後面直接放棄,跟她同樣,把結構體去掉,正確了????!!!!!!總以爲很莫名其妙……

三、閱讀代碼(-2--2分)

找一份和查找運算相關代碼,談談你對這個代碼認識體會。數組

考研題種關於查找、二叉搜索樹內容。
ACM、PTA天梯賽、leecode面試刷題網站,找查找相關題目閱讀分析。
請按照下面內容填寫代碼閱讀內容。請未必認真完成,若是發現應付,沒有介紹代碼思路、體會等扣分。函數

3.1 在排序數組中查找元素的第一個和最後一個位置

給定一個按照升序排列的整數數組 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)

3.2 解題思路

  • 方法一:線性掃描
首先,咱們對 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)

3.3 代碼截圖

  • 方法一
    學習

  • 方法二
    網站

3.4 學習體會

  • 這道題呢,實際上是挺簡單的,可是力扣裏面難度卻顯示中等。我一開始的時候,看到這道題,想到的就是方法一,直接用順序查找的方式作。
  • 後來,我看了力扣裏面的題解,發現他有兩種作法,另一種是二分查找法。提高了算法的時間複雜度。
  • 有去看了眼題,好吧,我又不認真看題了,他要求的是用時間複雜度爲O(logn)的算法來作,順序查找簡單粗暴,可是時間複雜度達到了O(n)。而二分查找法正好符合條件。
  • 雖然我以爲輸入數據的時候,時間複雜度就達到了O(n),查找的時間複雜度是O(n)仍是O(logn)區別並非很大。可是數據量多起來的時候,仍是差挺多的。咱們作題的時候也應該儘可能去使用那些效率高的算法,而不是怎麼簡單怎麼來。
相關文章
相關標籤/搜索