LeetCode 1045, 14, 25

目录

  • 1045. 买下所有产品的客户
    • 题目链接
    • 要求
    • 知识点
    • 思路
    • 代码
  • 14. 最长公共前缀
    • 题目链接
    • 标签
    • 普通版
      • 思路
      • 代码
    • 加强版
      • 思路
      • 代码
  • 25. K 个一组翻转链表
    • 题目链接
    • 标签
    • 思路
    • 代码

1045. 买下所有产品的客户

题目链接

1045. 买下所有产品的客户

  • Customer的字段为customer_idproduct_key
  • Product的字段为product_key

要求

  • 编写解决方案,报告 Customer 表中购买了 Product 表中所有产品的客户的 id。
  • 返回结果表 无顺序要求

知识点

  1. count():统计个数的函数。
  2. distinct:对某个字段进行去重。
  3. group by:根据某些字段进行分组。
  4. having:对分组后的结果进行筛选。

思路

购买了 Product 表中所有产品就是:顾客在 Customer 表中的购买记录产品种类数 = Product 表中的记录数。由于 Customer 表可能包含重复的行,所以不能统计顾客的购买记录数(即count(*)),而是要统计顾客的购买产品种类数(即count(distinct product_key)。Product 表中的记录数可以直接使用count(*)来获取,因为 product_keyProduct 表的主键(具有唯一值的列)。

代码

selectcustomer_id
fromCustomer
group bycustomer_id
havingcount(distinct product_key) = (selectcount(*)fromProduct)

14. 最长公共前缀

题目链接

14. 最长公共前缀

标签

字典树 字符串

普通版

思路

可以将第一个字符串作为 模版字符串,与字符串数组剩下的字符串进行比较。本解法是这样看待字符串数组的:将每个字符串中的所有字符从左到右排列,将所有字符串从上到下排列,即对于字符串数组strs = ["flower","flow","flight"],有以下的排列:

f l o w e r
f l o w
f l i g h t

可以想到,解题的策略是:从左到右比较每一列的字符是否相同,如果不相同,则返回模版字符串的索引为0和索引为上一列的子字符串。但是要注意一点,如果比较的列数超过了字符串的长度时,应立即返回

对于上面这个字符串数组,先比较第一列,发现都是f;然后比较第二列,发现都是l;再比较第三列,发现第三个字符串的字符i与模版字符串的字符o不同,这时返回的子字符串的右端点索引是1。

在比较的时候,我选择将模版字符串转换成char[],因为这样做比使用StringcharAt()方法快。但是我没有将所有字符串数组都转换成char[],因为这样的浪费的空间太多了。

返回子字符串时,可以使用String的一个构造方法public String(char[] s, int i, int j),其中第一个参数是字符数组,第二个参数是从这个字符数组的哪个索引开始截取,第三个参数是以这个字符数组的哪个索引作为子字符串的结束索引,这个构造方法返回的字符串的区间是[i, j)(含左不含右)。例如new String(new char[]{'h', 'e', 'l', 'l', 'o'}, 1, 3)返回的字符串是"el"

代码

class Solution {public String longestCommonPrefix(String[] strs) {char[] s1 = strs[0].toCharArray(); // 将第一个字符串转换成字符数组for (int i = 0; i < s1.length; i++) { // i是列数for (int j = 1; j < strs.length; j++) { // j是字符串的索引,从1开始,避免让第一个字符串自己和自己比较// 当i >= strs[j].length()时,意味着这个字符串的长度不够了,该返回了// 当s1[i] != strs[j].charAt(i)时,意味着公共前缀不包含索引为i的字符,直接返回if (i >= strs[j].length() || s1[i] != strs[j].charAt(i)) {return new String(s1, 0, i);}}}// 遍历完第一个字符串后,直接返回第一个字符串即可,第一个字符串就是公共前缀return strs[0];}
}

加强版

思路

对于“多个”这种字眼,我们可以采用 分治 的思路:每次都获取 左半区间 和 右半区间 内所有字符串的公共前缀,然后再求这两个公共前缀的公共前缀。直到区间只剩下一个字符串。

代码

class Solution {public String longestCommonPrefix(String[] strs) {return merge(strs, 0, strs.length - 1);}// 使用分治的思想求区间内的公共前缀private String merge(String[] strs, int i, int j) {if (i == j) {return strs[i];}int mid = i + j >> 1;String pre1 = merge(strs, i, mid); // 获取左半区间内所有字符串的公共前缀String pre2 = merge(strs, mid + 1, j); // 获取右半区间内所有字符串的公共前缀return commonPrefixTwo(pre1, pre2); // 求这两个公共前缀的公共前缀}// 求两个字符串的公共前缀private String commonPrefixTwo(String s1, String s2) {int minLen = Math.min(s1.length(), s2.length());int i = 0;while (i < minLen) {if (s1.charAt(i) != s2.charAt(i)) {break;}i++;}return s1.substring(0, i);}
}

25. K 个一组翻转链表

题目链接

25. K 个一组翻转链表

标签

递归 链表

思路

首先,这道题的难度为困难不是假的。其次,只要做过206. 反转链表, 24. 两两交换链表中的节点这两道题,对本题还是有一点思路的。其中,第二道题我写过文章:24. 两两交换链表中的节点。第一题很简单,相信大家看完本题后就会做了。

链表可以被分为长度为k的多段链表(最后一段长度如果不是k,则不需要反转),本题的操作可以理解为:反转多个长度为k的链表

反转一个链表有一种思路:将新链表从尾部开始建,每次都给出一个新节点插到头部,给出新节点的顺序是从旧链表的头部开始,直到旧链表的尾部。代码如下:

public ListNode reverseList(ListNode head) {ListNode new1 = null; // 新链表的头节点ListNode old1 = head; // 旧链表的头节点while (new1 != tail) { // 直到新链表的头节点等于旧链表的最后一个节点ListNode old2 = old1.next; // 先保存旧链表的第二个节点old1.next = new1; // 让旧链表的头节点指向新链表的头节点(反转的关键)new1 = old1; // 让新链表的头部向后移动一位old1 = old2; // 让旧链表的头部向后移动一位}return new1;
}

本题的反转链表有点不太一样,因为尾节点没有指向null,而是指向了一个节点,这时就需要传入两个值,一个是链表的头部head,一个是链表的尾部tail,进入循环的条件是 新链表的头节点 不等于 旧链表的尾节点,即new1 != tail

在反转完每段子链表时,子链表都从原链表中断开了,所以需要 重建子链表与原链表的关系,但有个前提——要知道四个节点:旧链表头节点的上一个节点prev、新链表的头节点head、新链表的尾节点tail、旧链表尾节点的下一个节点next。连接方式为:上一个节点指向新头节点prev.next = head,新尾节点指向下一个节点tail.next = next

要想反转这段链表,首先得保证这段链表的长度为k,并且还要找到尾节点,所以每次反转子链表前得先让尾节点的指针tail从旧链表的头部head开始,移动k步,如果遇到空节点,即tail == null,则返回结果即可,因为这段子链表的长度不足k

本题仍旧使用哨兵节点指向结果链表的头部的做法,因为前指针的初始值就是哨兵节点。

代码

class Solution {public ListNode reverseKGroup(ListNode head, int k) {ListNode sentinel = new ListNode(-1, head); // 哨兵节点指向结果链表的头部,返回其nextListNode prev = sentinel; // 前指针,指向待反转链表的头节点while (prev != null) {// 先保证有 k 个节点,并且还得有尾节点,然后才能反转ListNode tail = prev;for (int i = 0; i < k; i++) {tail = tail.next;if (tail == null) { // 如果节点数不够,则直接返回结果return sentinel.next;}}ListNode next = tail.next; // 反转前先保存原来尾节点的下一个节点// 进行反转ListNode[] reverse = reverse(head, tail); // 反转从头节点到尾节点的部分head = reverse[0]; // 获取新链表的头节点tail = reverse[1]; // 获取新链表的尾节点// 上面的操作会将部分链表从原始链表中截断,所以要重建节点之间的联系prev.next = head; // 让前一个节点指向新链表的头节点tail.next = next; // 让新链表的尾节点指向原来尾节点的下一个节点// 准备下一次的反转操作,更新指针的位置prev = tail; // 前指针移动到新链表的尾节点,即 指向待反转链表的头节点 的节点head = tail.next; // 头节点移动到新链表尾节点的下一个节点,即待反转链表的头节点}return sentinel.next;}// 新链表是从尾部开始建立,然后逐渐到头部private ListNode[] reverse(ListNode head, ListNode tail) {ListNode new1 = null; // 新链表的头节点ListNode old1 = head; // 旧链表的头节点while (new1 != tail) { // 直到新链表的头节点等于旧链表的最后一个节点ListNode old2 = old1.next; // 先保存旧链表的第二个节点old1.next = new1; // 让旧链表的头节点指向新链表的头节点(反转的关键)new1 = old1; // 让新链表的头部向后移动一位old1 = old2; // 让旧链表的头部向后移动一位}return new ListNode[]{tail, head}; // 返回新链表的头部和尾部}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搭建个人智能家居 6 -SGP30 CO₂与TVOC测量

搭建个人智能家居 6 -SGP30 CO₂与TVOC测量 前言说明ESPHomeHomeAssistant 前言 上一篇文章我们给这个智能家居系统添加了第三个外设&#xff0c;温湿度传感器。今天添加第四个外设&#xff0c;用于测量环境中CO₂与TVOC的传感器“SGP30”。 前问回顾&#xff1a; 搭建个人智能…

自然语言处理:第三十五章Embedding 测评榜单MTEB

文章链接: [2210.07316] MTEB: Massive Text Embedding Benchmark (arxiv.org) 项目地址: mteb:MTEB: Massive Text Embedding Benchmark - GitCode github地址: FlagEmbedding/C_MTEB at master FlagOpen/FlagEmbedding (github.com) Hugging Face Leadboard: MTEB Leader…

移动端超超超详细知识点总结(Part3)

flex布局体验 1. 传统布局与flex布局 传统布局&#xff1a; 兼容性好布局繁琐局限性&#xff0c;不能再移动端很好的布局flex 弹性布局&#xff1a; 操作方便&#xff0c;布局极为简单&#xff0c;移动端应用很广泛PC 端浏览器支持情况较差IE 11或更低版本&#xff0c;不支持…

Android开发AndroidStudio中创建Activity两种方法

本文讲解Android Studio中如何创建Activity。 目录 一、手动创建 二、自动创建 创建Activity分为手动和自动创建两种方法。 一、手动创建 创建步骤 1、在Layout目录下创建XML文件 Layout-New-Layout Resource file 打开对话框&#xff0c;编辑布局文件的名字&#xff0c…

JavaScript 进阶 - 第1天

文章目录 前言一、作用域1. 局部作用域1.1 函数作用域1.2 块作用域 2. 全局作用域3. 作用域链4. 闭包5. 变量提升 二、函数1. 函数提升2. 函数参数2.1 默认值2.2 动态参数2.3 剩余参数 3. 箭头函数 三、解构赋值1. 数组解构2. 对象解构 四、综合案例1. forEach遍历数组2. filte…

Capto2024软件怎么下载安装? 【详细安装图文教程】

Capto 2024是一款专为Mac用户设计的屏幕录制编辑软件。无论是想要制作教育视频、工作演示、游戏录制&#xff0c;还是进行简单的屏幕捕捉&#xff0c;Capto 2024都能满足您的需求。接下来&#xff0c;我将详细介绍其主要功能、特点以及使用场景&#xff0c;并为您评价这款软件。…

安装multisim14.0

前言 文件准备 软件安装 1、 2、 3、 4、 5、 6、 7、 8、 9、 10、 11、 12、 13、 14、汉化 15、在软件安装路径下打开”stringfiles“文件夹&#xff0c; Circuit Design Suite 14.0\stringfiles 16、 17、 18、 19、 20、运行multisim14.0

try-with-resources 工作原理

概述 try-with-resources 是 Java 7 引入的一种语法糖&#xff0c;用于简化资源管理&#xff0c;确保在使用资源后自动关闭它们。它是 try 语句的增强形式&#xff0c;可以在资源使用完毕后自动调用它们的 close() 方法&#xff0c;从而避免资源泄漏。 但这有个前提&#xff1…

Java多线程面试重点-2

16.Synchronized关键字加在静态方法和实例方法的区别? 修饰静态方法&#xff0c;是对类进行加锁&#xff08;Class对象&#xff09;&#xff0c;如果该类中有methodA和methodB都是被Synch修饰的静态方法&#xff0c;此时有两个线程T1、T2分别调用methodA()和methodB()&#x…

对于千兆变压器(Gigabit Transformer)的设计

对于千兆变压器&#xff08;Gigabit Transformer&#xff09;的设计&#xff0c;以下是一些关键方面的详细说明&#xff1a; 1. **频率特性&#xff1a;** 千兆变压器需要能够在高频率下工作&#xff0c;通常在1 GHz以上。为了确保良好的性能&#xff0c;设计中需要选择合适的…

热门开源项目推荐:智谱GLM-4-9B和ChatGLM3-6B

目录 热门开源项目推荐&#xff1a;智谱GLM-4-9B和ChatGLM3-6B 1.引言 1.1 开源文化简介 1.2 开源项目的重要性 1.3 博客目的和读者价值 2.什么是开源项目&#xff1f; 2.1 开源定义 2.2 开源许可证类型 2.3 开源社区的作用 3.为什么程序员应该关注开源项目&#xff…

如何在Ubuntu 22.04中还原默认终端:解决无法打开终端的问题

我之前安装了xterm和新的Python&#xff0c;无法打开ubuntu自带的gnome-terminalle 。 终端应用崩溃&#xff1a; 试着通过其他方式打开终端&#xff0c;例如按下 CtrlAltT。 尝试使用其他终端模拟器&#xff0c;例如 xterm、konsole 或 gnome-terminal。可以通过 AltF2 然后…

IDM究竟有哪些优势?一探究竟,揭开下载利器的神秘面纱

在当今互联网信息爆炸的时代&#xff0c;下载工具已经成为我们日常生活中不可或缺的一部分。Internet Download Manager&#xff08;IDM&#xff09;以其强大的功能和高效的性能&#xff0c;赢得了广大用户的青睐。那么&#xff0c;IDM究竟有哪些优势使其在众多下载工具中脱颖而…

整蛊软件/插件使用方法与配置步骤~

今天出一期整蛊软件的使用方法与配置步骤 很多人在使用整蛊软件的时候 想自己添加更多的玩法内容 但是还不知道如何去配置 这期给大家出一下图文教程步骤 基本上也是软件的功能介绍使用方式~ 案例可扫码查看 第一步&#xff1a;打开软件输入卡密登录&#xff1a; 卡密费用&…

最经济实惠的通配符SSL证书是哪款?

网络安全已成为企业和个人网站运营者关注的焦点。SSL证书作为确保数据传输安全的关键工具&#xff0c;其重要性不言而喻。特别是通配符SSL证书&#xff0c;因其能够为一个主域名及其所有子域名提供统一的安全保护&#xff0c;而受到广泛欢迎。但面对市场上众多的SSL证书品牌和价…

[大模型]Qwen2-7B-Instruct 接入 LangChain 搭建知识库助手

环境准备 在 autodl 平台中租赁一个 3090 等 24G 显存的显卡机器&#xff0c;如下图所示镜像选择 PyTorch–>2.1.0–>3.10(ubuntu20.04)–>12.1 接下来打开刚刚租用服务器的 JupyterLab&#xff0c;并且打开其中的终端开始环境配置、模型下载和运行 demo。 pip 换源…

mysql中社区版如何杀死锁

在MySQL中&#xff0c;特别是社区版&#xff0c;当遇到锁问题时&#xff0c;你可能需要杀死锁定资源的进程来解决问题。以下是一些步骤和相关信息&#xff0c;用于在MySQL中杀死锁定的进程&#xff1a; 查看当前进程&#xff1a; 首先&#xff0c;你需要查看当前MySQL中的所有…

One能聊天接入百度千帆AppBuilder

One能聊天介绍:基于ChatGPT实现的微信小程序,适配H5和WEB端。包含前后端,支持打字效果输出流式输出,支持AI聊天次数限制,支持分享增加次数等功能One能聊天开源地址:https://github.com/oldinaction/ChatGPT-MPOne能聊天演示环境:可关注【阿壹族】公众号,并回复【One能聊…

MySQL复制机制详解:主从复制与GTID复制的配置与管理

引言: MySQL复制是MySQL数据库的一项重要功能,它允许数据从一个MySQL数据库服务器(被称为主服务器)复制到一个或多个MySQL数据库服务器(被称为从服务器)。主要目的是为了实现数据冗余和备份,提高数据的可用性和读取性能。 主从复制(Master-Slave Replication)是最常…

12_YouOnlyLookOnce(YOLOv3)新一代实时目标检测技术

1.1 回顾V1和V2 V1&#xff1a;05_YouOnlyLookOnce(YOLOV1)目标检测领域的革命性突破-CSDN博客 V2&#xff1a;07_YouOnlyLookOnce(YOLOv2)Better&#xff0c;Faster&#xff0c;Stronger-CSDN博客 1.2 简介 YOLOv3&#xff08;You Only Look Once version 3&#xff09;是…