代码随想录第四天

题目一

. - 力扣(LeetCode)

看到题目的第一想法:

1、需要交换,那必然要想到用临时节点作为交换存储

2、有奇、偶差别, 必然会有终止条件的不同

整理了一下流程,没想到特别好的方法,直接看了题解

看了代码随想录的想法:

有几个点得到了验证,需要注意的是:

1、题目有提到,返回头节点,感觉也是暗示用虚拟头节点

2、需要注意current和虚拟头节点,是直接=head,还是=head->next,老是会混乱

3、以后只认虚拟头节点的套路

实现时的困难:

调整了好几次,主要是:

1、缓存哪个节点

2、缓存节点后的交换顺序是怎样的

总的来说,缓存,交换顺序这些都是比较常见的,感觉这一块有点生疏,绝对需要记一个模版.

ListNode* swapPairs(ListNode* head) {
    ListNode* dynamic = new ListNode(0);
    dynamic->next = head;
    ListNode* cur = dynamic;
    while(cur->next!=nullptr && cur->next->next!=nullptr){
        ListNode* temp = cur->next;//会把链表关系一并赋予
        cur->next = cur->next->next;
        temp->next = cur->next->next;
        cur->next->next = temp;
        cur = cur->next->next;
    }
    return dynamic->next;//注意要返回头节点才能是一个完整的链表呀,而且这里这也验证了虚拟头节点的好处..
}

题目二

. - 力扣(LeetCode)

看到题目的第一想法:

思路是先把链表反转,然后从head一路next直到找到n,在n-1时使得该节点等于current,然后再用常规的删除next节点的方法.但是题目有问到能不能只扫描一次?

看了代码随想录的想法:

        啊soory,没有想到经典的双指针,肯定是数组刷完没有好好总结5555..也没有对经典解法和经典套路做总结5555....

1、使用虚拟头节点,不需要判断头节点,达到统一操作

2、快慢指针实际是形成一个窗口,倒数第n个与最后一个的差额是n,快慢指针一起形成差额n,也能达到这个效果 //todo 总结一下碰到过多少快慢指针的

3、删除必须要令指针指向被删除指针的前一个节点;

实现时的困难:

        1、快慢指针的定义(用ListNode还是?)

                答:ListNode...

        2、注意while的结束条件(虽然说我经常还会debug一下看看对不对)

        3、虚拟节点定义完不要老漏了next=head呢;

题目三

. - 力扣(LeetCode) 

看到题目的第一想法:

奇怪的题....... 直接被这例子误导了

能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?

看了代码随想录的想法:

有点像变种的快慢指针,针对的不同对象,为什么又没有想到...

实现时的困难:

1、注意这里要自己求长度

2、由哪个列表先next.可以简洁一些

if (n > m) { //这里会有更好的办法吗
        /***  强行让A保持是最长的
         * // 让curA为最长链表的头,lenA为其长度
        if (lenB > lenA) {
            swap (lenA, lenB);
            swap (curA, curB);
        }
         */
        diff = n - m;
        curA = headA;
        while(diff-- !=0){
            curA = curA->next;
        }
    } else {
        diff = m - n;
        curB = headB;
        while(diff-- !=0){
            curB = curB->next;
        }
    }

3、指向相同?

        这道题应该是有点奇怪的,看了一下代码随想录,只提到不是比较值相同,而是指向相同,再看了一下评论区,对指向相同有了更多的理解.

下面这个图的情况不会有,这个图搞得我一直在想,如果前面相交了,后面又分叉了,该怎么办?

但实际这样想就又回到“题目要求的是指向相同,而不是值相同”的误区.

更简洁的解法:

如何检测相交

要检测两个单链表是否相交,通常使用的方法是使用两个指针分别从两个链表的头节点开始遍历。当一个指针到达链表末尾时,让它跳到另一个链表的头节点继续遍历。如果两个链表相交,那么这两个指针最终会相遇在同一节点上;如果不相交,那么它们永远不会指向相同的内存地址。

一旦某个节点相同,那么后面的链表部分也必然相同,如下面,这个如果head链表和headB中3开始相同,那next..... next->next->next... 这一坨都是一样的,所以不会出现后面又开始分叉的情况

// Create a linked list: 1 -> 2 -> 3 -> 4 -> 5
    ListNode *head = new ListNode(1);
    head->next = new ListNode(2);
    head->next->next = new ListNode(3);
    head->next->next->next = new ListNode(4);
    head->next->next->next->next = new ListNode(5);

    ListNode *headB = new ListNode(6);
    headB->next = new ListNode(7);
    headB->next->next = new ListNode(3);
    headB->next->next->next = new ListNode(4);
    headB->next->next->next->next = new ListNode(5);

贴个通义千问回答

更简洁的解法:

如何检测相交

要检测两个单链表是否相交,通常使用的方法是使用两个指针分别从两个链表的头节点开始遍历。当一个指针到达链表末尾时,让它跳到另一个链表的头节点继续遍历。如果两个链表相交,那么这两个指针最终会相遇在同一节点上;如果不相交,那么它们永远不会指向相同的内存地址。

#include <iostream>

// Definition for singly-linked list.
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(nullptr) {}
};

// Function to detect intersection point in two linked lists.
ListNode* getIntersectionNode(ListNode *headA, ListNode *headB) {
    ListNode *pA = headA, *pB = headB;

    while (pA != pB) {
        pA = pA != nullptr ? pA->next : headB;
        pB = pB != nullptr ? pB->next : headA;
    }
    return pA;
}

// Function to print the linked list
void printList(ListNode* head) {
    while (head != nullptr) {
        std::cout << head->val << " ";
        head = head->next;
    }
    std::cout << std::endl;
}

int main() {
    // Create two linked lists: A and B
    ListNode* A = new ListNode(1);
    A->next = new ListNode(2);
    A->next->next = new ListNode(3);

    ListNode* B = new ListNode(4);
    B->next = new ListNode(5);

    // Create common part
    ListNode* common = new ListNode(6);
    A->next->next->next = common;
    B->next->next = common;
    common->next = new ListNode(7);

    // Detect intersection point
    ListNode* intersection = getIntersectionNode(A, B);
    if (intersection != nullptr) {
        std::cout << "Intersection at node with value: " << intersection->val << std::endl;
    } else {
        std::cout << "No intersection." << std::endl;
    }

    // Clean up the memory
    ListNode* temp;
    while (A != nullptr) {
        temp = A;
        A = A->next;
        delete temp;
    }
    while (B != nullptr) {
        temp = B;
        B = B->next;
        delete temp;
    }
    while (common != nullptr) {
        temp = common;
        common = common->next;
        delete temp;
    }

    return 0;
}

题目四

. - 力扣(LeetCode)

看到题目的第一想法:

        成环其实不存在必要条件.

        看到这种存在前后差距的,马上能想到快慢指针,快慢指针精髓在于快多少步// todo 之前碰到的题目是怎么讲来着,总结总结....

        只能想到快一整个链表?

        定义快慢指针,每次都让快指针比慢指针快一步,然后让快指针循环到最后,判断一下快指针的next是否是等于慢指针所在的节点.       

看了代码随想录的想法:

        初步看了一下思路,很确定以前见过这个题,但我就是忘了..... - -

        细节还挺多的,总的来说就是让快指针先走一步//总结一下碰到的快慢指针

实现时的困难:

        1、这道题比较经典,而我只能把思路背下来了

       

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值