LeetCode 热题 HOT 100(P11~P20)

 系列文章: 

LeetCode 热题 HOT 100(P1~P10)-CSDN博客

LeetCode 热题 HOT 100(P11~P20)-CSDN博客

LC020valid_parentheses

. - 力扣(LeetCode)

题目:

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

解法:

遇到右括号的时候需要判断有没有对应匹配的左括号,因为必须是类型相同的才能进行闭合,因此需要一个栈来维护遇到的左括号,看栈顶的左括号是否跟当前的右括号匹配。

 static Map<Character, Character> cache = new HashMap<>();static {cache.put(')', '(');cache.put('}', '{');cache.put(']', '[');}public boolean isValid(String s) {LinkedList<Character> stack = new LinkedList<>();for (char c : s.toCharArray()) {//  遇到右括号就需要一定要有匹配的左括号if (cache.containsKey(c)) {if (stack.isEmpty()) {return false;}if (cache.get(c) != stack.pop()) {return false;}} else {//左括号的情况,直接入栈stack.push(c);}}return stack.isEmpty();}

这里有个技巧,维护一个右括号为key 的map,这样方便判断和匹配。

LC021merge_two 

. - 力扣(LeetCode)

题目:

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

解法:

遇到链表题,直接创建一个pre 节点,接着轮流比较两边的大小,比较繁琐的是需要判断很多临界情况。

 public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode pre = new ListNode();ListNode cur = pre;while (list1 != null || list2 != null) {ListNode next;if (list1 == null) {next = list2;list2 = list2.next;} else if (list2 == null) {next = list1;list1 = list1.next;} else {if (list1.val < list2.val) {next = list1;list1 = list1.next;} else {next = list2;list2 = list2.next;}}cur.next = next;cur = cur.next;}return pre.next;}

LC022generate_parentheses

. - 力扣(LeetCode)

题目:

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

题解:

一般这种题都是递归的思路,相当于有2n个位置,每个位置都可能至多有2种策略,不是放左括号就是放右括号,放好之后再接着放下一个。这里有个有效括号的限制,所以想清楚这个就相对容易了。

    List<String> result = new ArrayList<>();public List<String> generateParenthesis(int n) {dsf("", n, n);return result;}/*** 递归的写法** @param path  当前的字符串* @param left  左括号剩余使用次数* @param right 右括号剩余使用次数*/private void dsf(String path, int left, int right) {// 错误的情况if (left > right) {return;}if (left == 0 && right == 0) {result.add(path);return;}if (left > 0) {dsf(path + "(", left - 1, right);}if (right > 0) {dsf(path + ")", left, right - 1);}}

这里使用剩余使用测试,而不是已经使用次数,会让代码更加清晰。

递归的写法在熟悉递归模板之后,就是对什么时候跳出递归的判断,这一步思考清楚,后面就不难了。

LC023merge_k

. - 力扣(LeetCode)

题目:

给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。

题解:

其实就是利用递归的思路,先对半往下递归,最后是两个链表的合并(LC021merge_two )。

public ListNode mergeKLists(ListNode[] lists) {if (lists.length == 0) {return null;}return merge(lists, 0, lists.length - 1);}private ListNode merge(ListNode[] lists, int left, int right) {if (left == right) {return lists[left];}int mid = left + (right - left) / 2;final ListNode l1 = merge(lists, left, mid);final ListNode l2 = merge(lists, mid + 1, right);return merge2(l1, l2);}private ListNode merge2(ListNode l1, ListNode l2) {if (l1 == null) {return l2;}if (l2 == null) {return l1;}if (l1.val < l2.val) {l1.next = merge2(l1.next, l2);return l1;} else {l2.next = merge2(l1, l2.next);return l2;}}

递归真是好东西啊,任何复杂的问题都能化繁为简。

LC031next_permutation

. - 力扣(LeetCode)

题目:

整数数组的一个 排列  就是将其所有成员以序列或线性顺序排列。
整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
给你一个整数数组 nums ,找出 nums 的下一个排列。

题解:

这类题目就是典型的套路题了,当初靠自己想破脑袋估计也想不出来,直接看题解知道套路,掌握思路后加上自己在事例上推演下也就能写出来了。

public void nextPermutation(int[] nums) {final int len = nums.length;if (len < 2) {return;}int i = len - 2, k = len - 1;//找到最右边的“小数”while (i >= 0 && nums[i] >= nums[i + 1]) {i--;}//如果不是最后一种情况,注意这里包含=0 的情况if (i >= 0) {//从后往前,找到尽可能“小”的大数while (nums[i] >= nums[k]) {k--;}int tmp = nums[i];nums[i] = nums[k];nums[k] = tmp;}//需要将i+1 之后的数字排序//将「大数」换到前面后,需要将「大数」后面的所有数 重置为升序,升序排列就是最小的排列。Arrays.sort(nums, i + 1, len);}

LC032longest_valid

. - 力扣(LeetCode)

题目:

给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度

题解:

“最*** ” 的基本是动态规划的思路。只是这里情况比较复杂,需要考虑很多边界情况

public int longestValidParentheses(String s) {final char[] chars = s.toCharArray();int[] dp = new int[chars.length];int max = 0;for (int i = 1; i < chars.length; i++) {//只有封闭的右括号才有可能配对if (chars[i] == ')') {//跟前一位刚好匹配if (chars[i - 1] == '(') {// 数量就是前前位+2,这里>= 还是> 实际是一样的,因为dp[0]=0dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;} else { // i-1 也是右括号final int pre = i - 1 - dp[i - 1];if (pre >= 0 && chars[pre] == '(') {dp[i] = (pre > 0 ? dp[pre - 1] : 0) + dp[i - 1] + 2;}}max = Math.max(max, dp[i]);}}return max;}

这个也可以算套路题吧,动态规划还是挺考验功力的,动态方程往往取决动态数组的定义。这类题只能靠多做,多培养感觉了。

LC033search_in

. - 力扣(LeetCode)

题目:

整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

题解:

经典的二分查找啊,之前刚学二分查找的时候觉得这玩意还不简单,没有特意准备,结果是啪啪打脸了。先复习下二分查找模板:

left, right = 0, len(array) - 1 
/注意这里的=
while left <= right:mid = left+(right - left) / 2 if array[mid] == target:# find the target!!break or return result elif array[mid] < target:left = mid + 1 else:right = mid - 1

回到这道题,关键点是旋转数组始终有一半是有序的,这个时候针对有序的一边进行判断和处理,如果不在这一边就说明在另一边,说明当前这一边可以舍弃,继续下一步迭代。

public int search(int[] nums, int target) {if (nums.length == 0) {return -1;}int left = 0, right = nums.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] == target) {return mid;}//左边有序的情况if (nums[left] <= nums[mid]) {if (target >= nums[left] && target <= nums[mid]) {right = mid - 1;} else {left = mid + 1;}} else {if (target > nums[mid] && target <= nums[right]) {left = mid + 1;} else {right = mid - 1;}}}return -1;}

LC34find_first

. - 力扣(LeetCode)

题目:

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

题解:

这道题比较有意思,一般我们通过折半查找都是确定具体的位置,这里是要找做边界和右边界,实际跟折半查找非常类似,只是左边界往小的那一边继续找,右边界就往大的那一边继续找。

public int[] searchRange(int[] nums, int target) {final int len = nums.length;if (len == 0) {return new int[]{ -1, -1 };}int left = 0, right = len - 1;int begin = -1, end = -1;//先找左边起始点while (left <= right) {int mid = left + (right - left) / 2;//要找左边界,需要往尽可能小的方向寻找if (nums[mid] == target) {begin = mid;right = mid - 1;} else if (target > nums[mid]) {left = mid + 1;} else {right = mid - 1;}}left = 0;right = len - 1;while (left <= right) {int mid = left + (right - left) / 2;//要找右边界,需要往尽可能大的方向寻找if (nums[mid] == target) {end = mid;left = mid + 1;} else if (target > nums[mid]) {left = mid + 1;} else {right = mid - 1;}}return new int[]{ begin, end };}

可以看到有挺多重复代码,可以提一个方法出来

public int[] searchRange(int[] nums, int target) {int left = 0, right = nums.length - 1;int begin = getLocation(nums, target, left, right, true);int end = getLocation(nums, target, left, right, false);return new int[]{ begin, end };}/*** 找到target 对应的下标** @param nums* @param target* @param left* @param right* @param isBegin 是否起始点* @return*/private int getLocation(int[] nums, int target, int left, int right, boolean isBegin) {int location = -1;while (left <= right) {int mid = left + (right - left) / 2;if (target == nums[mid]) {location = mid;//关键点在于找起止点的时候对左右游标的处理if (isBegin) {right = mid - 1;} else {left = mid + 1;}} else if (target < nums[mid]) {right = mid - 1;} else {left = mid + 1;}}return location;}

LC39combination_sum

. - 力扣(LeetCode)

题目:

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
 candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

题解:

也是典型的递归思路,关键是怎么保证不走回头路,比如有整数数组是(1,2,3),在递归1 的时候,把所有可以跟1组合的所有数组都穷举了,那么递归到2 的时候,就不能再用1 了,因为这个组合肯定在之前递归1的时候已经存在了。

public List<List<Integer>> combinationSum(int[] candidates, int target) {if (candidates.length == 0) {return result;}dfs(candidates, new ArrayList<>(), 0, target);return result;}/*** 注意这里需要一个start 标识,用来避免走回头路引起的重复数据** @param candidates* @param path* @param start* @param target*/private void dfs(int[] candidates, ArrayList<Integer> path, int start, int target) {if (target == 0) {result.add(new ArrayList<>(path));return;}if (target < 0) {return;}for (int i = start; i < candidates.length; i++) {path.add(candidates[i]);dfs(candidates, path, i, target - candidates[i]);path.remove(path.size() - 1);}}

LC46permutations

. - 力扣(LeetCode)

题目:

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

题解:

也是用递归解决,难点在于去重。这里通过一个boolean 数组来标识已经使用过的数字。这里可以复习下上一篇的递归模板。

List<List<Integer>> result = new ArrayList<>();public List<List<Integer>> permute(int[] nums) {boolean[] used = new boolean[nums.length];dfs(nums, new ArrayList<>(), used);return result;}private void dfs(int[] nums, ArrayList<Integer> path, boolean[] used) {if (path.size() == nums.length) {result.add(new ArrayList<>(path));return;}for (int i = 0; i < nums.length; i++) {if (used[i]) {continue;}path.add(nums[i]);used[i] = true;dfs(nums, path, used);used[i] = false;path.remove(path.size() - 1);}}

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

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

相关文章

医疗器械经营许可证办理流程及申请流程有哪些?

1、证书内容差异&#xff1a; 1.医疗器械经营许可证应当载明许可证号码、法定代表人、负责人、住所、经营范围、仓库地址、发证部门、日期及有效期、公司名称等事项。 2.医疗器械生产经营管理注册证书应当载明编号、公司产品名称、法定代表人、住所、经营活动场所、业务发展方…

基于PyTorch的视频分类实战

1、数据集下载 官方链接&#xff1a;https://serre-lab.clps.brown.edu/resource/hmdb-a-large-human-motion-database/#Downloads 百度网盘连接&#xff1a; https://pan.baidu.com/s/1sSn--u_oLvTDjH-BgOAv_Q?pwdxsri 提取码: xsri 官方链接有详细的数据集介绍&#xf…

网络视频播放器|基于JSP技术+ Mysql+Java+ B/S结构的网络视频播放器设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

Windows server 2008 R2 在VMware虚拟机上的安装

Windows server 2008 R2 在VMware虚拟机上的安装 准备工作VMware 新建并配置虚拟机安装和启动Windows server 2008 R2 准备工作 Windows server 2008 R2 ISO镜像的下载&#xff1a;Windows server 2008 R2 ISO VMware 新建并配置虚拟机 第一步&#xff0c;点击新建虚拟机 第…

【洛谷 P9242】[蓝桥杯 2023 省 B] 接龙数列 题解(线性DP)

[蓝桥杯 2023 省 B] 接龙数列 题目描述 对于一个长度为 K K K 的整数数列&#xff1a; A 1 , A 2 , … , A K A_{1},A_{2},\ldots,A_{K} A1​,A2​,…,AK​&#xff0c;我们称之为接龙数列当且仅当 A i A_{i} Ai​ 的首位数字恰好等于 A i − 1 A_{i-1} Ai−1​ 的末位数字…

ASP.NET通过Appliaction和Session统计在人数和历史访问量

目录 背景: Appliaction&#xff1a; Session&#xff1a; 过程&#xff1a; 数据库&#xff1a; Application_Start&#xff1a; Session_Start&#xff1a; Session_End&#xff1a; Application_End&#xff1a; 背景: 事件何时激发Application_Start在调用当前应用…

200W-300W厚膜电阻-SOT227小方块封装功率负载电阻器

SOT-227 型电阻器是许多电流监测和精密控制应用的理想选择&#xff0c;其电阻值低至 0.5 mΩ。这些高度可靠的无感厚膜功率电阻器采用四端子开尔文连接&#xff0c;可将测量路径与电流路径隔离&#xff0c;当与适当的散热器一起使用时&#xff0c;同样适用于高功率电流监测。电…

C# Selenium Edge 驱动下的常见用法

using OpenQA.Selenium; using OpenQA.Selenium.Edge; using OpenQA.Selenium.Support.UI; //添加缩放属性 将浏览器缩放设为100% EdgeOptions optionsnew EdgeOptions(); options.AddArgument("force-device-scale-factor1"); //不需添加额外属性 options可不写…

若依jar包运行脚本,从零到一:用Bash脚本实现JAR应用的启动、停止与监控

脚本使用说明&#xff1a; 启动应用&#xff1a;sh app.sh start停止应用&#xff1a;sh app.sh stop检查应用状态&#xff1a;sh app.sh status重启应用&#xff1a;sh app.sh restart 注意事项&#xff1a; 请确保你的系统上安装了 Java 环境&#xff0c;并且 ruoyi-admin…

Android11实现能同时开多个录屏应用(或者共享屏幕或投屏时录屏)

1.概述 Android原生对MediaProjection的管理逻辑&#xff0c;是如果服务端已经保存有MediaProjection的实例&#xff0c;那么再次创建的时候&#xff0c;之前的MediaProjection实例就会被暂停&#xff0c;并且引用指向新的实例&#xff0c;也就导致了当开启后一个录屏应用时&a…

Cookie 信息泄露 Cookie未设置http only属性 原理以及修复方法

漏洞名称&#xff1a;Cookie信息泄露、Cookie安全性漏洞、Cookie未设置httponly属性 漏洞描述&#xff1a; cookie的属性设置不当可能会造成系统用户安全隐患&#xff0c;Cookie信息泄露是Cookiehttp only配置缺陷引起的&#xff0c;在设置Cookie时&#xff0c;可以设置的一个…

Visual Studio .NET 中常用的文件类型

Visual Studio .NET 中常用的文件类型 扩展名名称描述.slnVisual studio .NET解决方案文件.sln文件为解决方案资源管理器提供显示管理文件的图形接口所需的信息。打开.sln文件能快捷地打开整个项目的所有文件.csprojVisual C# 项目文件一个特殊的XML文档&#xff0c;主要用来控…

SQLiteC/C++接口详细介绍sqlite3_stmt类简介

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十八&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍sqlite3_stmt类&#xff08;一&#xff09; 预准备语句对象 typedef struct sqlite3_stmt sqlite3_stmt…

【洛谷 P9232】[蓝桥杯 2023 省 A] 更小的数 题解(字符串+区间DP)

[蓝桥杯 2023 省 A] 更小的数 题目描述 小蓝有一个长度均为 n n n 且仅由数字字符 0 ∼ 9 0 \sim 9 0∼9 组成的字符串&#xff0c;下标从 0 0 0 到 n − 1 n-1 n−1&#xff0c;你可以将其视作是一个具有 n n n 位的十进制数字 n u m num num&#xff0c;小蓝可以从 n…

java 程序连接 redis 集群 的时候报错 MUTLI is currently not supported in cluster mode

找了半天找不到,为什么国内文章环境是真的差&#xff0c; redis 集群不支持事务&#xff0c;而你的方法上面估计使用了 spring 的事务导致错误具体解决&#xff1a; Transactional(propagation Propagation.NOT_SUPPORTED)public <T> void removeMultiCacheMapValue…

内置泵电源,热保护电路等功能的场扫描电路D78040,偏转电流可达1.7Ap-p,可用于中小型显示器。

D78040是一款场扫描电路&#xff0c;偏转电流可达1.7Ap-p&#xff0c;可用于中小型显示器。 二 特 点 1、有内置泵电源 2、垂直输出电路 3、热保护电路 4、偏转电流可达1.7Ap-p 三 基本参数 四 应用电路图 1、应用线路 2、PIN5脚输出波形如下&#xff1a;

6-高维空间:机器如何面对越来越复杂的问题

声明 本文章基于哔哩哔哩付费课程《小白也能听懂的人工智能原理》。仅供学习记录、分享&#xff0c;严禁他用&#xff01;&#xff01;如有侵权&#xff0c;请联系删除 目录 一、知识引入 &#xff08;一&#xff09;二维输入数据 &#xff08;二&#xff09;数据特征维度 …

一级指针和二级指针

一级指针 形式&#xff1a;int a 2; int *p &a; 解释&#xff1a; int*p &a表示一级指针p指向变量a的值。此时一级指针p存放的是a的地址&#xff0c;*p解引用是a的值。 作用&#xff1a; c中随处可见。不多言。 二级指针 形式&#xff1a;int a 2; int *p &…

C语言calloc函数的特点,效率低。但是进行初始化操作

#define _CRT_SECURE_NO_WARNINGS 1 #include<stdlib.h> #include<string.h> #include<errno.h> #include<stdio.h> int main() { int *p (int *)calloc(10,sizeof(int)); //初始化&#xff0c;效率低&#xff0c;然而malloc函数相反&#xf…

Linux/Ubuntu/Debian的终端中和的区别

下边举例说明&#xff1a; “cd /home & wine ps.exe”和“cd /home && wine ps.exe”之间的区别在于命令在类 Unix shell 环境&#xff08;例如 Linux 或 macOS&#xff09;中执行的方式&#xff1a; ‘cd /home & wine ps.exe’: 在此命令中&#xff0c;“…