給定單向鍊錶的頭指標和乙個要刪除的節點的值,定義乙個函式刪除該節點。
返回刪除後的鍊錶的頭節點。
示例 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...