前言
还是静不下来,浮躁,总是受外界影响。。。
内容
一、相交链表
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
intersectVal
- 相交的起始节点的值。如果不存在相交节点,这一值为0
listA
- 第一个链表listB
- 第二个链表skipA
- 在listA
中(从头节点开始)跳到交叉节点的节点数skipB
- 在listB
中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA
和 headB
传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。
快慢指针
注意curA和headA,使用不当会出错误
func getIntersectionNode(headA, headB *ListNode) *ListNode {
countA,countB:=0,0
curA:=headA
curB:=headB
//原因是在循环中更新headA和headB的值时,它们被更新为nil,导致循环提前结束。而在后面的代码中,尝试访问headA和headB的值,这会导致空指针错误
for ;curA!=nil;curA=curA.Next{//curA不能为headA
countA++
}
for ;curB!=nil;curB=curB.Next{
countB++
}
var fast,slow *ListNode
var step int
if countA>countB{
step=countA-countB
fast=headA//同样的 此时也不能为curA
slow=headB
}else{
step=countB-countA
fast=headB
slow=headA
}
for i:=0; i < step; i++ {
fast = fast.Next //不然 这里会出错
}
for fast!=slow{
fast=fast.Next
slow=slow.Next
}
return fast
}
双指针
双指针 好神奇 pA遍历完headA去headB pB遍历完headB去headA 两指针相遇 返回相遇时的结点即为相交结点
时间复杂度:O(m+n) 空间复杂度:O(1)
func getIntersectionNode(headA, headB *ListNode) *ListNode {
if headA==nil||headB==nil{
return nil
}
pA,pB:=headA,headB
for pA!=pB{
if pA!=nil{
pA=pA.Next
}else{
pA=headB//headB不是pB
}
if pB!=nil{
pB=pB.Next
}else{
pB=headA
}
}
return pA
}
哈希表
哈希表 确实没想到
//时间复杂度:O(m+n)
//空间复杂度:O(m),其中 m是链表 headA的长度。需要使用哈希集合存储链表 headA中的全部节点。
func getIntersectionNode(headA, headB *ListNode) *ListNode {
arr:=map[*ListNode]bool{}
for temp:=headA;temp!=nil;temp=temp.Next{
arr[temp]=true
}
for temp:=headB;temp!=nil;temp=temp.Next{
if arr[temp]{
return temp
}
}
return nil
}
二、环形链表
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
哈希表
同题141 哈希表存储访问过的结点,再次访问到的结点即为入环的第一个节点
func detectCycle(head *ListNode) *ListNode {
hashTable:=map[*ListNode]struct{}{}
for head!=nil{
if _,ok:=hashTable[head];ok{
return head
}
hashTable[head]=struct{}{}
head=head.Next
}
return nil
}
快慢指针
空间复杂度:O(1) 我们只使用了 slow,fast,ptr 三个指针
func detectCycle(head *ListNode) *ListNode {
fast,slow:=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
}
三、旋转链表
给你一个链表的头节点 head
,旋转链表,将链表每个节点向右移动 k
个位置。
思路:闭合为环
func rotateRight(head *ListNode, k int) *ListNode {
if head==nil||head.Next==nil||k==0{
return head
}
count:=0
cur:=head
for cur.Next!=nil{
count++
cur=cur.Next
}
// 因为上面判断的是当前节点的下一个节点何时为nil,也即是少计算了一个尾结点,所以count++
count++
cur.Next=head// 将尾巴指向头部
cur=head// 重新指向头部
k=k%count
for i:=1;i<count-k;i++{
cur=cur.Next
}
result:=cur.Next//result 就是新的头节点
cur.Next=nil//将 cur.Next 设为 nil,断开原本的连接
return result
}
最后
应该要结束链表了,明天写个总结。