双指针技巧秒杀七道链表题目 :: labuladong的算法小抄 #982
Replies: 178 comments 38 replies
-
刚开始写相交链表,写的很多判断条件,最后去理解了一下,还是切换的逻辑上,没想到被绊倒了 |
Beta Was this translation helpful? Give feedback.
-
大佬,最后一个判断交叉的,当没有交叉时,是不是只要判断p1,p2都已经发生过一次交换后,再出现了需要交换的时候,就可以直接退出了。 func getIntersectionNode(a,b *LinkNode) *LinkNode {
if a == nil || b == nil{
return nil
}
p1, p2 := a, b
tag, tag2 := false, false
for p1.val != p2.val {
if p1.next == nil {
if tag && tag2 {
return nil // 无交叉
}
p1 = b
tag = true
} else {
p1 = p1.next
}
if p2.next == nil {
if tag && tag2 {
return nil // 无交叉
}
p2 = a
tag2 = true
} else {
p2 = p2.next
}
}
return p1 // 返回p1或者p2都可
} |
Beta Was this translation helpful? Give feedback.
-
相交链表的这个技巧太牛了 |
Beta Was this translation helpful? Give feedback.
-
讲的真的很不错,我现在能够解答一些类似题目了。。。很开心。谢谢大佬。 |
Beta Was this translation helpful? Give feedback.
-
相交链表,大佬这个思路确实巧妙,我想了一个复杂度一样的算法但是更好理解。分别统计两条链表的长度,差值表示非公共部分的长度差,那么让长链表的指针先走差值的步数,再齐头并进,那么如果两个指针相等则是相交的位置。 public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p = headA, q = headB;
int l1=0, l2=0;
while(p.next!=null){ // 统计A链表长度
p=p.next;
l1++;
}
while(q.next!=null){// 统计B链表长度
q=q.next;
l2++;
}
p = headA;
q = headB;
if(l2>=l1){
for(int i=0;i<l2-l1;i++){
q=q.next;
}
}else{
for(int i=0;i<l1-l2;i++){
p=p.next;
}
}
while(p!=null&&q!=null){
if(p==q){ // 相等说明相交。
return q;
}
p=p.next;
q=q.next;
}
return null;
} |
Beta Was this translation helpful? Give feedback.
-
@Clarence-G 这个解法也不错!最后一个 public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = 0, lenB = 0;
// 计算两条链表的长度
for (ListNode p = headA; p != null; p = p.next) {
lenA++;
}
for (ListNode q = headB; q != null; q = q.next) {
lenB++;
}
// 让 p 和 q 到达尾部的距离相同
ListNode p = headA, q = headB;
if (lenA > lenB) {
for (int i = 0; i < lenA - lenB; i++) {
p = p.next;
}
} else {
for (int i = 0; i < lenB - lenA; i++) {
q = q.next;
}
}
// 看两个指针是否会相同,p == q 时有两种情况:
// 1、要么是两条链表不相交,他俩同时走到尾部空指针
// 2、要么是两条链表相交,他俩走到两条链表的相交点
while (p != q) {
p = p.next;
q = q.next;
}
return p;
} |
Beta Was this translation helpful? Give feedback.
-
@labuladong |
Beta Was this translation helpful? Give feedback.
-
相交链表,大佬的思路真是清奇,撸完之后爽呆了! |
Beta Was this translation helpful? Give feedback.
-
有个疑惑,我想请问下 相交链表的那个如果是这种呢 链表A->B->C->D 和链表F->G->C->H->I呢 也就是相交元素只有C元素,后面的并不是两个链表的公共部分,这样的话用逻辑拼接应该不可行了吧? |
Beta Was this translation helpful? Give feedback.
-
相交链表有点问题,如果题目是要求找2个链表的第一个相交点,这种解法才是最优吧;如果只要判断是否相交,感觉可以两个链表分别遍历到头,比较最后一个指针相等就可以了 |
Beta Was this translation helpful? Give feedback.
-
最后一道找交点的题,可以不用算出哪个链表的长短,也不用跳到其他链表。 <T> ListGenericNode<T> getIntersectionNode(ListGenericNode<T> headA, ListGenericNode<T> headB) {
ListGenericNode<T> shortHead = headA;
ListGenericNode<T> longHead = headB;
if (headA == null || headB == null) {
return null;// 没有相交点
}
while (shortHead.next != null && longHead.next != null) {
shortHead = shortHead.next;
longHead = longHead.next;
}
ListGenericNode<T> pNodeA = headA, pNodeB = headB;
// 如果 shortHead 链表更长,则 pNodeA 开始迭代
while (shortHead.next != null) {
pNodeA = pNodeA.next;
shortHead = shortHead.next;
}
// 如果 longHead 更长,则 pNodeB 开始迭代
while (longHead.next != null) {
longHead = longHead.next;
pNodeB = pNodeB.next;
}
// headA is done by shortHeadA point,now start to visit headB
// and the same as headB if listB is longer than listA
// 此时 同时 pNodeA 和 pNodeB 开始同时迭代,如果有相交点则如果相加则一定会相交
while (pNodeA != pNodeB && pNodeA != null) {
pNodeA = pNodeA.next;
pNodeB = pNodeB.next;
}
return pNodeA;
} |
Beta Was this translation helpful? Give feedback.
-
我首先想到的也是先计算两个链表的长度,然后再遍历 |
Beta Was this translation helpful? Give feedback.
-
虽然也看懂了,但是感觉技巧性还是比较强,能不能总结一些规律、框架啊 |
Beta Was this translation helpful? Give feedback.
-
142. 环形链表 II这题JS用上面的例子解没有做好边界判断,
|
Beta Was this translation helpful? Give feedback.
-
两个链表是否相交东哥的代码执行
东哥写法的特点指针走完一个链表后,不是马上就跳到另一个链表的头结点,而是先经过一个null节点 东哥写法的优点即使两个链表不相交,两个指针最后都必为null,既两个指针相等 |
Beta Was this translation helpful? Give feedback.
-
求倒数第K个节点的那个题,使用遍历一遍然后在走l-k个节点的方法复杂度和本文中的方法是一样的,都是两个节点总共走了2l-k步。 |
Beta Was this translation helpful? Give feedback.
-
这是来自QQ邮箱的假期自动回复邮件。
您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。
|
Beta Was this translation helpful? Give feedback.
-
86题分割链表,不需要每次都让链表的next置空,只需要最后添加 func partition(head *ListNode, x int) *ListNode {
// 分成两个链表,提取出小于x的链表
// less
dummy1 := &ListNode{-1, nil}
// greater
dummy2 := &ListNode{-1, nil}
p1, p2 := dummy1, dummy2
p := head
for p != nil {
if p.Val < x {
p1.Next = p
p1 = p1.Next
} else {
p2.Next = p
p2 = p2.Next
}
// 可以不需要
// temp := p.Next
// p.Next = nil
// p = temp
p = p.Next
}
p1.Next = dummy2.Next
// 出现环的原因在于最后一个节点的指针没有重新分配,可能非空
p2.Next = nil
return dummy1.Next
} |
Beta Was this translation helpful? Give feedback.
-
第86题可以避免成环
|
Beta Was this translation helpful? Give feedback.
-
打卡,学到了优先级队列的应用👍 |
Beta Was this translation helpful? Give feedback.
-
文章链接点这里:双指针技巧秒杀七道链表题目
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions