单链表排序和其他链表操作
单链表排序方式
148 排序链表
链表排序
插入排序
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func insertionSortList(head *ListNode) *ListNode {
if head==nil{
return head
}
//定一个前置节点
dummy:=new(ListNode)
cur:=head
for cur!=nil{
//每次从前面的节点寻找大于cur的节点,插入此节点前面
pre:=dummy
for pre.Next!=nil&&pre.Next.Val<cur.Val{
pre = pre.Next
}
next:=cur.Next
//cur 放pre前面
cur.Next = pre.Next
pre.Next = cur
cur = next
}
return dummy.Next
}
归并递归
- 找中点,循环递归
func sortList(head *ListNode) *ListNode {
//快排链表 归并(递归迭代)
if head==nil{
return head
}
return sort(head)
}
//找中点
func sort(head *ListNode)*ListNode{
if head.Next==nil{ //一个直接返回
return head
}
slow,fast,pre:=head,head,head //快慢指针找中点,依据fast判断
for fast!=nil&&fast.Next!=nil{
pre = slow
slow = slow.Next
fast = fast.Next.Next
}
pre.Next = nil //断开链接
left:=sort(head) //左边递归
right:=sort(slow) //右边递归
return merge(left,right)
}
func merge(left,right *ListNode)*ListNode{
dummy:=new(ListNode)
pre:=dummy
for left!=nil&&right!=nil{
if left.Val<right.Val{
pre.Next = left
pre = pre.Next
left = left.Next
}else{
pre.Next = right
pre = pre.Next
right = right.Next
}
}
if left==nil{
pre.Next = right
}else{
pre.Next = left
}
return dummy.Next
}
归并迭代
快排链表
leetcode 148使用链表快排会超时,此方法用于面试,修改节点,不仅仅是交换值
func sortList(head *ListNode) *ListNode {
//快排链表,非互换值
return fast(head)
}
func fast(head *ListNode)*ListNode{
if head==nil||head.Next==nil{ //单点直接返回
return head
}
//大于 等于 小于分别三个头节点
left,mid,right:=new(ListNode),new(ListNode),new(ListNode)
tmp:=head.Val
l,m,r:=left,mid,right
for p:=head;p!=nil;p = p.Next{
if p.Val<tmp{
l.Next = p
l = l.Next
}else if p.Val>tmp{
r.Next= p
r = r.Next
}else{
m.Next = p
m = m.Next
}
}
//断开链接
l.Next=nil
m.Next=nil
r.Next=nil
left.Next = fast(left.Next) //左侧小于val的进行不断排序
right.Next=fast(right.Next)
//结束,循环进行排序然后拼接
getTail(left).Next = mid.Next //左侧小于val的尾部连接等于val的链表头
getTail(mid).Next=right.Next //等于val链表尾部连接大于val的链表头
return left.Next //返回左侧的next
}
//返回尾部节点
func getTail(head *ListNode)*ListNode{
for head.Next!=nil{
head = head.Next
}
return head
}
其他链表操作
138复制复杂链表
- 放置相同数值然后拆分
/**
* Definition for a Node.
* type Node struct {
* Val int
* Next *Node
* Random *Node
* }
*/
func copyRandomList(head *Node) *Node {
if head==nil{
return nil
}
//每个结点后放置相同数值的结点
for cur:=head;cur!=nil;cur = cur.Next.Next{
tmp:=new(Node)
tmp.Val = cur.Val
tmp.Next = cur.Next
cur.Next = tmp
}
//随机指针赋值
for cur:=head;cur!=nil;cur = cur.Next.Next{
tmp:=cur.Next
if cur.Random!=nil{ //不空则赋值下一个,否则默认nil
tmp.Random = cur.Random.Next
}
}
//拆解链表
res:=head.Next
for cur:=head;cur!=nil;cur = cur.Next{
tmp:=cur.Next
cur.Next = cur.Next.Next//连接原始链表
if tmp.Next!=nil{
tmp.Next = tmp.Next.Next
}
}
return res
}
143 重排链表
142 环形链表2
- 主要是公式的推导和for循环判断为fast!=nil
- 上一题用到环形链表思想
假设 slow 走距离 a+b ,fast走距离 a+n(b+c)
因为二倍,2(a+b) = a+n(b+c)+b,求a
a = n(b+c)-b = (n-1)(b+c)+c
所以从头走到环入口,距离为多倍的环+c,正好和slow在入口相遇
func detectCycle(head *ListNode) *ListNode {
slow,fast:=head,head
for fast!=nil{ //判断条件不是slow==fast
slow = slow.Next
if fast.Next==nil{
return nil //fast.Next为nil则不能继续进行
}
fast = fast.Next.Next
if slow==fast{
p:=head
for p!=slow{
p = p.Next
slow = slow.Next
}
return p
}
}
return nil
}