leetcode热题100-GO-解-2025.3.25
29/100
当日懒得写了,题量是3.28补的(
234.回文链表
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
示例 1:

1 2
| 输入:head = [1,2,2,1] 输出:true
|
示例 2:

1 2
| 输入:head = [1,2] 输出:false
|
解一
一眼用栈,先入后出匹配一下就行
时间复杂度O(n),空间复杂度O(n)
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
|
func isPalindrome(head *ListNode) bool { if head == nil || head.Next == nil { return true } if head.Next.Next == nil { return head.Val == head.Next.Val } stack := make([]int, 0)
curr := head for curr.Next != nil && curr.Next.Next != nil { stack = append(stack, curr.Val) curr = curr.Next } if curr.Next == nil { stack = append(stack, curr.Val) } if curr.Next.Next == nil { stack = append(stack, curr.Val) stack = append(stack, curr.Next.Val) } for i := len(stack) - 1; i >= 0; i-- { if stack[i] != head.Val { return false } head = head.Next } return true }
|
解二
快慢指针找中点 空间复杂度O(1)
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
|
func isPalindrome2(head *ListNode) bool { if head == nil || head.Next == nil { return true } if head.Next.Next == nil { return head.Val == head.Next.Val }
slow, fast := head, head for fast != nil && fast.Next != nil { slow = slow.Next fast = fast.Next.Next }
var prev *ListNode for slow != nil { next := slow.Next slow.Next = prev prev = slow slow = next }
for prev != nil { if head.Val != prev.Val { return false } head = head.Next prev = prev.Next } return true }
|
141.环形链表
给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true
。 否则,返回 false
。
示例 1:

1 2 3
| 输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。
|
示例 2:

1 2 3
| 输入:head = [1,2], pos = 0 输出:true 解释:链表中有一个环,其尾部连接到第一个节点。
|
示例 3:

1 2 3
| 输入:head = [1], pos = -1 输出:false 解释:链表中没有环。
|
快慢指针,两者若能指向同一地址则有环,否则无环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| func hasCycle(head *ListNode) bool { if head == nil || head.Next == nil { return false } if head.Next.Next == nil { return false } slow, fast := head, head for fast != nil && fast.Next != nil { slow = slow.Next fast = fast.Next.Next if slow == fast { return true } } return false }
|
142.环形链表 II
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:

1 2 3
| 输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点 解释:链表中有一个环,其尾部连接到第二个节点。
|
示例 2:

1 2 3
| 输入:head = [1,2], pos = 0 输出:返回索引为 0 的链表节点 解释:链表中有一个环,其尾部连接到第一个节点。
|
示例 3:

1 2 3
| 输入:head = [1], pos = -1 输出:返回 null 解释:链表中没有环。
|
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
| func detectCycle(head *ListNode) *ListNode { slow, fast := head, head hasCycle := false
for fast != nil && fast.Next != nil { slow = slow.Next fast = fast.Next.Next if slow == fast { hasCycle = true break } }
if !hasCycle { return nil }
slow = head for slow != fast { slow = slow.Next fast = fast.Next }
return slow }
|
设链表头节点到环的起始节点的距离为 a
,环的起始节点到快慢指针相遇节点的距离为 b
,相遇节点再到环的起始节点的距离为 c
。
- 快慢指针移动距离关系:
- 当快慢指针相遇时,慢指针
slow
移动的距离为 a + b
。
- 快指针
fast
移动的距离为 a + b + k * (b + c)
,其中 k
为快指针在环内绕的圈数(k >= 1
)。因为快指针速度是慢指针的两倍,所以快指针移动的距离也是慢指针的两倍,即 2 * (a + b) = a + b + k * (b + c)
。
- 等式化简:
- 对
2 * (a + b) = a + b + k * (b + c)
进行化简,得到 a + b = k * (b + c)
,进一步变形为 a = (k - 1) * (b + c) + c
。
- 这个等式表明,从链表头节点到环的起始节点的距离
a
,等于快指针在环内绕 k - 1
圈后再加上从相遇节点到环的起始节点的距离 c
。
- 寻找环的起始节点:
- 当快慢指针相遇后,将慢指针
slow
重新移动到链表头节点,然后让慢指针 slow
和快指针 fast
以相同的速度(每次移动一步)继续移动。
- 由于
a = (k - 1) * (b + c) + c
,当慢指针 slow
移动距离 a
到达环的起始节点时,快指针 fast
也刚好在环内绕了 k - 1
圈后再移动距离 c
,同样到达环的起始节点,此时快慢指针再次相遇,相遇节点就是环的起始节点。
21.合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
水题,略
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 mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode { if list1 == nil { return list2 } if list2 == nil { return list1 } dummy := &ListNode{} curr := dummy for list1 != nil && list2 != nil { if list1.Val < list2.Val { curr.Next = list1 list1 = list1.Next } else { curr.Next = list2 list2 = list2.Next } curr = curr.Next } if list1 != nil { curr.Next = list1 } if list2 != nil { curr.Next = list2 } return dummy.Next }
|
2.两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:

1 2 3
| 输入:l1 = [2,4,3], l2 = [5,6,4] 输出:[7,0,8] 解释:342 + 465 = 807.
|
示例 2:
1 2
| 输入:l1 = [0], l2 = [0] 输出:[0]
|
示例 3:
1 2
| 输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9] 输出:[8,9,9,9,0,0,0,1]
|
典型错误解:
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
| func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { sum1 := 0 sum2 := 0 for i := 0; l1 != nil; i++ { sum1 += l1.Val * int(math.Pow10(i)) l1 = l1.Next } for i := 0; l2 != nil; i++ { sum2 += l2.Val * int(math.Pow10(i)) l2 = l2.Next } sum := sum1 + sum2 if sum == 0 { return &ListNode{Val: 0} } dummy := &ListNode{} curr := dummy for sum != 0 { curr.Next = &ListNode{Val: sum % 10} sum /= 10 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
| func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { dummy := &ListNode{} curr := 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 } carry = sum / 10 curr.Next = &ListNode{Val: sum % 10} curr = curr.Next }
return dummy.Next }
|
19.删除链表的倒数第N个节点
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
示例 1:
1 2
| 输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]
|
示例 2:
1 2
| 输入:head = [1], n = 1 输出:[]
|
示例 3:
1 2
| 输入:head = [1,2], n = 1 输出:[1]
|
快慢指针
指针先走N步,慢指针再开始走
快指针到达链表尾时慢指针为倒数第N个
删除操作不必多说
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} slow, fast := dummy, dummy for i := 0; i <= n; i++ { fast = fast.Next } for fast != nil { slow = slow.Next fast = fast.Next } slow.Next = slow.Next.Next return dummy.Next }
|