u
This commit is contained in:
@@ -0,0 +1,101 @@
|
|||||||
|
package top100liked
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://leetcode.cn/problems/linked-list-cycle-ii/?envType=study-plan-v2&envId=top-100-liked
|
||||||
|
|
||||||
|
type ListNode struct {
|
||||||
|
Val int
|
||||||
|
Next *ListNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 哈希表
|
||||||
|
// func detectCycle(head *ListNode) *ListNode {
|
||||||
|
// _map := make(map[*ListNode]bool)
|
||||||
|
// for head != nil {
|
||||||
|
// if _map[head] {
|
||||||
|
// return head
|
||||||
|
// }
|
||||||
|
// _map[head] = true
|
||||||
|
// head = head.Next
|
||||||
|
// }
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 快慢指针法
|
||||||
|
// 核心推导如下:
|
||||||
|
//
|
||||||
|
// 设定变量
|
||||||
|
//
|
||||||
|
// • a = 头节点到入环点的距离
|
||||||
|
// • b = 入环点到相遇点的距离
|
||||||
|
// • c = 相遇点回到入环点的距离(环长 = b + c)
|
||||||
|
//
|
||||||
|
// 推导
|
||||||
|
//
|
||||||
|
// 相遇时:
|
||||||
|
//
|
||||||
|
// • slow 走了 a + b
|
||||||
|
// • fast 走了 a + b + n(b + c)(多走了 n 整圈)
|
||||||
|
// • 因为 fast 速度是 slow 的 2 倍:2(a + b) = a + b + n(b + c)
|
||||||
|
//
|
||||||
|
// 化简得:
|
||||||
|
//
|
||||||
|
// a + b = n(b + c)
|
||||||
|
//
|
||||||
|
// a = n(b + c) - b
|
||||||
|
// a = (n-1)(b + c) + c
|
||||||
|
//
|
||||||
|
// 等式的含义
|
||||||
|
//
|
||||||
|
// a = (n-1)(b + c) + c 意味着:
|
||||||
|
// 从头节点走 a 步 = 从相遇点走 (n-1) 整圈 + 再走 c 步
|
||||||
|
// 而 c 步恰好就是从相遇点回到入环点的距离。
|
||||||
|
//
|
||||||
|
// 所以
|
||||||
|
//
|
||||||
|
// • ptr 从头出发,走 a 步到达入环点
|
||||||
|
// • slow 从相遇点出发,走 (n-1) 圈 + c 步,也到达入环点
|
||||||
|
// • 两者速度相同、同时出发,必然在入环点相遇
|
||||||
|
//
|
||||||
|
// 这就是为什么不需要知道 a、b、c 的具体值,只需要让两个指针同速走,就能找到入口。
|
||||||
|
func detectCycle(head *ListNode) *ListNode {
|
||||||
|
slow, fast := head, head
|
||||||
|
for fast != nil {
|
||||||
|
slow = slow.Next
|
||||||
|
if fast.Next == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fast = fast.Next.Next
|
||||||
|
if fast == slow {
|
||||||
|
p := head
|
||||||
|
for p != slow {
|
||||||
|
p = p.Next
|
||||||
|
slow = slow.Next
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
input := &ListNode{
|
||||||
|
Val: 3,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 2,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 0,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: -4,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input.Next.Next.Next.Next = input.Next
|
||||||
|
fmt.Println(detectCycle(input))
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package top100liked
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://leetcode.cn/problems/merge-two-sorted-lists/description/?envType=study-plan-v2&envId=top-100-liked
|
||||||
|
|
||||||
|
type ListNode struct {
|
||||||
|
Val int
|
||||||
|
Next *ListNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
|
||||||
|
p1, p2 := list1, list2
|
||||||
|
p := &ListNode{}
|
||||||
|
res := p
|
||||||
|
for p1 != nil && p2 != nil {
|
||||||
|
if p1.Val <= p2.Val {
|
||||||
|
p.Next = p1
|
||||||
|
p = p.Next
|
||||||
|
p1 = p1.Next
|
||||||
|
} else {
|
||||||
|
p.Next = p2
|
||||||
|
p = p.Next
|
||||||
|
p2 = p2.Next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for p1 != nil {
|
||||||
|
p.Next = p1
|
||||||
|
p = p.Next
|
||||||
|
p1 = p1.Next
|
||||||
|
}
|
||||||
|
for p2 != nil {
|
||||||
|
p.Next = p2
|
||||||
|
p = p.Next
|
||||||
|
p2 = p2.Next
|
||||||
|
}
|
||||||
|
return res.Next
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
input1 := &ListNode{
|
||||||
|
Val: -9,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 3,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input2 := &ListNode{
|
||||||
|
Val: 5,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 7,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output := mergeTwoLists(input1, input2)
|
||||||
|
for output != nil {
|
||||||
|
fmt.Println(output.Val)
|
||||||
|
output = output.Next
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package top100liked
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://leetcode.cn/problems/add-two-numbers/description/?envType=study-plan-v2&envId=top-100-liked
|
||||||
|
|
||||||
|
type ListNode struct {
|
||||||
|
Val int
|
||||||
|
Next *ListNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
|
||||||
|
dummy := &ListNode{}
|
||||||
|
p := dummy
|
||||||
|
carry := 0
|
||||||
|
for l1 != nil || l2 != nil || carry > 0 {
|
||||||
|
sum := carry
|
||||||
|
if l1 != nil {
|
||||||
|
sum += l1.Val
|
||||||
|
l1 = l1.Next
|
||||||
|
}
|
||||||
|
if l2 != nil {
|
||||||
|
sum += l2.Val
|
||||||
|
l2 = l2.Next
|
||||||
|
}
|
||||||
|
p.Next = &ListNode{Val: sum % 10}
|
||||||
|
p = p.Next
|
||||||
|
carry = sum / 10
|
||||||
|
}
|
||||||
|
return dummy.Next
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
input1 := &ListNode{
|
||||||
|
Val: 2,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 4,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 3,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input2 := &ListNode{
|
||||||
|
Val: 5,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 6,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 4,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output := addTwoNumbers(input1, input2)
|
||||||
|
for output != nil {
|
||||||
|
fmt.Println(output.Val)
|
||||||
|
output = output.Next
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package top100liked
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/?envType=study-plan-v2&envId=top-100-liked
|
||||||
|
|
||||||
|
type ListNode struct {
|
||||||
|
Val int
|
||||||
|
Next *ListNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// func removeNthFromEnd(head *ListNode, n int) *ListNode {
|
||||||
|
// pre := &ListNode{Next: head}
|
||||||
|
// p := head
|
||||||
|
// l := 0
|
||||||
|
// for p != nil {
|
||||||
|
// l++
|
||||||
|
// p = p.Next
|
||||||
|
// }
|
||||||
|
// p1 := pre
|
||||||
|
// p2 := pre.Next.Next
|
||||||
|
// for range l - n {
|
||||||
|
// p1 = p1.Next
|
||||||
|
// p2 = p2.Next
|
||||||
|
// }
|
||||||
|
// p1.Next = p2
|
||||||
|
// return pre.Next
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 双指针
|
||||||
|
func removeNthFromEnd(head *ListNode, n int) *ListNode {
|
||||||
|
dummy := &ListNode{0, head}
|
||||||
|
first, second := head, dummy
|
||||||
|
for range n {
|
||||||
|
first = first.Next
|
||||||
|
}
|
||||||
|
for first != nil {
|
||||||
|
first = first.Next
|
||||||
|
second = second.Next
|
||||||
|
}
|
||||||
|
second.Next = second.Next.Next
|
||||||
|
return dummy.Next
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
input1 := &ListNode{
|
||||||
|
Val: 1,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 2,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 3,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 4,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 5,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input2 := &ListNode{
|
||||||
|
Val: 1,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 2,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output := removeNthFromEnd(input1, 2)
|
||||||
|
for output != nil {
|
||||||
|
fmt.Print(output.Val, " ")
|
||||||
|
output = output.Next
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
output = removeNthFromEnd(input2, 1)
|
||||||
|
for output != nil {
|
||||||
|
fmt.Print(output.Val, " ")
|
||||||
|
output = output.Next
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package top100liked
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://leetcode.cn/problems/swap-nodes-in-pairs/description/?envType=study-plan-v2&envId=top-100-liked
|
||||||
|
|
||||||
|
type ListNode struct {
|
||||||
|
Val int
|
||||||
|
Next *ListNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func swapPairs(head *ListNode) *ListNode {
|
||||||
|
if head == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if head.Next == nil {
|
||||||
|
return head
|
||||||
|
}
|
||||||
|
dummy := &ListNode{0, head}
|
||||||
|
p1, p2, p3 := dummy, dummy.Next, dummy.Next.Next
|
||||||
|
for {
|
||||||
|
p1.Next = p3
|
||||||
|
p2.Next = p3.Next
|
||||||
|
p3.Next = p2
|
||||||
|
p2, p3 = p3, p2
|
||||||
|
for range 2 {
|
||||||
|
if p3.Next == nil {
|
||||||
|
return dummy.Next
|
||||||
|
}
|
||||||
|
p1 = p1.Next
|
||||||
|
p2 = p2.Next
|
||||||
|
p3 = p3.Next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// func swapPairs(head *ListNode) *ListNode {
|
||||||
|
// dummyHead := &ListNode{0, head}
|
||||||
|
// temp := dummyHead
|
||||||
|
// for temp.Next != nil && temp.Next.Next != nil {
|
||||||
|
// node1 := temp.Next
|
||||||
|
// node2 := temp.Next.Next
|
||||||
|
// temp.Next = node2
|
||||||
|
// node1.Next = node2.Next
|
||||||
|
// node2.Next = node1
|
||||||
|
// temp = node1
|
||||||
|
// }
|
||||||
|
// return dummyHead.Next
|
||||||
|
// }
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
input1 := &ListNode{
|
||||||
|
Val: 1,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 2,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 3,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 4,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input2 := &ListNode{
|
||||||
|
Val: 1,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 2,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 3,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output := swapPairs(input1)
|
||||||
|
for output != nil {
|
||||||
|
fmt.Print(output.Val, " ")
|
||||||
|
output = output.Next
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
output = swapPairs(input2)
|
||||||
|
for output != nil {
|
||||||
|
fmt.Print(output.Val, " ")
|
||||||
|
output = output.Next
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package top100liked
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://leetcode.cn/problems/reverse-nodes-in-k-group/description/?envType=study-plan-v2&envId=top-100-liked
|
||||||
|
|
||||||
|
type ListNode struct {
|
||||||
|
Val int
|
||||||
|
Next *ListNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交记录 3
|
||||||
|
// 你就说快不快吧
|
||||||
|
// func reverseKGroup(head *ListNode, k int) *ListNode {
|
||||||
|
// if k == 1 {
|
||||||
|
// return head
|
||||||
|
// }
|
||||||
|
// nodes := []*ListNode{}
|
||||||
|
// p := head
|
||||||
|
// nodes = append(nodes, &ListNode{0, head})
|
||||||
|
// for p != nil {
|
||||||
|
// nodes = append(nodes, p)
|
||||||
|
// p = p.Next
|
||||||
|
// }
|
||||||
|
// tmp := nodes[0]
|
||||||
|
// for i := range (len(nodes) - 1) / k {
|
||||||
|
// tmp.Next = nodes[(i+1)*k]
|
||||||
|
// nodes[i*k+1].Next = nodes[(i+1)*k].Next
|
||||||
|
// for j := range k - 1 {
|
||||||
|
// nodes[(i+1)*k-j].Next = nodes[(i+1)*k-j-1]
|
||||||
|
// }
|
||||||
|
// tmp = nodes[i*k+1]
|
||||||
|
// }
|
||||||
|
// return nodes[0].Next
|
||||||
|
// }
|
||||||
|
|
||||||
|
func reverseKGroup(head *ListNode, k int) *ListNode {
|
||||||
|
dummy := &ListNode{Next: head}
|
||||||
|
prev := dummy
|
||||||
|
for {
|
||||||
|
// 检查剩余节点是否够 k 个
|
||||||
|
tail := prev
|
||||||
|
for range k {
|
||||||
|
tail = tail.Next
|
||||||
|
if tail == nil {
|
||||||
|
return dummy.Next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next := tail.Next // 下一组的起点
|
||||||
|
// 翻转 [prev, tail] 这 k 个节点
|
||||||
|
p := prev.Next
|
||||||
|
var reversedHead, reversedTail *ListNode
|
||||||
|
reversedTail = p // 翻转后 p 变成尾部
|
||||||
|
var pre *ListNode
|
||||||
|
for range k {
|
||||||
|
tmp := p.Next
|
||||||
|
p.Next = pre
|
||||||
|
pre = p
|
||||||
|
p = tmp
|
||||||
|
}
|
||||||
|
reversedHead = pre
|
||||||
|
// 接回原链表
|
||||||
|
prev.Next = reversedHead
|
||||||
|
reversedTail.Next = next
|
||||||
|
prev = reversedTail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test1(t *testing.T) {
|
||||||
|
input := &ListNode{
|
||||||
|
Val: 1,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 2,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 3,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 4,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 5,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output := reverseKGroup(input, 2)
|
||||||
|
for output != nil {
|
||||||
|
fmt.Print(output.Val, " ")
|
||||||
|
output = output.Next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test2(t *testing.T) {
|
||||||
|
input := &ListNode{
|
||||||
|
Val: 1,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 2,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 3,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 4,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 5,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output := reverseKGroup(input, 3)
|
||||||
|
for output != nil {
|
||||||
|
fmt.Print(output.Val, " ")
|
||||||
|
output = output.Next
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test3(t *testing.T) {
|
||||||
|
input := &ListNode{
|
||||||
|
Val: 1,
|
||||||
|
Next: &ListNode{
|
||||||
|
Val: 2,
|
||||||
|
Next: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output := reverseKGroup(input, 2)
|
||||||
|
for output != nil {
|
||||||
|
fmt.Print(output.Val, " ")
|
||||||
|
output = output.Next
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user