双指针技巧秒杀七道链表题目 :: labuladong的算法小抄 #982
Replies: 178 comments 38 replies
-
好文 |
Beta Was this translation helpful? Give feedback.
-
刚开始写相交链表,写的很多判断条件,最后去理解了一下,还是切换的逻辑上,没想到被绊倒了 |
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.
-
相交链表的这个技巧太牛了 |
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.
-
东哥,我有点飘了 |
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.
-
收到
|
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.
-
收到
|
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.
-
厉害了 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
文章链接点这里:双指针技巧秒杀七道链表题目
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions