DAY 3 本篇部分题目在 『算法拾遗』链表(Linked List) 中已经做过
还有一个递归版,但是那个空间复杂度是 O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 func removeElements (head *ListNode, val int ) *ListNode { dummy := &ListNode{Next: head} curr := dummy for curr.Next != nil { if curr.Next.Val == val { curr.Next = curr.Next.Next } else { curr = curr.Next } } return dummy.Next }
分别写了单向链表和双向链表两个版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 type MyLinkedList struct { head *LinkNode size int } type LinkNode struct { val int next *LinkNode } func Constructor () MyLinkedList { dummyHead := &LinkNode{} return MyLinkedList{ head: dummyHead, size: 0 , } } func (this *MyLinkedList) Get(index int ) int { if index < 0 || index >= this.size { return -1 } cur := this.head.next for i := 0 ; i < index; i++ { cur = cur.next } return cur.val } func (this *MyLinkedList) AddAtHead(val int ) { newNode := &LinkNode{val: val} newNode.next = this.head.next this.head.next = newNode this.size++ } func (this *MyLinkedList) AddAtTail(val int ) { newNode := &LinkNode{val: val} cur := this.head for cur.next != nil { cur = cur.next } cur.next = newNode this.size++ } func (this *MyLinkedList) AddAtIndex(index int , val int ) { if index < 0 || index > this.size { return } if index == this.size { this.AddAtTail(val) return } cur := this.head for i := 0 ; i < index; i++ { cur = cur.next } newNode := &LinkNode{val: val} newNode.next = cur.next cur.next = newNode this.size++ } func (this *MyLinkedList) DeleteAtIndex(index int ) { if index < 0 || index >= this.size { return } cur := this.head for i := 0 ; i < index; i++ { cur = cur.next } cur.next = cur.next.next this.size-- }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 type MyLinkedList struct { size int head *Node tail *Node } type Node struct { val int next, prev *Node } func Constructor () MyLinkedList { dummy := &Node{} dummy.next = dummy dummy.prev = dummy return MyLinkedList{ size: 0 , head: dummy, tail: dummy, } } func (this *MyLinkedList) Get(index int ) int { if index < 0 || index >= this.size { return -1 } curr := this.head.next for i := 0 ; i < index; i++ { curr = curr.next } return curr.val } func (this *MyLinkedList) AddAtHead(val int ) { newNode := &Node{ val: val, next: this.head.next, prev: this.head, } this.head.next.prev = newNode this.head.next = newNode this.size++ } func (this *MyLinkedList) AddAtTail(val int ) { newNode := &Node{ val: val, next: this.tail, prev: this.tail.prev, } this.tail.prev.next = newNode this.tail.prev = newNode this.size++ } func (this *MyLinkedList) AddAtIndex(index int , val int ) { if index < 0 || index > this.size { return } curr := this.head.next for index != 0 { curr = curr.next index-- } newNode := &Node{ val: val, prev: curr.prev, next: curr, } curr.prev.next = newNode curr.prev = newNode this.size++ } func (this *MyLinkedList) DeleteAtIndex(index int ) { if index < 0 || index >= this.size { return } curr := this.head.next for index != 0 { curr = curr.next index-- } curr.next.prev = curr.prev curr.prev.next = curr.next this.size-- }
经典反转链表,操作过程如下
初始化当前节点为头节点 暂存下一个节点 将当前节点指向前一个节点 前驱节点后移 当前节点后移 重复 1-4,只到当前节点为 NULL
,输出前驱结点为新的头结点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 func reverseList (head *ListNode) *ListNode {var prev *ListNode = nil var next *ListNode = nil var curr *ListNode = headfor curr != nil {next = curr.Next curr.Next = prev prev = curr curr = next } return prev}
我一开始也不是很懂,所以我画了个图一步一步来,图画出来我就懂了
类似地,还有一个递归的写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 func reverseList (head *ListNode) *ListNode {if head == nil || head.Next == nil {return head} p := reverseList(head.Next) head.Next.Next = head head.Next = nil return p}
DAY 4 本篇部分题目在 『算法拾遗』链表(Linked List) 中已经做过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 func swapPairs (head *ListNode) *ListNode { dummy:=&ListNode{ Next: head, } curr := dummy for curr!=nil && curr.Next!=nil && curr.Next.Next != nil { first:=curr.Next second:=curr.Next.Next first.Next=second.Next second.Next=first curr.Next=second curr=curr.Next.Next } return dummy.Next }
经典快慢指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func removeNthFromEnd (head *ListNode, n int ) *ListNode { dummy := &ListNode{ Next: head, } fast, slow := dummy, dummy for i := 1 ; i < n; i++ { fast = fast.Next } for fast.Next.Next != nil { fast = fast.Next slow = slow.Next } slow.Next = slow.Next.Next return dummy.Next }
双指针,先对齐再往后走
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 func getIntersectionNode (headA, headB *ListNode) *ListNode { lenA, lenB := 0 , 0 for curr := headA; curr != nil ; curr = curr.Next { lenA++ } for curr := headB; curr != nil ; curr = curr.Next { lenB++ } if lenA < lenB { headA, headB = headB, headA lenA, lenB = lenB, lenA } diff := lenA - lenB a, b := headA, headB for i := 0 ; i < diff; i++ { a = a.Next } for a != nil && b != nil { if a == b { return a } a = a.Next b = b.Next } return nil }
快慢指针找环,然后让其中一个回到原点,再同步前进
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 func detectCycle (head *ListNode) *ListNode { dummy := &ListNode{ Next: head, } fast, slow := dummy, dummy for fast != nil && fast.Next != nil { fast = fast.Next.Next slow = slow.Next if fast == slow { break } } if fast == nil || fast.Next == nil { return nil } fast = dummy for fast != slow { fast = fast.Next slow = slow.Next } return fast }
DAY 5 周日休息