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