代码随想录训练营第38期Day4

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

今天是第四天跟着代码随想录刷题,其实今天是周末才写的周六的博客,因为之前留了一些内容没有做完,今天把这周遗留的问题成功的解决了,主要学了以下内容,首先是数组的螺旋矩阵的内容,然后是链表的内容,包括24.两两交换链表中的节点、19.删除链表的数第N个节点、面试题 02.07. 链表相交和142.环形链表II ,内容还是比较多,花了两天的时间认真地写下了每一个代码。

链接地址:螺旋矩阵II24.两两交换链表中的节点19.删除链表的倒数第N个节点面试题 02.07. 链表相交142.环形链表II


一、螺旋矩阵II

注意:主要是有两个点,一个是确定循环的次数,一个是奇数偶数需不需要补中间点的问题。
思路:默认左闭右开,大循环内套四个小循环的赋值过程,按照顺时针,上右下左的方向来写代码。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
        int count = 1; // 用来给矩阵中每一个空格赋值
        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
        int i,j;
        while (loop --) {
            i = startx;
            j = starty;

            // 下面开始的四个for就是模拟转了一圈
            // 模拟填充上行从左到右(左闭右开)
            for (j; j < n - offset; j++) {
                res[i][j] = count++;
            }
            // 模拟填充右列从上到下(左闭右开)
            for (i; i < n - offset; i++) {
                res[i][j] = count++;
            }
            // 模拟填充下行从右到左(左闭右开)
            for (; j > starty; j--) {
                res[i][j] = count++;
            }
            // 模拟填充左列从下到上(左闭右开)
            for (; i > startx; i--) {
                res[i][j] = count++;
            }

            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
            startx++;
            starty++;

            // offset 控制每一圈里每一条边遍历的长度
            offset += 1;
        }

        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
        if (n % 2) {
            res[mid][mid] = count;
        }
        return res;

二、两两交换链表中的节点

思路:首先还是需要Hummyhead(记作节点0),假设需要交换节点1和节点2,那么需要让0的下一位指向2,让2的下一位指向1,让1的下一位指向3,但是让0的下一位指向2以后,1就断了,然后2指向1的时候,3也断了,所以还需要设立两个指针,指针1和指针3单独拎出来先设一个是temp和temp1这样之后就比较方便指向1和3,还需要知道我想要操控1和2换位置,我需要把指针位置放到0这个位置才行,所以一次循环结束,cur需要移动两次,方便操控下两个元素。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
    ListNode* Hummyhead=new ListNode(0);
    Hummyhead->next=head;
    ListNode* cur=Hummyhead;
    while(cur->next!=NULL&&cur->next->next!=NULL)
    {
        ListNode* temp=cur->next;
        ListNode* temp1=temp->next->next;
        cur->next=cur->next->next;
        cur->next->next=temp;
        temp->next=temp1;
        cur=cur->next->next;

    }
    return Hummyhead->next;

    }
};

在代码中需要注意的是cur->next!=NULL&&cur->next->next!=NULL这两个顺序不能错,因为如果整个是偶数的话,最后的指针指向了最后一个,他的next就是null,如果先判断他的next的next就会出现报错,所以先判断cur的next不为null。
牢记创立一个虚拟头节点的代码:

ListNode* Hummyhead=new ListNode(0); Hummyhead->next=head;

创立一个指针指向某个位置的代码:

ListNode* temp=cur->next;

三、删除链表的数第N个节点

思路:笨方法,先得到整个列表的长度,然后计算一开始的指针需要指到哪个位置,然后用常规方法删除指针就好了。
(代码随想录里用的聪明方法,二刷再来自己写)

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
    ListNode* Hummyhead=new ListNode(0);
    Hummyhead->next=head;
    ListNode* cur=Hummyhead->next;
    int a=0;
    while(cur!=NULL)
    {
        a++;
        cur=cur->next;
    }
    ListNode* cur1=Hummyhead;
    int b=a-n;
    while(b!=0)
    {
        b--;
        cur1=cur1->next;
    }
    ListNode* cur2=cur1->next;
    cur1->next=cur1->next->next;
    delete cur2;
    return Hummyhead->next;
    }
};

四、链表相交

思路:链表相交的意思就是,两个链表在某个位置以后的地址都是完全一样了,是地址一样,不是里面的内容一样。这道题的思路了主要就是根据知道两个链表的长度把两个链表“并排放到一起,尾巴是挨着的”,这样让指针从短链表的头开始,长链表的中间某个位置开始,两个指针一起跑(保证跑到最后一一对应),看到从哪里开始一样就行了。
在这里插入图片描述

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    ListNode *hummyheada=new ListNode(0);
    ListNode *hummyheadb=new ListNode(0);
    hummyheada->next=headA;
    hummyheadb->next=headB;
    ListNode *len=headA;
    int a=0;
    while(len!=NULL)
    {
        a++;
        len=len->next;
    }
    int b=0;
    len=headB;
    while(len!=NULL)
    {
        b++;
        len=len->next;
    }
    ListNode *cura=headA;
    ListNode *curb=headB;
    int c=std::abs(b-a);
    if(a>=b)
    {
        while(c!=0)
       {
           c--;
           cura=cura->next; }  
    }
    else
    {  
        while(c!=0)
       {
           c--;
           curb=curb->next;
       }
    }
    while(cura!=curb&&cura!=NULL)
    {
        cura=cura->next;
        curb=curb->next;
    }
    return cura;


    }   
    };

五、环形链表II

思路:这道题代码很简单,就是要理解题目的意思和想出解决的方法。
在这里插入图片描述
设立两个指针,一个快指针,一个慢指针,快指针,先看有没有环,快指针不会跑到NULL就说明有环,然后看怎么找入口。
快指针速度为2慢指针速度为1,两个一定会在环上相遇,重点关注相遇的位置的那个点。
在这里插入图片描述
先列相遇方程:2*(x+y)=x+n*(y+z)+y
得出:x=(n-1)*(y+z)+z
这是不是可以表明,我找两个指针一个在起点,一个在相遇的位置,两个一起跑,相遇点一定在入口节点,因为这两个的距离是一样的,一个是从头节点到环形入口节点,一个是从相遇点,跑不知道多少圈,但是加一个z就是会跑到入口节点停住,这样就相遇了。所以思路很明显,一个快指针一个慢指针,找到相遇的点,然后再找两个指针,一个在起点,一个在相遇点跑,这样相遇的节点就是环入口的节点。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
    ListNode *fast=head;
    ListNode *slow=head;
    while(fast->next!=NULL&&fast->next->next!=NULL)  
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            ListNode *temp=fast;
            ListNode *begin=head;
            while(begin!=temp) 
                {
                    begin=begin->next;
                    temp=temp->next;
                }
            return begin;
        }

    }
    return NULL;
    

    }
};

总结

跟着代码随想录第一周的刷题结束了,终于是在星期日的晚上十一点完成了这周所有的任务,还是比较有成就感的,但是我觉得做的不好的地方在于我可能一天大部分的时间都在做这个,没有时间做其他事了,效率有待提高,下周希望能在不耽误刷题的过程中,还能做一下项目的内容,或者刷一刷数据结构的课程,就更好了,期待下周的总结看自己有没有做到!下周是520,女朋友要过来,可能还会耽误一两天的刷题进度,希望自己以后能补回来吧!

  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值