LeetCode 1731, 151, 148

目录

  • 1731. 每位经理的下属员工数量
    • 题目链接
    • 要求
    • 知识点
    • 思路
    • 代码
  • 151. 反转字符串中的单词
    • 题目链接
    • 标签
    • 思路
    • 代码
  • 148. 排序链表
    • 题目链接
    • 标签
    • Collections.sort()
      • 思路
      • 代码
    • 归并排序
      • 思路
      • 代码

1731. 每位经理的下属员工数量

题目链接

1731. 每位经理的下属员工数量

  • Employees的字段为employee_idnamereports_toage

要求

  • 编写一个解决方案来返回需要听取汇报的所有经理的 ID、名称、直接向该经理汇报的员工人数,以及这些员工的平均年龄,其中该平均年龄需要四舍五入到最接近的整数。
  • 返回的结果集需要按照 employee_id 进行排序。

知识点

  1. round():四舍五入的函数。
  2. count():统计个数的函数。
  3. avg():求平均值的函数。
  4. group by:根据某些字段进行分组。
  5. order by:根据某些字段进行排序。

思路

可以先按经理的id report_to AS manager_id 统计(将查询结果作为一张表)出直接向该经理汇报的员工人数、平均年龄(需要四舍五入到整数位),然后再将 Employees 作为经理的表 m,与这张子表 sub 进行多表查询,限制条件为 m.employee_id == sub.manager_id,最后再根据 employee_id 进行排序即可。

代码

select
    employee_id,
    name,
    reports_count,
    average_age
from
    Employees m,
    (
        select
            reports_to manager_id,
            count(*) reports_count,
            round(avg(age), 0) average_age
        from
            Employees
        group by
            manager_id
    ) sub
where
    employee_id = manager_id
order by
    employee_id

151. 反转字符串中的单词

题目链接

151. 反转字符串中的单词

标签

双指针 字符串

思路

本题可以使用 J a v a Java Java字符串的 s p l i t ( ) split() split()方法,这个方法可以按模式字符串分割原字符串,并且会保留空字符串,比如" main".split(" ")的结果是[, main]而不是[main]

针对空串,需要遍历 s p l i t ( ) split() split()返回的数组,将长度不为0的字符串(即不是空串)加入到一个链表中(为什么使用链表?因为不知道最终非空字符串的个数),再使用 C o l l e c t i o n s . r e v e r s e ( ) Collections.reverse() Collections.reverse()方法将链表反转,最后将这个链表转为 O b j e c t [ ] Object[] Object[],这就得到了一个字符串数组,然后将这些字符串通过 S t r i n g B u i l d e r StringBuilder StringBuilder拼接得到结果。

注意, S t r i n g B u i l d e r StringBuilder StringBuilder . a p p e n d ( ) .append() .append()方法的返回值仍然是 S t r i n g B u i l d e r StringBuilder StringBuilder,也就是说 . a p p e n d ( ) .append() .append()支持链式编程,即可以将builder.append(" " + str)写作builder.append(" ").append(str)

代码

class Solution {
    public String reverseWords(String s) {
        Object[] split = split(s);
        int n = split.length;

        // 如果字符串的个数为0,则返回空串
        if (n == 0) {
            return "";
        }

        // 拼接单词和空格
        StringBuilder builder = new StringBuilder();
        builder.append(split[0]); // 上面的判断已经保证至少有一个单词,所以可以先拼接第1个单词
        for (int i = 1; i < split.length; i++) {
            builder.append(" ").append(split[i]);
        }
        return builder.toString();
    }
    // 将字符串分成单词的数组并反转
    private Object[] split(String s) {
        List<String> list = new ArrayList<>();
        for (String str : s.split(" ")) {
            if (str.length() != 0) {
            	list.add(str);
            }
        }
        Collections.reverse(list);
        return list.toArray();
    }
}

148. 排序链表

题目链接

148. 排序链表

标签

链表 双指针 分治 排序 归并排序

Collections.sort()

思路

相信看到这道题后,想到的第一个方法就是先将链表转为节点数组,然后对节点数组进行排序,最后再将节点数组转换为链表,这样做完全可以。

J a v a Java Java中,可以使用 C o l l e c t i o n s . s o r t ( ) Collections.sort() Collections.sort()方法对 L i s t List List的实现类(比如 A r r a y L i s t , L i n k e d L i s t ArrayList, LinkedList ArrayList,LinkedList)进行排序,传入 一个 L i s t List List集合 和 匿名内部类或Lambda表达式 就可以排序了。所以第一步是将链表转化为 L i s t List List集合,第二步是对 L i s t List List集合进行排序,第三步是将有序的 L i s t List List集合转化为链表返回。

代码

class Solution {
    public ListNode sortList(ListNode head) {
        // 先将链表转为java中的List
        List<ListNode> list = new ArrayList<>();
        while (head != null) {
            list.add(head);
            head = head.next;
        }

        // 对List进行排序
        Collections.sort(list, (n1, n2) -> n1.val - n2.val);

        // 将有序List转化为链表
        ListNode sentinel = new ListNode();
        ListNode curr = sentinel;
        for (ListNode node : list) {
            curr.next = node;
            curr = curr.next;
        }
        curr.next = null; // 防止成为循环链表,这一步很关键
        return sentinel.next;
    }
}

归并排序

思路

上面的办法虽然好,但出这道题的人可能不希望这样解,他希望使用 归并排序 的思想对本题进行求解。

归并排序的思想是 分治,对一个长链表进行排序,可以先把其分为很多段(直到不可再分,即只剩一个节点),然后对每段都排序,最后再合成这些有序的短链表为长链表。

对于合并两个有序链表,可以看我写的这篇文章 21. 合并两个有序链表。

可以先求出链表的长度,代码如下,其中 n 是链表的长度:

int n = 0;
for (ListNode curr = head; curr != null; curr = curr.next) {
    n++;
}

然后再进行归并排序,先从短链表的长度为0开始,每次合并完所有短链表后,将短链表的长度扩大1倍,然后再进行合并,直到短链表的长度比长链表大。

每次合并得先得到两个短链表,然后才能合成,当合并到最后两个短链表时,这两个短链表的长度可能不够这轮归并所要求的短链表长度,但无所谓,依然可以将其合并一次,除了消耗一点点时间外没有任何影响。

注意:合并完短链表后,短链表和长链表是分开的,所以需要重建它们之间的关系。

只说这些思路是远远不够的,本题的难点在于对边界值的判断,这就需要大家极其仔细了,具体看代码的注释吧。

代码

class Solution {
    public ListNode sortList(ListNode head) {
        // 如果链表为空,则返回空;如果链表只有一个节点,则不需要排序
        if (head == null || head.next == null) {
            return head;
        }

        // 先统计链表的长度
        int n = 0;
        for (ListNode curr = head; curr != null; curr = curr.next) {
            n++;
        }

        // 再进行归并排序
        ListNode sentinel = new ListNode(-1, head);
        for (int subN = 1; subN < n; subN <<= 1) { // subN是短链表的长度
        	// prev指向待合成的两个短链表的第一个短链表的头节点
            ListNode prev = sentinel, curr = sentinel.next;
            while (curr != null) {
                // 找第一个长度为subN的短链表
                ListNode list1 = curr; // list1为短链表的头节点
                // i从1开始是因为list1也算一个节点,所以只需要走subN-1步就能得到长度为subN的短链表
                for (int i = 1; i < subN && curr.next != null; i++) {
                    curr = curr.next;
                }

                // 找第二个长度为subN的短链表
                // 把curr.next赋值给list2 是因为 curr是第一个短链表的最后一个节点
                ListNode list2 = curr.next; // list2为短链表的头节点
                curr.next = null; // 将第一个短链表和第二个短链表分开
                curr = list2; // curr从第二个短链表的头节点开始
                // i从1开始是因为list1也算一个节点,所以只需要走subN-1步就能得到长度为subN的短链表
                // 由于curr从curr.next开始,不知道curr.next是否为null,所以需要加上curr != null的判断条件
                for (int i = 1; i < subN && curr != null && curr.next != null; i++) {
                    curr = curr.next;
                }

                // 处理下一个短链表
                ListNode next = null; // next是下一个长度为subN的短链表的头节点
                if (curr != null) { // 如果curr不为null,那就意味着第二个短链表的长度为subN
                    next = curr.next; // 此时把curr.next 赋值给 下一个短链表的头节点
                    curr.next = null; // 将第二个短链表和下一个短链表分开
                }

                // 合并两个有序短链表,merged是合并后链表的头节点
                ListNode merged = mergeTwoLists(list1, list2);

                // 将短链表接入长链表
                prev.next = merged;
                while (prev.next != null) { // 让prev到短链表的最后一个节点
                    prev = prev.next;
                }

                // 更新curr到下一个短链表的头节点处
                curr = next;
            }
        }
        return sentinel.next;
    }
    // 合并两个有序链表
    private ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode sentinel = new ListNode(-1); // 定义一个哨兵节点,返回它的next
        ListNode curr = sentinel;

        // 1. 先把小的节点加到哨兵节点上,直到两个链表任意一个为空
        while (list1 != null && list2 != null) {
            if (list1.val < list2.val) {
                curr.next = list1;
                list1 = list1.next;
            } else {
                curr.next = list2;
                list2 = list2.next;
            }
            curr = curr.next;
        }
        
        // 2. 如果链表1不为空,则加上它剩余的部分
        if (list1 != null) {
            curr.next = list1;
        } else { // 否则链表2不为空,加上它剩余的部分(就算链表2为空,也是加上一个null,对结果不影响)
            curr.next = list2;
        }

        // 3. 返回哨兵节点的next,因为它指向结果链表
        return sentinel.next;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/713642.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

文章解读与仿真程序复现思路——电工技术学报EI\CSCD\北大核心《计及台风时空特性和灵活性资源协同优化的配电网弹性提升策略》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

SpringBootWeb 篇-入门了解 Spring Cache 、Spring Task 与 WebSocket 框架

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Spring Cache 概述 1.1 Spring Cache 具体使用 1.1.1 引入依赖 1.1.2 Spring Cache 相关注解的介绍 2.0 Spring Task 概述 2.1 cron 表达式 2.2 Spring Task 使用…

程序猿大战Python——函数——拆包和交换变量值与引用

拆包 目标&#xff1a;了解拆包的使用。 先来看看在现实生活中的拆包。比如&#xff0c;张同学背着背包来教室上课后&#xff0c;需要从背包中拿出电脑、鼠标、数据线、电源线等&#xff0c;这个过程就是拆包! 接着&#xff0c;看一下在Python程序中的拆包&#xff1a;把组合形…

基于单片机和GP2Y1010AU粉尘传感器的空气质量检测仪设计

摘要 随着社会的发展,随着工业的发展,其给人们的生活带来很多便利。然而,工业生产过程中会产生很多对人体有害的因素,比如煤炭开采、水泥生产等行业中的粉尘污染。其在各种危害因素中对人体健康的影响最为严重。粉尘对人体的危害最直接、最严重的是引起尘肺病。当粉尘浓度过…

云原生技术实现Devops自动化运维

云原生技术实现Devops自动化运维 随着云计算和DevOps理念的普及&#xff0c;云原生技术在自动化运维中的应用日益广泛。本文将探讨云原生技术如何通过容器化、微服务架构、CI/CD流水线等手段&#xff0c;提升DevOps自动化运维的效率和灵活性&#xff0c;并通过案例分析具体应用…

Day01_Ajax入门

文章目录 学习目标一、AJAX 概念和 axios 使用1. 目标2. 讲解2.1 什么是 AJAX ?2.2 什么是服务器&#xff1f;2.3 为何学 AJAX ?2.4 怎么学 AJAX ?2.5 例子2.6 axios语法 二、认识 URL1. 目标2. 讲解2.1 为什么要认识 URL ?2.2 什么是 URL &#xff1f;2.3 URL的组成 &…

架构设计 - WEB项目的基础序列化配置

摘要&#xff1a;web项目中做好基础架构(redis&#xff0c;json)的序列化配置有重要意义 支持复杂数据结构&#xff1a;Redis 支持多种不同的数据结构&#xff0c;如字符串、哈希表、列表、集合和有序集合。在将这些数据结构存储到 Redis 中时&#xff0c;需要将其序列化为字节…

IT入门知识博客文章大纲(0/10)

IT入门知识博客文章大纲 引言 什么是IT&#xff1f; 信息技术&#xff08;Information Technology&#xff09;&#xff0c;互联网技术是指在计算机技术的基础上开发建立的一种信息技术 。互联网技术通过计算机网络的广域网使不同的设备相互连接&#xff0c;加快信息的传输速度…

【JavaEE精炼宝库】多线程(6)线程池

目录 一、线程池的概念及优势 1.1 线程池的概念&#xff1a; 1.2 线程池的优势&#xff1a; 二、工厂模式 三、标准库中的线程池 3.1 标准库线程池参数解释&#xff1a; 3.1.1 corePoolSize | maximumPoolSize&#xff1a; 3.1.2 keepAliveTime | unit&#xff1a; 3.1…

Vue50-mixin混入

一、为什么要使用 mixin混入 两个组件共享一个配置。 二、使用 mixin混入 2-1、创建一个混合js文件 2-2、引入混合js文件 1、局部混合 在每个组件中都引入混合js文件 注意&#xff1a; 混合就是复用配置&#xff0c;vm实例中的所有的配置项&#xff0c;都能在混合.js文件中写…

【计算机毕业设计】基于Springboot的毕业生实习与就业管理系统【源码+lw+部署文档】

包含论文源码的压缩包较大&#xff0c;请私信或者加我的绿色小软件获取 免责声明&#xff1a;资料部分来源于合法的互联网渠道收集和整理&#xff0c;部分自己学习积累成果&#xff0c;供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者…

新旧torch中傅里叶变换实现(fft)

由泰勒级数我们知道&#xff0c;一个函数可以被分解成无穷个幂函数叠加的形式&#xff0c;于是同样地&#xff0c;一个周期函数也可以被分解成多个周期函数叠加&#xff0c;于是自然而然地&#xff0c;三角函数符合这个需求&#xff0c;由傅里叶级数我们可以将周期函数分解成无…

Qwen2大语言模型微调、导出、部署实践

上篇文章&#xff1a; Qwen1.5大语言模型微调实践_qwen1.5 7b微调-CSDN博客 我们介绍了Qwen1.5 大语言模型使用LLaMA-Factory 来微调&#xff0c;这篇文章我们介绍一下微调后模型的导出、部署。 一、模型导出 在webui 界面训练好模型之后点击“Export”选项卡&#xff0c;然…

linux 部署瑞数6实战(维普,药监局)第一部分

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx 本文章未经许可禁止转载&…

ICML24麻省理工提出使用更少的条件独立性测试来发现因果关系新方法

【摘要】众多科学领域的核心问题围绕着理解因果关系这一基本问题。然而,大多数基于约束的因果发现算法,包括广受欢迎的PC算法,通常会进行指数级数量的条件独立性(CI)测试,在各种应用中造成局限。为解决这一问题,我们的工作重点是表征在减少CI测试数量的情况下,可以了解潜在因果…

POC EXP | woodpecker插件编写

woodpecker插件编写 目录 woodpecker介绍woodpecker使用插件编写 安装环境 woodpecker-sdkwoodpecker-request 创建Maven项目 Confluence OGNL表达式注入漏洞插件编写 创建Package包和Class类编写POC 漏洞POC代码编写导出jar包将jar包放入woodpecker的plugin目录运行woodpeck…

UML与设计模式

1、关联关系 关联关系用于描述不同类的对象之间的结构关系&#xff0c;它在一段时间内将多个类的实例连接在一起。关联关系是一种静态关系&#xff0c;通常与运行状态无关&#xff0c;而是由“常识”、“规则”、“法律”等因素决定的&#xff0c;因此关联关系是一种强关联的关…

MPC质心跟随控制(CoM Tracking Control)

MPC质心跟随 在人形机器人中,质心(CoM)的跟随控制是保持机器人稳定和协调运动的关键技术之一。模型预测控制(MPC)是一种先进的控制方法,通过解决在线优化问题来控制机器人质心的位置和速度。下面我们详细介绍如何使用MPC实现质心跟随控制。 MPC基本原理 模型预测控制是…

Iptables深入浅出

1、iptables的基本概念 众所周知iptables是Linux系统下自带免费的包过滤防火墙。其实不然&#xff0c;iptables其实不是真正的防火墙&#xff0c;我们可以把它理解成一个客户端代理&#xff0c;用户通过iptables这个代理&#xff0c;将用户的安全设定执行到对应的”安全框架”…