前言
链表分成多种,这里总结链表常见操作和链表的类型
单链表
最简单的链表,只有指向下一个链表的指针
结构
* type ListNode struct {
* Val int
* Next *ListNode
* }
常见操作
遍历
for node := head;node != nil;node=node.Next {
}
插入(在第K个位置插入,k的范围是1~n)
func Insert(node *Node){
cnt := 0
knode := head
for ;knode != nil && cnt != k-1;knode=knode.Next { // 取到地k-1个结点 然后插入到它后面
cnt ++
}
node.Next := knode.Next
knode.Next = node
}
链表题常见思路
快慢双指针遍历链表(判环)
题目:leetcode141 思路:通过快慢指针判断,如果一个快,一个慢,总是会相遇的 代码:
func hasCycle(head *ListNode) bool {
if head == nil || head.Next == nil {
return false
}
fastPtr := head.Next
slowPtr := head
for {
if slowPtr == fastPtr {
return true
}
if slowPtr.Next == nil {
break
}else if fastPtr.Next == nil || fastPtr.Next.Next == nil {
break
}
slowPtr = slowPtr.Next
fastPtr = fastPtr.Next.Next
}
return false
}
随机链表的复制
题目:leetcode138 middle 思路:一开始思考Random可能会卡住。但其实我们不需要关心老链表的Random之间是怎么映射的。只需要维护新老链表节点的映射关系,就可以将老链表的数据关系无缝迁移了
func copyRandomList(head *Node) *Node {
mOldNew := make(map[*Node]*Node)
newHead := &Node{}
newNode := newHead
for node:=head;node!=nil;node=node.Next{
now := &Node{
Val: node.Val,
}
newNode.Next = now
newNode = now
mOldNew[node] = now
}
for node:=head;node!=nil;node=node.Next{
mOldNew[node].Random = mOldNew[node.Random]
}
return newHead.Next
}
反转链表
题目:leetcode92 思路:既然是区间反转,首先可以拆分成两个步骤:
- 先把中间这段反转
- 反转后,处理首尾指针关系
中间反转的思路: 当前指针依次指向上一个指针.
先考虑左端点:我们需要关注left前一个节点,即为反转后的链表头,链表头最后一个节点的位置是left-1,由于题目头节点不是虚拟节点,所以我们创造一个虚拟节点,把链表挂载上 考虑右端点:我们需要关注right后一个节点的地址,为反转后的链表尾的第一个节点位置是right+1,就是right.Next,提前保存,然后拼接
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseBetween(head *ListNode, left int, right int) *ListNode {
//首先l r >=1
if left == right{
return head
}
// 逻辑上得到left-1 还有right节点
// 修改Left - 1节点的指针
// 修改right节点
cnt := 0
h := &ListNode{Next: head}
leftBeforeNode := h
rightNode := h
for node := h; node != nil; node= node.Next{
if cnt == left - 1{
leftBeforeNode = node
}
if cnt == right{
rightNode = node
rightNodeNext := rightNode.Next
leftNode := leftBeforeNode.Next
reverse(leftBeforeNode.Next, rightNode)
leftBeforeNode.Next = rightNode
leftNode.Next = rightNodeNext
break
}
cnt ++
}
return h.Next
}
func reverse(st,ed *ListNode){
var lastNode *ListNode
edNext := ed.Next
for node:=st; node!=edNext ;{
nxt := node.Next
node.Next = lastNode
lastNode = node
node = nxt
}
}