常見鍊錶問題

2021-10-22 03:22:35 字數 3472 閱讀 7746

給定單向鍊錶的頭指標和乙個要刪除的節點的值,定義乙個函式刪除該節點。

返回刪除後的鍊錶的頭節點。

示例 1:

輸入: head = [4,5,1,9], val = 5

輸出: [4,1,9]

解釋: 給定你鍊錶中值為 5 的第二個節點,那麼在呼叫了你的函式之後,該鍊錶應變為 4 -> 1 -> 9.

示例 2:

輸入: head = [4,5,1,9], val = 1

輸出: [4,5,9]

解釋: 給定你鍊錶中值為 1 的第三個節點,那麼在呼叫了你的函式之後,該鍊錶應變為 4 -> 5 -> 9.

考慮可能有刪除頭節點的情況,在頭節點前新增乙個前置節點dummy,新鍊錶的頭節點即為dummy.next

初始化兩個指標,pre = dummy,cur = head

只要當前節點的值cur.val與目標值val不相等,cur後移,pre一直指向cur的前乙個節點

找到要刪除的節點後,讓前乙個節點指向下下個節點即可,pre.next = cur.next

返回新鍊錶的頭節點dummy.next

func

deletenode

(head *listnode, val int

)*listnode

// 設定前置啞節點

dummy.next = head // 啞節點的next指向頭節點

pre, cur := dummy, head // pre和cur分別指向前置和當前節點

for cur !=

nil

pre = cur // 否則,前置節點一直後移:指向當前節點

cur = cur.next // 當前節點後移,指向下乙個節點

}return dummy.next // 啞節點的下乙個節點即為所求

}

由於需要遍歷鍊錶,所以時間複雜度為o(n),n代表鍊錶長度;

使用了常數個變數節點,由於存放啞節點、前置節點、當前節點,所以空間複雜度為o(1)。

定義乙個函式,輸入乙個鍊錶的頭節點,反轉該鍊錶並輸出反轉後鍊錶的頭節點。

示例:

輸入: 1->2->3->4->5->null

輸出: 5->4->3->2->1->null

限制:

0 <= 節點個數 <= 5000

下面使用雙指標、遞迴兩種方法講解。

雙指標解法

(1)解題思路

定義兩個指標: pre和 cur ;pre 在前 cur 在後。

每次讓 pre 的 next 指向 cur ,實現一次區域性反轉

區域性反轉完成之後, pre 和 cur 同時往前移動乙個位置

迴圈上述過程,直至 pre 到達鍊錶尾部

(2)**實現

func

reverselist

(head *listnode)

*listnode

return pre

}

(3)複雜度分析

時間複雜度o(n),空間複雜度o(1)

(4)執行效果

遞迴解法

(1)解題思路

頭結點或頭結點的後續節點為空,直接返回

將head.next之後的節點呼叫自身,都翻轉後存放在newhead鍊錶中,翻轉後newhead即為新的頭結點

然後,在處理head.next的後續指標指向head,並將head的後續節點指向空,即實現所有節點的翻轉。

(2)**實現

func

reverselist

(head *listnode)

*listnode

newhead :=

reverselist

(head.next)

// 遞迴呼叫自身,將head.next之後的節點翻轉,newhead即為翻轉後的頭結點

head.next.next = head // head.next的後續節點指向head頭

head.next =

nil// head頭的後續指標指向空節點

return newhead // 返回翻轉後的頭結點

}

(3)複雜度分析

時間複雜度:o(n),n為鍊錶節點個數;空間複雜度o(n),n為遞迴棧深度

(4)執行效果

輸入兩個遞增排序的鍊錶,合併這兩個鍊錶並使新鍊錶中的節點仍然是遞增排序的。

示例1:

輸入:1->2->4, 1->3->4

輸出:1->1->2->3->4->4

限制:0 <= 鍊錶長度 <= 1000

1. 初始化: 前置偽頭節點 pre ,當前節點cur指向pre 。

2. 迴圈合併: 當 l1或l2為空時跳出迴圈;

a. 當 l1.val <= l2.val 時, cur的後繼節點指定為 l1,l1後移乙個節點;

b. 當 l1.val > l2.val 時, cur的後繼節點指定為 l2,l2後移乙個節點;

c. 節點 cur向前走一步,即 cur = cur.next。

3. 合併剩餘尾部: 跳出時有兩種情況,即 l1為空或l2為空

a. 當l1不為空時,將l1新增到cur的後繼節點中;

b. 當l2不為空時,將l2新增到cur的後繼節點中。

4. 合併的鍊錶在偽節點之後,因此返回偽節點的next即為所求。

func

mergetwolists

(l1 *listnode, l2 *listnode)

*listnode

// 初始化前置節點

cur := pre // 當前節點指向前置節點

for l1 !=

nil&& l2 !=

nilelse

cur = cur.next

}if l1 !=

nilif l2 !=

nilreturn pre.next

}

時間複雜度為o(m+n),m和n分別表示l1和l2鍊錶的長度;

空間複雜度為o(1),因為使用到pre和cur常數個變數。

鍊錶常見問題

思路 快慢指標,慢指標每次移動一步,快指標每次移動兩步,如果存在環,那麼兩個指標一定會在環內相遇 把第二個煉表頭節點的頭接到第乙個鍊錶尾部,然後就轉換成判斷單鏈表是否有環的問題了 當快慢指標相遇後,將乙個指標固定在相遇點,另乙個指標回到鍊錶起始位置,然後兩指標每次都移動乙個node,當兩指標再次相遇...

鍊錶常見問題 2

這個問題大家在資料結構中是很常見的,這個問題說簡單也簡單,可是想不通的時候還是有點難度的,領扣對這道題的描述有以下幾種情況 領扣給的鍊錶節點定義方式 definition for singly linked list.class listnode 方法 public boolean hascycle...

鍊錶常見問題(上)

void slistprinttailtohead slistnode phead printf d cur data tail cur 遞迴實現 void slistprinttailtoheadr slistnode phead void slistdelnontailnode slistnod...