type ListNode struct {
Val int
Next *ListNode
}
- null/nil 异常处理
- dummy node 哑巴节点
- 快慢指针
- 插入一个节点到排序链表
- 从一个链表中移除一个节点
- 翻转链表
- 合并两个链表
- 找到链表的中间节点
func deleteDuplicates(head *ListNode) *ListNode {
current := head
for current != nil {
for current.Next != nil && current.Val == current.Next.Val {
current.Next = current.Next.Next
}
current = current.Next
}
return head
}
func deleteDuplicates(head *ListNode) *ListNode {
if head == nil {
return head
}
dummy := &ListNode{Val: 0}
dummy.Next = head
head = dummy
var rmVal int
for head.Next != nil && head.Next.Next != nil {
if head.Next.Val == head.Next.Next.Val {
rmVal = head.Next.Val
for head.Next != nil && head.Next.Val == rmVal {
head.Next = head.Next.Next
}
} else {
head = head.Next
}
}
return dummy.Next
}
注意点 • A->B->C 删除 B,A.next = C • 删除用一个 Dummy Node 节点辅助(允许头节点可变) • 访问 X.next 、X.value 一定要保证 X != nil
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
for head != nil {
temp := head.Next
head.Next = prev
prev = head
head = temp
}
return prev
}
func reverseBetween(head *ListNode, left int, right int) *ListNode {
if head == nil {
return head
}
dummy := &ListNode{Val: 0}
dummy.Next = head
head = dummy
var prev *ListNode
i := 0
for i < left {
prev = head
head = head.Next
i++
}
var j = i
var next *ListNode
var mid = head
for head != nil && j <= right {
temp := head.Next
head.Next = next
next = head
head = temp
j++
}
prev.Next = next
mid.Next = head
return dummy.Next
}
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
if list1 == nil {
return list2
}
if list2 == nil {
return list1
}
var dummy = &ListNode{Val: 0}
var head = &ListNode{Val: 0}
dummy.Next = head
for list1 != nil || list2 != nil {
if list1 == nil {
for list2 != nil {
head.Next = list2
list2 = list2.Next
head = head.Next
}
break
}
if list2 == nil {
for list1 != nil {
head.Next = list1
list1 = list1.Next
head = head.Next
}
break
}
if list1.Val <= list2.Val {
head.Next = list1
list1 = list1.Next
} else {
head.Next = list2
list2 = list2.Next
}
head = head.Next
}
return dummy.Next.Next
}
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
dummy := &ListNode{Val: 0}
head := dummy
for list1 != nil && list2 != nil {
if list1.Val < list2.Val {
head.Next = list1
list1 = list1.Next
} else {
head.Next = list2
list2 = list2.Next
}
head = head.Next
}
for list1 != nil {
head.Next = list1
list1 = list1.Next
head = head.Next
}
for list2 != nil {
head.Next = list2
list2 = list2.Next
head = head.Next
}
return dummy.Next
}
func partition(head *ListNode, x int) *ListNode {
if head == nil {
return head
}
headDummy := &ListNode{Val: 0}
tailDummy := &ListNode{Val: 0}
tail := tailDummy
headDummy.Next = head
head = headDummy
for head.Next != nil {
if head.Next.Val < x {
head = head.Next
} else {
t := head.Next
head.Next = head.Next.Next
tail.Next = t
tail = tail.Next
}
}
tail.Next = nil
head.Next = tailDummy.Next
return headDummy.Next
}
func sortList(head *ListNode) *ListNode {
return mergeSort(head)
}
func findMiddle(head *ListNode) *ListNode {
slow := head
fast := head.Next
for fast != nil && fast.Next != nil {
fast = fast.Next.Next
slow = slow.Next
}
return slow
}
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
dummy := &ListNode{Val: 0}
head := dummy
for l1 != nil && l2 != nil {
if l1.Val < l2.Val {
head.Next = l1
l1 = l1.Next
} else {
head.Next = l2
l2 = l2.Next
}
head = head.Next
}
for l1 != nil {
head.Next = l1
l1 = l1.Next
head = head.Next
}
for l2 != nil {
head.Next = l2
l2 = l2.Next
head = head.Next
}
return dummy.Next
}
func mergeSort(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
middle := findMiddle(head)
tail := middle.Next
middle.Next = nil
left := mergeSort(head)
right := mergeSort(tail)
result := mergeTwoLists(left, right)
return result
}
func reorderList(head *ListNode) {
if head == nil || head.Next == nil {
return
}
middle := findMiddle(head)
tail := middle.Next
middle.Next = nil
tail = reverseList(tail)
head = mergeTwoLists(head, tail)
}
func findMiddle(head *ListNode) *ListNode {
slow := head
fast := head.Next
for fast != nil && fast.Next != nil {
fast = fast.Next.Next
slow = slow.Next
}
return slow
}
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
for head != nil {
temp := head.Next
head.Next = prev
prev = head
head = temp
}
return prev
}
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
dummy := &ListNode{Val: 0}
head := dummy
for l1 != nil && l2 != nil {
head.Next = l1
l1 = l1.Next
head = head.Next
head.Next = l2
l2 = l2.Next
head = head.Next
}
for l1 != nil {
head.Next = l1
l1 = l1.Next
head = head.Next
}
for l2 != nil {
head.Next = l2
l2 = l2.Next
head = head.Next
}
return dummy.Next
}
func hasCycle(head *ListNode) bool {
if head == nil {
return false
}
fast := head.Next
slow := head
for fast != nil && fast.Next != nil {
if fast == slow {
return true
}
fast = fast.Next.Next
slow = slow.Next
}
return false
}
func detectCycle(head *ListNode) *ListNode {
if head == nil {
return nil
}
fast := head.Next
slow := head
for fast != nil && fast.Next != nil {
if fast == slow {
fast = head
slow = slow.Next
for fast != slow {
fast = fast.Next
slow = slow.Next
}
return slow
}
fast = fast.Next.Next
slow = slow.Next
}
return nil
}
- 指针比较时直接比较对象,不要用值比较,链表中有可能存在重复值情况;
- 第一次相交后,快指针需要从下一个节点开始和头指针一起匀速移动.
另外一种方式是 fast=head,slow=head
func detectCycle(head *ListNode) *ListNode {
// 思路:快慢指针,快慢相遇之后,其中一个指针回到头,快慢指针步调一致一起移动,相遇点即为入环点
// nb+a=2nb+a
if head == nil {
return head
}
fast := head
slow := head
for fast != nil && fast.Next != nil {
fast = fast.Next.Next
slow = slow.Next
if fast == slow {
// 指针重新从头开始移动
fast = head
for fast != slow {
fast = fast.Next
slow = slow.Next
}
return slow
}
}
return nil
}
这两种方式不同点在于,一般用 fast=head.Next 较多,因为这样可以知道中点的上一个节点,可以用来删除等操作。
- fast 如果初始化为 head.Next 则中点在 slow.Next;
- fast 初始化为 head,则中点在 slow.
func isPalindrome(head *ListNode) bool {
// 1 2 nil
// 1 2 1 nil
// 1 2 2 1 nil
if head==nil{
return true
}
slow:=head
// fast如果初始化为head.Next则中点在slow.Next
// fast初始化为head,则中点在slow
fast:=head.Next
for fast!=nil&&fast.Next!=nil{
fast=fast.Next.Next
slow=slow.Next
}
tail:=reverse(slow.Next)
// 断开两个链表(需要用到中点前一个节点)
slow.Next=nil
for head!=nil&&tail!=nil{
if head.Val!=tail.Val{
return false
}
head=head.Next
tail=tail.Next
}
return true
}
func reverse(head *ListNode)*ListNode{
// 1->2->3
if head==nil{
return head
}
var prev *ListNode
for head!=nil{
t:=head.Next
head.Next=prev
prev=head
head=t
}
return prev
}
func copyRandomList(head *Node) *Node {
if head == nil {
return head
}
cur := head
for cur != nil {
clone := &Node{Val: cur.Val, Next: cur.Next}
temp := cur.Next
cur.Next = clone
cur = temp
}
cur = head
for cur != nil {
if cur.Random != nil {
cur.Next.Random = cur.Random.Next
}
cur = cur.Next.Next
}
cur = head
cloneHead := cur.Next
for cur != nil && cur.Next != nil {
temp := cur.Next
cur.Next = cur.Next.Next
cur = temp
}
return cloneHead
}