DS博客做業02--線性表

1.本週學習總結

1.1思惟導圖

1.2談談你對線性表的認識和學習體會

學線性表這一章的時候,我感受吧就像是在學加上告終構體能夠變化長度的數組和鏈表 。感受就是應該和上學期的數組和鏈表差很少,結果作起PTA的時候,一堆堆的錯誤。而後上級考的時候,一遍遍的段錯誤到絕望……而後就感受本身跟上學期比起來鬆懈了很多,最基本的代碼問題又開始

2.PTA實驗做業

2.1題目1:6-3 jmu-ds- 順序表刪除重複元素

設計一個算法,從順序表中刪除重複的元素,並使剩餘元素間的相對次序保存不變。
 - 輸入格式: 第一行輸入順序表長度。 第二行輸入順序表數據元素。中間空格隔開。
 - 輸出格式:數據之間空格隔開,最後一項尾部不帶空格。
 - 輸出刪除重複元素後的順序表。

2.1.1設計思路(僞代碼)

由於順序表中的數均爲正數,構造一個哈希數組賦初值爲0,遍歷順序表,將L->data[i]的值做爲哈希數組的下標統計順序表中各個數出現的次數,將哈希數組值爲一的數存入重構順序表中。
  • 僞代碼
定義整型變量i、j=0,i爲原順序表的下標,j爲重構順序表的下標
定義整型哈希數組hash[100],並賦初值爲0
遍歷順序表
    將L->data[i]做爲哈希數組的下標,統計其出現的次數
    if L->data[i]出現的次數爲一次 then
        將L->data[i]的值賦給L->data[j++]  //重構順序表
將j的值做爲順序表長度賦給L->length

2.1.2代碼截圖

  • void CreateSqList(List &L,int a[],int n); //建立順序表
    算法

  • void DispSqList(List L);//輸出順序表
    數組

  • void DelSameNode(List &L) ;//刪除順序表重複元素
    函數

2.1.3本題PTA提交列表說明

Q1:一開始部分正確是由於忽略了空表及所有刪除後的輸出,而後又認真的看了一下題目,在輸出的函數部分用if語句分出空順序表的狀況;
Q2:後來兩個間隔長時間的答案正確的提交改進了算法,將時間複雜度爲O(n3)改進成了O(n);
A2:一開始作這道題的時候用的是笨辦法,用兩層for循環查找重複元素,找到後再來一層循環將順序表往前挪,雖然作法簡單易懂,可是時間複雜度特別高,當時抱着作出結果就好的心態,作完就沒去管它了。隔了兩週多吧,老師上課提到這道題,通過這兩週的學習,我又想到了只用兩層循環的重構作法,而後老師說能夠用哈希數組來作,只要一層循環就能搞定,當時在課上我就本身試着作了一遍。

2.2題目2:6-8 jmu-ds-鏈表倒數第m個數

已知一個帶有表頭節點的單鏈表,查找鏈表中倒數第m個位置上的節點。
 - 輸入要求:先輸入鏈表結點個數,再輸入鏈表數據,再輸入m表示倒數第m個位置。
 - 輸出要求,若能找到則輸出相應位置,要是輸入無效位置,則輸出-1。

2.2.1設計思路(僞代碼)

利用兩個LinkList型指針p,ptr,將p移到第m個位置,讓ptr從指向頭結點的位置與p同時往下指,當p指向尾結點時,ptr的位置即爲倒數第m個數的位置。
  • 僞代碼
定義LinkList型指針p,ptr,兩個指針均指向頭結點,ptr表示指向倒數第m個位置的指針
if 頭結點爲空 或者 m取小等於0的無效位置 then
    返回 -1
while 指針p不爲空 且 m的值不爲0 do
    指針p往下移
if m的值大於0 then //即L的長度小於m 
    返回 -1
else
    while 指針p不爲空 do
        指針p與指針ptr同時向下移動
    返回 ptr->data的值
end if

2.2.2代碼截圖

2.2.3本題PTA提交列表說明

Q1:當時作的時候,是在幫同窗改過這題代碼的狀況下作的,因此無效位置條件的測試點都過了,可是我沒想到的是有效位置上出了錯
A1:我當時看了一遍又一遍,以爲本身的代碼沒什麼毛病啊,(當時由於題目的各類函數細節不表,懶得本身打出來去dev調試),後面又靜下心來慢慢看那,發現我else裏頭while語句的條件寫錯了,寫成了p->next,這樣一來ptr所指向的位置就變成了倒數第m+1個
Q2:當時作這道題的時候不只是在幫同窗改完代碼的基礎上,更是在老師上課講完了相關例題以後寫的,總以爲沒有了本身的思考,下回PTA的做業仍是不要拖着了(哭唧唧)

2.3題目3:6-10 jmu-ds-有序鏈表的插入刪除

鏈表L是一個有序的帶頭結點鏈表,實現有序鏈表插入刪除操做。

2.3.1設計思路(僞代碼)

插入函數:找到比輸入數據大的結點,將數據插入該結點的前面
刪除函數:找到所輸入的數據,並將該結點釋放刪除,若找不到則輸出X找不到!
  • 僞代碼
插入函數:
    定義LinkList型的變量p、ptr,爲p申請空間,將e賦值給p->data,令ptr等於L
    while ptr->next不爲空 then  //保存前驅結點,方便插入操做
        if ptr->next->data的值大於e then
            將指針p插入在ptr指針後
            返回空值
        end if
        ptr指針日後移
    end while
    將指針p插入在ptr指針後

刪除函數:
    定義LinkList類型的指針 ptr、q,令ptr等於L保存前結點
    if 頭結點爲空 then
        return
    while ptr->next 不爲空 do
        if ptr->next->data的值與e相等 then
            利用指針q刪除該結點,釋放q
            return
        end if
    ptr指針日後移
    end while
    輸出X找不到!  //當輸入數據找不到時纔會執行該語句

2.3.2代碼截圖

  • void ListInsert(LinkList &L,ElemType e);//有序鏈表插入元素e
    學習

  • void ListDelete(LinkList &L,ElemType e);//鏈表刪除元素e
    測試

2.3.3本題PTA提交列表說明

Q1:這題作完後再看,真的是超簡單,可是吧當時不知道在想什麼,信心滿滿的作完,結果編譯錯誤……看了眼PTA的錯誤提醒,好吧,把指針跟數據進行比較,我也是沒誰了
Q2:改完想着好了這題作完了,結果來了個運行超時……(吐血)
A2:檢查了兩遍,沒毛病啊,再提交一下,運行超時……而後問了下同窗,一語驚醒夢中人:你指針都沒移動。好的吧個人錯,繼續改。
Q3:改完之後想着這回總該對了吧,結果如上圖所見,答案錯誤
A3:如同上一題同樣的緣由,沒用dev調試,看了n邊的代碼,始終找不出錯誤,最後認命的手動補充細節不表的函數,過程當中又出現了問題,由於建鏈的時候忘記讓尾結點等於NULL,結果輸出的時候陷入了死循環。改完後,在調試過程當中發現插入函數在尾部插入的狀況不能實現,再瞅了眼代碼,好吧,還真沒考慮到在末尾插入的狀況,終於,答案正確了。
 - 寫這題呢不是由於難,不會作,而是發現本身又開始犯起了基本的錯誤,指針跟數據都能比較起來,不知道爲啥作這道題的時候,邏輯思惟亂亂的,各類出錯。固然還有,不要由於題目給的代碼細節不表懶得本身寫,就不去用dev調試,你覺得不表的函數你都會,可是可能也會有不懂的地方。

3.閱讀代碼

3.1題目:鏈表的中間結點

給定一個帶有頭結點 head 的非空單鏈表,返回鏈表的中間結點。
若是有兩個中間結點,則返回第二個中間結點。
  • 示例1:
輸入:[1,2,3,4,5]
輸出:此列表中的結點 3 (序列化形式:[3,4,5])
返回的結點值爲 3 。 (測評系統對該結點序列化表述是 [3,4,5])。
注意,咱們返回了一個 ListNode 類型的對象 ans,這樣:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
  • 示例2:
輸入:[1,2,3,4,5,6]
輸出:此列表中的結點 4 (序列化形式:[4,5,6])
因爲該列表有兩個中間結點,值分別爲 3 和 4,咱們返回第二個結點。

提示: 給定鏈表的結點數介於 1 和 100 之間。設計

3.2解題思路

解法一:輸出到數組

  • 解題思路
按順序將每一個結點放入數組 A 中。而後中間結點就是 A[A.Length/2],由於咱們能夠經過索引檢索每一個結點。
時間複雜度:O(N),其中 N 是給定列表中的結點數目。
空間複雜度:O(N),A 用去的空間
  • 僞代碼
1.定義一個數組A
2.利用while遍歷鏈表並將鏈表賦值給數組
3.返回數組A[n/2]的值

解法二:快慢指針法

  • 解題思路
當用慢指針 slow 遍歷列表時,讓另外一個指針 fast 的速度是它的兩倍。當 fast 到達列表的末尾時,slow 必然位於中間。
時間複雜度:O(N),其中 N 是給定列表的結點數目
空間複雜度:O(1),slow 和 fast 用去的空間。
  • 僞代碼
定義兩個ListNode類型的指針變量slow、fast,且兩個指針變量均指向head
while fast指針不爲空 且 fast->next指針不爲空 do
   slow指針往下移一位
   fast指針往下移兩位
end while
返回slow指針的值

3.3代碼截圖

  • 解法一
  • 解法二

3.4學習體會

這道題其實超級簡單,選擇這道題的緣由是這套題配的解題思路。
看到這道題的時候,個人想法就是:遍歷一邊鏈表,而後記下鏈表的長度,再用一個循環來使指針指向中間的位置。雖然跟上述兩種作法的時間複雜度同樣,都是O(n),可是,卻用了兩次循環,並且感受本身的作法特別的笨。而後看到解法一的解題思路時,我在想爲何還要用數組,跟個人想法不是差很少,卻還要在定義新的臨時變量,結果看完代碼…好吧,是個人思路不對,存進數組後直接輸出就行了,根本不用再次遍歷。而後看到解法二的時候,內心的想法:真的是妙啊,連新的臨時變量都用不上了,而後就想到了鏈表倒數第k個數的那道題,有殊途同歸之妙。
因此記下這道題,一是給本身一個新的邏輯思惟跟解題思路,更是提醒本身觸類旁通,不要新的思路解法學了,卻運用不到其餘相似的題目上。
相關文章
相關標籤/搜索