【LeetCode热题100】打卡第11天:有效括号合并两个有序链表

news2024/11/17 17:27:02

文章目录

  • 【LeetCode热题100】打开第11天
    • ⛅前言
      • 🔒有效括号
      • 🔑题解
      • 🔒合并两个有序链表
      • 🔑题解
      • 💡思路一:合并到第三方链表上
        • 🔐【非递归实现】
        • 🔐【递归实现】
      • 💡思路二 :合并到一个链表上
        • 🔐【非递归实现】
        • 🔐【递归实现】

【LeetCode热题100】打开第11天

⛅前言

大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏!

精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。在此专栏中,我们将会涵盖各种类型的算法题目,包括但不限于数组、链表、树、字典树、图、排序、搜索、动态规划等等,并会提供详细的解题思路以及Java代码实现。如果你也想刷题,不断提升自己,就请加入我们吧!QQ群号:827302436。我们共同监督打卡,一起学习,一起进步。

博客主页💖:知识汲取者的博客

LeetCode热题100专栏🚀:LeetCode热题100

Gitee地址📁:知识汲取者 (aghp) - Gitee.com

Github地址📁:Chinafrfq · GitHub

题目来源📢:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

PS:作者水平有限,如有错误或描述不当的地方,恳请及时告诉作者,作者将不胜感激

🔒有效括号

原题链接:Loading Question… - 力扣(LeetCode)

在这里插入图片描述

🔑题解

  • 解法一:替换

    /**
     * @author ghp
     * @title 有效的括号
     */
    class Solution {
        public boolean isValid(String s) {
            if (s.length() % 2 == 1) {
                // 字符个数为奇数,一定含有无效括号
                return false;
            }
            // 循环替换所有的括号,直到无法替换为止
            while (true) {
                int len = s.length();
                s = s.replace("()", "");
                s = s.replace("{}", "");
                s = s.replace("[]", "");
                if (s.length() == len) {
                    // 已经将所有可替换的全都替换了,如果此时len为0说明字符串有效
                    return len == 0;
                }
            }
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n 2 ) O(n^2) O(n2),while循环每一次都替换一对括号,总共需要循环n/2次,每次替换replace方法的时间复杂度是n,所以总的时间复杂度为 O ( n / 2 ∗ n ) O(n/2*n) O(n/2n)
    • 空间复杂度: O ( 1 ) O(1) O(1)

    其中 n n n 为括号的个数

  • 解法二:栈

    这个虽然时间复杂度

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Stack;
    
    /**
     * @author ghp
     * @title 有效的括号
     */
    class Solution {
    
        public static final Map<Character, Character> brackets = new HashMap() {{
            put('(', ')');
            put('[', ']');
            put('{', '}');
        }};
    
        public boolean isValid(String s) {
            if (s.length() % 2 == 1) {
                // 字符个数为奇数,一定含有无效括号
                return false;
            }
            Stack<Character> stack = new Stack<>();
            for (int i = 0; i < s.length(); i++) {
                char ch = s.charAt(i);
                if (brackets.containsKey(ch)) {
                    // 左括号,直接入栈
                    stack.push(ch);
                } else {
                    // 右括号,出栈,并判断是否与当前括号匹配(注意这里要判空,防止NPE)
                    if (stack.isEmpty() || brackets.get(stack.pop()) != ch) {
                        return false;
                    }
                }
            }
            return stack.isEmpty();
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ) O(n) O(n)
    • 空间复杂度: O ( n ) O(n) O(n)

    其中 n n n 为字符的个数


🔒合并两个有序链表

在这里插入图片描述

🔑题解

💡思路一:合并到第三方链表上

创建一个新的头节点,然后构成一个新链表,这个链表用来存放链表1和链表2比较留下的最小的结点

🔐【非递归实现】

解题示意图

原始代码

import java.util.*;

class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1 == null || list2 == null) {
        	//只要有一个为空就直接返回另一个
        	return list1 != null ? list1 : list2;
        }
        ListNode head1 = list1;//辅助遍历list1
        ListNode head2 = list2;//辅助遍历list2
        int val;//用来创建新链表的头节点
        //选出链表1和链表链表2较小的头节点作为 新链表的头节点的val
        if(head1.val < head2.val) {
        	val = head1.val;
        	head1 = head1.next;//这里需要后移,因为已经比较过了,后面就不需要再进行比较了
        }else {
        	val = head2.val;
        	head2 = head2.next;
        }
        ListNode newNode = new ListNode(val);//新建一个头节点,他是合并后链表的头节点
        ListNode head = newNode;//指向newNode链表,辅助遍历
        while(head1 != null && head2 != null) {//切记判断不要使用head1.next或者head2.next
        	if(head1.val < head2.val) {
                //说明当前链表1的结点是最小的
        		head.next = head1;//将链表1的结点添加到新链表上
        		head = head.next;//始终保证辅助指针再新链表的尾结点,方便结点的添加
        		head1 = head1.next;
        	}else {
        		head.next = head2;
        		head = head.next;
        		head2 = head2.next;
        	}
        }
        if(head1 != null && head2 == null) {
            //直接将链表1不为空的部分连接到新链表后面
        	head.next = head1;
        }
        if(head1 == null && head2 != null) {
            直接将链表2不为空的部分连接到新链表后面
        	head.next = head2;
        }
        return newNode;
    }
}

期间犯的错去:新建结点直接ListNode newNode = null;导致报空指针异常,原因是为空时,后面用到了head.next = head1|head2,后面还会讲解(当然还有一些睁眼瞎的错误,就不记录了w(゚Д゚)w

代码优化

  • 优化1:时间优化。我们可以直接创建一个结点,然后返回的时候只返回newNode.next结点即可,这样就不需要先进行判断了是用链表1的结点作为头节点,还是链表2的结点作为头节点,能够一定程度降低时间损耗。
  • 优化2:空间优化。同时因为我们是将链表1和链表2进行合并,不再需要再使用链表1和链表2,所以可以直接使用list1和list2进行遍历,而不再借助辅助指针进行比遍历,能一定程度减少内存消耗

优化后的代码

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1 == null || list2 == null) {
        	//只要有一个为空就直接返回另一个
        	return list1 != null ? list1 : list2;
        }
        ListNode newNode = new ListNode(-1);//新建一个空指针,指向合并后链表的头节点
        ListNode head = newNode;//辅助newNode,用新增结点
        while(list1 != null && list2 != null) {
        	if(list1.val < list2.val) {
        		head.next = list1;
        		head = head.next;
        		list1 = list1.next;
        	}else {
        		head.next = list2;
        		head = head.next;
        		list2 = list2.next;
        	}
        }
        if(list1 != null && list2 == null) {
            //直接将链表1不为空的部分连接到新链表后面
        	head.next = list1;
        }
        if(list1 == null && list2 != null) {
            直接将链表2不为空的部分连接到新链表后面
        	head.next = list2;
        }
        return newNode.next;
    }
}

🔐【递归实现】

解题示意图
在这里插入图片描述

代码实现

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
    	if(list1 == null || list2 == null) {
        	//只要有一个为空就直接返回另一个
        	return list1 != null ? list1 : list2;
        }
        ListNode newNode = new ListNode(-1);//新建头节点,用于构建新链表
        ListNode head = newNode;//辅助指针,用于遍历新链表同时新增结点
        if(list2.val>list1.val){
        	head.next = list1;//将链表1的结点挂到新链表上
        	head = head.next;//始终保证head指向新链表的尾结点,方便增加结点
            head.next = Merge(list1.next,list2);//list1已经比完,移动list1指针
        }
        else{
        	head.next = list2;
        	head = head.next;
            head.next = Merge(list1,list2.next);
        }
        return newNode.next;
    }
}

💡思路二 :合并到一个链表上

先确定头节点是选用list1还是list2,然后借助辅助指针,将链表1和链表2串连起来

🔐【非递归实现】

解题示意图

在这里插入图片描述

代码实现

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1 == null || list2 == null) {
        	//只要有一个为空就直接返回另一个
        	return list1 != null ? list1 : list2;
        }
        ListNode newNode = null;//新建一个空指针,指向合并后链表的头节点
        ListNode head = null;//辅助newNode,用新增结点
        while(list1 != null && list2 != null) {
        	if(list1.val < list2.val) {
        		if(newNode == null) {
        			//以head1为头结点
        			newNode = list1;
        			head = newNode;//设置辅助指针,因为头指针是新链表的位置标识,不能动
        			list1 = list1.next;
        			continue;//后面的代码就不需要执行了
        		}
        		head.next = list1;
        		head = head.next;
        		list1 = list1.next;
        	}else {
        		if(newNode == null) {
                    //以head2为头节点
        			newNode = list2;
        			head = newNode;
        			list2 = list2.next;
        			continue;
        		}
        		head.next = list2;
        		head = head.next;
        		list2 = list2.next;
        	}
        }
        if(list1 != null && list2 == null) {
            //直接将链表1不为空的部分连接到新链表后面
        	head.next = list1;
        }
        if(list1 == null && list2 != null) {
            直接将链表2不为空的部分连接到新链表后面
        	head.next = list2;
        }
        return newNode;
    }
}

🔐【递归实现】

代码实现

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1 == null || list2 == null) {
        	return list1 != null ? list1 : list2;//只要有一个为空就直接返回另一个
        }
        //判断选用哪一个作为头节点
        if(list2.val>list1.val){
            //开始递归
            list1.next = Merge(list1.next,list2);
            return list1;
        }
        else{
            list2.next = Merge(list1,list2.next);
            return list2;
        }
    }
}

这个是参考别人的,这段代码太妙了wow~ ⊙o⊙

具体实现思路,就是不断地去寻找两个链表的最小结点,直到为空为止(具体过程我知道,但是不知道为什么描述不出来,可能是还没完全懂吧┭┮﹏┭┮)

递归需要两个必备条件:递归终止条件+递归入口条件。即什么时候结束递归,什么时候开始递归。明白这两点应该就能看懂这段代码了

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

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

相关文章

2023年上半年数据库系统工程师下午真题及答案解析

试题一(15分) 某新能源汽车公司为了提升效率&#xff0c;需开发一个汽车零件采购系统。请完成系统的数据库设计。 概念结构设计 需求描述 (1)记录供应商信息&#xff0c;包括供应商的名称、地址和一个电话。 (2)记录零件信息&#xff0c;包括零件的编码、名称和价格。 (3)…

线程的四个属性

如上图所示&#xff0c;线程有四个属性&#xff1a; 线程ID线程名称守护线程线程优先级 1. 线程ID 每个线程都有id&#xff0c;这个id不能修改 线程id会不停的自增&#xff0c;从1开始 main函数就是第一个线程&#xff0c;id1 id 是操作系统用来识别各个线程的编号&#…

DHVT:在小数据集上降低VIT与卷积神经网络之间差距,解决从零开始训练的问题

VIT在归纳偏置方面存在空间相关性和信道表示的多样性两大缺陷。所以论文提出了动态混合视觉变压器(DHVT)来增强这两种感应偏差。 在空间方面&#xff0c;采用混合结构&#xff0c;将卷积集成到补丁嵌入和多层感知器模块中&#xff0c;迫使模型捕获令牌特征及其相邻特征。 在信…

tcp shrinking window 之进退

一个有趣的问题&#xff1a;Unbounded memory usage by TCP for receive buffers, and how we fixed it 引出一个 kernel patch&#xff1a;[PATCH] Add a sysctl to allow TCP window shrinking in order to honor memory limits 但这 patch 把一个问题变成了两个问题&#…

apple pencil一代的平替有哪些品牌?平价电容笔推荐

要知道&#xff0c;真正的苹果原装电容笔&#xff0c;价格可不低&#xff0c;仅仅一支就是近千块。实际上&#xff0c;平替电容笔对没有太多预算的用户是个不错的选择。一款苹果的电容笔的售价&#xff0c;相当于平替电容笔的四倍&#xff0c;不过平替电容笔的书写体验&#xf…

pnpm对npm及yarn降维打击详解

目录 正文npm2yarnpnpm总结 正文 大家最近是不是经常听到 pnpm&#xff0c;我也一样。今天研究了一下它的机制&#xff0c;确实厉害&#xff0c;对 yarn 和 npm 可以说是降维打击。 那具体好在哪里呢&#xff1f; 我们一起来看一下。 我们按照包管理工具的发展历史&#xf…

3.5 凸多边形最优三角部分

博主简介&#xff1a;一个爱打游戏的计算机专业学生博主主页&#xff1a; 夏驰和徐策所属专栏&#xff1a;算法设计与分析 1.什么是多边形的三角剖分&#xff1f; 多边形三角剖分是指将多边形分割成互不相交的三角形的弦的集合T。 我的理解&#xff1a; 多边形三角剖分是将给…

uniapp本地存储详解

uniapp本地存储详解 前言 在开发uniapp应用时&#xff0c;我们常常需要使用本地存储来保存一些数据&#xff0c;比如用户登录信息、设置项等&#xff0c;使得应用能够在设备上保存和读取数据&#xff0c;以便提供更好的用户体验和离线功能支持&#xff0c;本文将简单介绍unia…

python编程——编译器与解释器

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 本文专栏&#xff1a;python专栏 专栏介绍&#xff1a;本专栏为免费专栏&#xff0c;并且会持续更新python基础知识&#xff0c;欢迎各位订阅关注。 目录 前言 一、编译器与解释器的介绍 二、编译器与解释器…

JDK1.8下载安装(优雅)

bug虐我千百遍&#xff0c;我待bug如初恋。 这里使用的环境是win11 64位系统&#xff0c;应该适配win8-win11 一、下载 这里提供两种下载方式&#xff0c;官网下载和第三方下载&#xff0c;区别就是下载速度不同 1. 官网下载 &#xff08;1&#xff09;官网下载&#xff1a;…

智慧物流货运系统源码 货运平台的功能介绍

网络货运平台源码 网络货运平台的功能 网络货运是指利用互联网平台&#xff0c;通过物流配送的方式进行商品销售和物流运输的一种新型商业模式。这种模式将传统的货运模式与互联网技术相结合&#xff0c;通过网络平台进行交易、物流配送和结算等一系列商业流程&#xff0c;从而…

用户画像如何创新破局数据驱动增长 | 数据增长

用户画像即用户信息标签化&#xff0c;就是企业通过收集与分析消费者社会属性、生活习惯、消费行为等主要信息的数据之后&#xff0c;完美地抽象出一个用户的商业全貌&#xff0c;是企业应用大数据技术的基本方式。例如&#xff1a;通过收集用户的人口属性、行为属性、消费习惯…

面向初学者的数据科学|要学习的内容概述

面向初学者的数据科学|要学习的内容概述 数据科学家是21世纪最性感的工作。每个人都想变得性感。该领域开始变得竞争激烈&#xff0c;提高了就业标准。 因此&#xff0c;仅仅知道如何使用不同的工具是不够的&#xff0c;求职者需要能够抓住基本的概念和技术&#xff0c;然后应用…

VMware Cloud Foundation 5.0 发布 - 领先的多云平台

VMware Cloud Foundation 5.0 发布 - 领先的多云平台 高效管理虚拟机 (VM) 和容器工作负载。为本地部署的全栈超融合基础架构 (HCI) 提供云的优势。 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-cloud-foundation-5/&#xff0c;查看最新版。原创作品&#xff…

DEMO:F4帮助 收藏夹功能

货铺QQ群号&#xff1a;834508274微信群不能扫码进了&#xff0c;可以加我微信SAPliumeng拉进群&#xff0c;申请时请提供您哪个模块顾问&#xff0c;否则是一律不通过的。进群统一修改群名片&#xff0c;例如BJ_ABAP_森林木。群内禁止发广告及其他一切无关链接&#xff0c;小程…

没有硬件资源?免费使用Colab搭建你自己的Stable Diffiusion在线模型!保姆级教程...

部署 Stable Diffusion 需要一定的硬件资源&#xff0c;具体取决于要处理的图像大小和处理速度等因素。一般来说&#xff0c;至少需要一台具有较高计算能力的服务器&#xff0c;而对 GPU 的高要求就限制了我们学习和使用SD来生成我们想要的图像。 GPU是深度学习开发的重要硬件条…

C++ 学习 ::【基础篇:16】:C++ 类的基本成员函数:拷贝构造函数(认识、特征、注意点及典型使用场景)及其基本写法与调用

本系列 C 相关文章 仅为笔者学习笔记记录&#xff0c;用自己的理解记录学习&#xff01;C 学习系列将分为三个阶段&#xff1a;基础篇、STL 篇、高阶数据结构与算法篇&#xff0c;相关重点内容如下&#xff1a; 基础篇&#xff1a;类与对象&#xff08;涉及C的三大特性等&#…

FastJSON autoType is not support问题解决

概述 产品在使用内部的后台管理系统时反馈的问题。 于是登录平台&#xff0c;发现如下报错详情&#xff1a; 排查 经过分析&#xff0c;不难得知&#xff0c;请求是从gateway网关转发到对应的统计服务 statistics&#xff0c;此服务有个接口/api/statistics/data/overview…

华为OD机试真题 Java 实现【支持优先级的队列】【2023 B卷 100分】

一、题目描述 实现一个支持优先级的队列&#xff0c;高优先级先出队列&#xff0c;同优先级时先进先出。 如果两个输入数据和优先级都相同&#xff0c;则后一个数据不入队列被丢弃。 队列存储的数据内容是一个整数。 二、输入描述 一组待存入队列的数据&#xff08;包含内…

Java官方笔记4类和对象

创建类 定义类Bicycle&#xff1a; public class Bicycle {// the Bicycle class has// three fieldspublic int cadence;public int gear;public int speed;// the Bicycle class has// one constructorpublic Bicycle(int startCadence, int startSpeed, int startGear) {gea…