代码随想录算法训练营第四天| LC24. 两两交换链表中的节点、LC19. 删除链表的倒数第N个节点、LC160. 相交链表、LC142. 环形链表II、链表章节总结

LeetCode 24 两两交换链表中的节点

题目链接:24. 两两交换链表中的节点

做题情况:当时做的时候不知道突然就想到了双指针(可能最近做双指针的题目多自然就往那方面想了),实际上本题目没必要用双指针啊,只要一个指针去遍历就行了,下面是自己用两个指针去做的,虽然最后ac出了,但是代码很冗余和最初写的时候思路有点混乱,一个指针可以做的事情偏偏自己用了两个,当时具体ac代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyhead=new ListNode(0);
        dummyhead->next=head;
        ListNode* pre=dummyhead;
        ListNode* cur=dummyhead->next;
        while(cur!=nullptr&&cur->next!=nullptr){
            ListNode* temp=cur->next;
            cur->next=cur->next->next;
            // ListNode* temp=cur->next;
            temp->next=cur;
            pre->next=temp;
            pre=pre->next->next;
            cur=cur->next;
        }
        head = dummyhead->next;
        delete dummyhead;
        return head;
    }
};

下面才是看起来思路清晰且代码简洁的ac代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyhead=new ListNode(0);
        dummyhead->next=head;
        ListNode* cur=dummyhead;
        while(cur->next!=nullptr&&cur->next->next!=nullptr){
            ListNode*temp1=cur->next;
            ListNode*temp2=cur->next->next->next;
            cur->next=cur->next->next;
            cur->next->next=temp1;
            temp1->next=temp2;
            cur=cur->next->next;
        }
        head = dummyhead->next;
        delete dummyhead;
        return head;
    }
};

LeetCode 19 删除链表的倒数第N个节点

题目链接:19. 删除链表的倒数第N个节点

做题情况:这题目才是用双指针呢,结合实例图形一下子ac出来了,注意使用虚拟头节点的好处和删除链表节点找所删除节点的前一个节点即可,下面是自己具体ac代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
 //结合实例图形才能更好写出没有错误的代码
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
       ListNode* dummyhead=new ListNode(0);
        dummyhead->next=head;
        ListNode* fast=head;//此处相当于n多加了1
        ListNode* low=dummyhead;
        while(n--){
            fast=fast->next;
        }
        while(fast!=nullptr){
            low=low->next;
            fast=fast->next;
        }
        ListNode* temp=low->next;
        low->next=low->next->next;
        delete temp;
        head = dummyhead->next;
        delete dummyhead;
        return head;
    }
};

LeetCode 160 相交链表

题目链接:160. 相交链表

做题情况:自己当时独立做题目的时候,犯了两个错误导致没ac出来:①统计完总数后要重新指向头节点,不然就会出现空指针异常 ②指针相等而不是值相等,所以像cur_A->val恒等于cur_B->val&&cur_A->next恒等于cur_B->next或者只有cur_A->val恒等于cur_B->val就是有问题的,而是cur_A恒等于cur_B,自己具体犯的错误以及ac代码见下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* cur_A=headA;
        int sum_A=0;
        while(cur_A!=nullptr){
            sum_A +=1;
            cur_A=cur_A->next;
        }
        ListNode* cur_B=headB;
        int sum_B=0;
        while(cur_B!=nullptr){
            sum_B +=1;
            cur_B=cur_B->next;
        }
        int n=sum_A>sum_B?(sum_A-sum_B):(sum_B-sum_A);
        //此处要记得重新赋值,不然会空指针异常
        cur_A=headA;
        cur_B=headB;
        if(sum_A>sum_B){
            while(n--){
                cur_A=cur_A->next;
            }
        }else{
            while(n--){
                cur_B=cur_B->next;
            }
        }
        while(cur_A!=nullptr&&cur_B!=nullptr){
            if(cur_A==cur_B){//此处的写法很重要,是指针相等而不是值相等,像cur_A->val==cur_B->val&&cur_A->next==cur_B->next或者只有cur_A->val==cur_B->val就是有问题的
                return cur_A;
            }
            cur_A=cur_A->next;
            cur_B=cur_B->next;
        }
        return nullptr;
    }
};

LeetCode 142 环形链表II

题目链接:142. 环形链表II

做题情况:拿到题目后当时又想到双指针,但是想了一会儿不会做,看完卡哥视频和代码随想录书相关部分后,整理思路如下:
①咋样判断是否有环,用双指针法
②环判断出来后看咋样找环的入口,通过一些数学推导进行找出来,最后是从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是环形入口的节点。
具体ac代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* slow=head;
        ListNode* fast=head;
        while(fast!=nullptr&&fast->next!=nullptr){
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow){
                ListNode* index1=fast;
                ListNode* index2=head;
                while(index1!=index2){
                    index1=index1->next;
                    index2=index2->next;
                }
                return index1;
            }
        }
        return nullptr;
    }
};

链表章节总结

具体知识点总结见卡哥总结,自己主要分享一些自己做题心得:① 双指针方法时刻牢记在自己心中。② 做链表题目时候结合实例图形进行编程能达到事倍功半的效果,千万别空在脑子里面想,很容易出错,这在while循环的判断条件写法和循环里面的写法很有用,可以避免很多无限循环和空指针异常错误

今天自己独立做所给题目花了一个半小时(这也是每天特地给自己留的时间),ac出第二道,第一道和第三道没ac出来,但是看完知识点后代码bug找到了和ac了,第四题不会做,所有做下来以及写博客共花了四个小时左右

贵在坚持,加油,共勉

你可能感兴趣的:(代码随想录算法训练营,算法,leetcode,数据结构)