当前位置: 首页 > news >正文

刷爆leetcode第四期 0011~0015

刷爆leetcode第四期

  • 编号0011 分割链表
    • 解法一
    • 解法二
  • 编号0012 回文链表
    • 解法一
    • 解法二
  • 编号0013 双链表相交节点
  • 编号0014 环形链表
  • 编号0015 环形链表二

编号0011 分割链表

解法一

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你不需要 保留 每个分区中各节点的初始相对位置。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/partition-list-lcci

我们来看图

在这里插入图片描述
其实这个题目解释起来也简单

我们要将整个数组所有小于x的值放在x的左边
所有大于x的值放在x的右边

解决这个问题我们可以设计两个新链表

然后遍历链表 如果遍历到的元素小于x我们就将它放到创造的第一个链表当中

如果遍历到的元素大于x我们就就将它放到创造的第二个链表当中

在这里插入图片描述

我们这里提交代码

在这里插入图片描述
发现最后这里出错了

检查下 发现我们忽略了两种特殊情况

如果都大于或者都小于呢

所以我们补上后面的代码

在这里插入图片描述
加上后面这段代码之后就能过了

代码完整表示如下

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* partition(struct ListNode* head, int x)
{
    if(head==NULL)
    {
        return NULL;
    }

    struct ListNode* lesshead = NULL;
    struct ListNode* betterhead = NULL;
    struct ListNode* lesstail = NULL;
    struct ListNode* bettertail = NULL;




    struct ListNode* pos = head;
    //  pos节点指向空的时候就不进去了  注意结束条件
    while(pos)
    {
        if(pos->val<x)
        {
            if(lesshead==NULL)
            {
                lesshead=lesstail=pos;
            }
            else
            {
                // 尾插数据 注意这里其实lesstail=pos也一样
                lesstail->next=pos;
                lesstail=lesstail->next;
            }
        }
        else
        {
            if(betterhead==NULL)
            {
                betterhead=bettertail=pos;
            }
            else
            {
                //写一种不同的写法 方便大家理解
                bettertail->next = pos;
                bettertail = pos;
            }

        }
        pos=pos->next;
    }
    if(lesstail==NULL)
    {
        return betterhead;
    }
    if(bettertail==NULL)
    {
        return lesshead;
    }
    
    lesstail->next = betterhead;
    bettertail->next = NULL;
    return lesshead;
}

解法二

除了上面那一种解法之外我们还可以使用一个新的解法

利用我们学到的基础知识 头插 尾插

如果这个数小于我们规定的值就头插到新链表

如果这个数大于等于我们规定的值就尾插到新链表

画图表示如下

在这里插入图片描述

代码表示如下

struct ListNode* partition(struct ListNode* head, int x)
{
    if (head == NULL)
    {
        return NULL;
    }



    struct ListNode* newhead = NULL;
    struct ListNode* newtail = NULL;

    struct ListNode* pos = head;
    struct ListNode* next = head;


    while (next)
    {
        next = next->next;

        if (pos->val < x)
        {
            pos->next = newhead;
            newhead = pos;
            if (newtail==NULL)
            {
                newtail = newhead;
            }
        }
        else
        {
            if (newhead == NULL)
            {
                newhead = head;
                newtail = head;
                newtail->next = NULL;
            }
            else
            {
                newtail->next = pos;
                pos->next = NULL;
                newtail = pos;
            }

        }
        pos = next;
    }
    return newhead;
}

这里要注意的是 在既要头插又要尾插的问题中
第一次赋值的时候 一定要把第一个数组的next赋值给空指针

编号0012 回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

解法一

在这里插入图片描述

这里我们有很多种解法

我们先给一种时间复杂度O(N)空间复杂度O(N)的 数组法

还是直接上图

在这里插入图片描述

上代码

bool isPalindrome(struct ListNode* head)
{
    if(head==NULL)
    {
        return true;
    }
    int* num_val = (int *)malloc(sizeof(int)*100001);
    int count =0;
    struct ListNode* pos =head;

    while(pos)
    {
        num_val[count++]=pos->val;
        pos = pos->next;
    }

    int left =0;
    int right = count-1;
    while(left<right)
    {
        if(num_val[left]!=num_val[right])
        {
            return false;
        }
        left++;
        right--;
    }

    return true;
}

很简单的解法 也不需要多讲什么了

只有一点要注意的是

空链表是回文链表

解法二

这个解法就比较有难度了

但是它能够将我们的空间复杂度降低至O(1)

在这里插入图片描述
我们首先写两个函数

一个寻找中间节点

一个逆序单链表

代码表示如下

struct ListNode* Findhalf(struct ListNode* head)
{
    assert(head);
    struct ListNode* slow=head;
    struct ListNode* fast=head;

    while((fast!=NULL)&&(fast->next!=NULL))
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

struct ListNode* reversehalf(struct ListNode* half)
{
    // 这里其实补判断空指针也可以 不过大家尽量养成一个好习惯 
    if(half == NULL)
    {
        return NULL;
    }
    struct ListNode* prev =NULL;
    struct ListNode* pos =half;
    struct ListNode* next =half;


    while(pos)
    {
        next=next->next;
        pos->next = prev;
        prev = pos;
        pos =next;
    }
    return prev;
}



bool isPalindrome(struct ListNode* head)
{
    if(head==NULL)
    {
        return true;
    }
    struct ListNode* half =NULL;
    struct ListNode* halfstart =NULL;

    // 找到中间节点 
    half = Findhalf(head);
    // 翻转中间节点 
    halfstart = reversehalf(half);

    // 比较两个链表 
    struct ListNode* p1 =head;
    struct ListNode* p2 =halfstart;

    while(p1&&p2)
    {
        if(p1->val!=p2->val)
        {
            return false;
        }
        p1=p1->next;
        p2=p2->next;
    }
    return true;
}

编号0013 双链表相交节点

输入两个链表,找出它们的第一个公共节点。

在这里插入图片描述

这道题目也很简单

使用双指针法就可以轻松解决

如下图

如果它们有交点

那么它们就会在交点处相遇
在这里插入图片描述

如果它们没有交点

那么它们就会在空指针处相遇

在这里插入图片描述

代码表示如下

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{


    if(headA==NULL)
    {
        return NULL;
    }
    if(headB==NULL)
    {
        return NULL;
    }


    struct ListNode *l1 =headA;
    struct ListNode *l2 =headB;

    while(l1!=l2)
    {
        l1=l1==NULL?headB:l1->next;
        l2=l2==NULL?headA:l2->next;
    }
    return l2;
}

编号0014 环形链表

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/linked-list-cycle

还是先上图

在这里插入图片描述
我们先来看有环的情况

这个时候实际上fast和slow会在里面陷入死循环

我们把这个图再抽象下

在这里插入图片描述
实际上就是一个这样子的图形

大家有没有表示眼熟?

这不就是我们的操场吗

那么我们把问题变一下

两个人跑步 一个跑的比较快 一个跑的比较慢

如果在一个直线的操场上它们会相遇嘛?

显然不会

但是如果在一个环形的操场上呢?

那必然会啊

那么我们接着来看

在这里插入图片描述

所以说这里就论证了当fast=2 slow=1时

它们在某个节点相遇的必然性

所以这个时候我们就可以上手写代码了

代码表示如下

bool hasCycle(struct ListNode *head) 
{
    if(head==NULL || head->next == NULL)
    {
        return NULL;
    }


    struct ListNode * fast = head->next;
    struct ListNode * slow = head;
    while(fast!=NULL && fast->next!=NULL)
    {
        if(slow==fast)
        {
            return true;
        }
        else
        {
            slow = slow->next;
            fast = fast->next->next;
        }

    }
    return false;
    
}

编号0015 环形链表二

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/linked-list-cycle-ii

这一题跟上一题一样
在这里插入图片描述
这样子就证明了

一个slow指针从起点开始走

一个slow指针从遇见的点开始走

它们会在环的起点相遇

代码表示如下

struct ListNode *detectCycle(struct ListNode *head) 
{
    if(head==NULL || head->next==NULL)
    {
        return NULL;
    }


    struct ListNode *slow =head;
    struct ListNode *fast =head;
     struct ListNode *cur =head;
    struct ListNode *pos  =NULL;
    struct ListNode *meet  =NULL;
    while(fast!=NULL&&fast->next!=NULL)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(fast==slow)
        {
            meet = fast;
            while(meet!=cur)
            {
                cur=cur->next;
                meet=meet->next;
            }
            pos = meet;
            return pos;


        }

    }
    return NULL;

    
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 二次型和矩阵正定的意义
  • Springboot整合RabbitMQ
  • 量化投资交易接口究竟能否取缔手工交易?
  • didChangeDependencies什么时候被调用
  • 【测试面试】2022年软件测试面试题大全(精品带回答的)
  • Java --- JVM年轻代与老年代
  • 制作地图的布局、元素和设计介绍
  • C/C++面试准备——运算符
  • 【华为机考】ACM输入输出(中等+)
  • 美团四年,字节三年这七年测试之路希望能让正在迷茫的你少走弯路
  • Vue 基础
  • Ts/Typescript基础运用
  • 嵌入注意力机制的多尺度深度可分离表情识别--2021.宋玉琴
  • 页面登录功能的思路
  • ShardingSphere 5.2.0:分片审计功能拦截多分片场景下的不合理请求
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • Angular数据绑定机制
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • Invalidate和postInvalidate的区别
  • Js基础知识(一) - 变量
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • Vue.js-Day01
  • Vue2.0 实现互斥
  • vuex 学习笔记 01
  • Wamp集成环境 添加PHP的新版本
  • 利用jquery编写加法运算验证码
  • 排序算法学习笔记
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 入门到放弃node系列之Hello Word篇
  • 使用 QuickBI 搭建酷炫可视化分析
  • 移动端唤起键盘时取消position:fixed定位
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​1:1公有云能力整体输出,腾讯云“七剑”下云端
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • #etcd#安装时出错
  • (¥1011)-(一千零一拾一元整)输出
  • (07)Hive——窗口函数详解
  • (2020)Java后端开发----(面试题和笔试题)
  • (30)数组元素和与数字和的绝对差
  • (4)事件处理——(7)简单事件(Simple events)
  • (C++17) optional的使用
  • (libusb) usb口自动刷新
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (ZT)出版业改革:该死的死,该生的生
  • (多级缓存)多级缓存
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (论文阅读40-45)图像描述1
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (一)appium-desktop定位元素原理
  • (一)模式识别——基于SVM的道路分割实验(附资源)
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法