怒刷LeetCode的第3天(Java版)

目录

第一题

题目来源

题目内容

解决方法

方法一:动态规划

第二题

题目来源

题目内容

解决方法

方法一:模拟

方法二:数学规律

方法三:分组

第三题

题目来源

题目内容

解决方法

方法一:数学方法

方法二:转换字符串


第一题

题目来源

213. 打家劫舍 II - 力扣(LeetCode)

题目内容

解决方法

方法一:动态规划

这道题可以使用动态规划的方法求解。首先,我们观察到第一个房屋和最后一个房屋是相邻的,因此它们不能同时被偷窃。所以,我们可以将问题分成两种情况来考虑:

  • 偷窃第一个房屋但不偷窃最后一个房屋:在这种情况下,我们只需要计算从第一个房屋到倒数第二个房屋能够偷窃到的最高金额。

  • 不偷窃第一个房屋但偷窃最后一个房屋:在这种情况下,我们只需要计算从第二个房屋到最后一个房屋能够偷窃到的最高金额。

对于每一种情况,我们可以使用动态规划来求解。定义一个长度为n的数组dp,其中dp[i]表示从第一个房屋到第i个房屋能够偷窃到的最高金额。那么,我们有以下状态转移方程:

  1. 对于第一种情况,dp[i] = max(dp[i-2] + nums[i], dp[i-1]),其中dp[i-2] + nums[i]表示偷窃第i个房屋得到的金额,dp[i-1]表示不偷窃第i个房屋得到的金额。

  2. 对于第二种情况,dp[i] = max(dp[i-1], dp[i-2] + nums[i]),其中dp[i-1]表示不偷窃第i个房屋得到的金额,dp[i-2] + nums[i]表示偷窃第i个房屋得到的金额。

最后,我们可以将第一种情况和第二种情况的结果取较大值作为最终的结果,即max(dp[n-2], dp[n-1]),其中n是数组nums的长度。

class Solution {public int rob(int[] nums) {int n = nums.length;if (n == 1) {return nums[0];}return Math.max(robHouse(nums, 0, n - 2), robHouse(nums, 1, n - 1));}private int robHouse(int[] nums, int start, int end) {int pre2 = 0, pre1 = 0;for (int i = start; i <= end; i++) {int cur = Math.max(pre2 + nums[i], pre1);pre2 = pre1;pre1 = cur;}return pre1;}
}

在上述解法中,我们使用了动态规划的思想来解决问题。接下来我们来分析一下该解法的时间复杂度和空间复杂度。

时间复杂度分析:

  • 在计算偷窃第一种情况的最高金额时,我们需要遍历从第一个房屋到倒数第二个房屋,因此时间复杂度为O(n)。
  • 在计算偷窃第二种情况的最高金额时,我们需要遍历从第二个房屋到最后一个房屋,同样时间复杂度为O(n)。
  • 最后取两种情况的较大值作为最终结果,时间复杂度为O(1)。 综上所述,该解法的时间复杂度为O(n)。

空间复杂度分析:

  • 我们使用了一个长度为n的dp数组来保存每个房屋能够偷窃到的最高金额,因此空间复杂度为O(n)。
  • 另外,我们还使用了常量级的额外空间来保存前两个房屋的偷窃金额,所以空间复杂度为O(1)。 综上所述,该解法的空间复杂度为O(n)。

总结: 该解法的时间复杂度为O(n),空间复杂度为O(n)。在给定限制条件下,这是一个较优的解法。

LeetCode运行结果:

第二题

题目来源

6. N 字形变换 - 力扣(LeetCode)

题目内容

解决方法

方法一:模拟

这个问题可以使用模拟的方法来解决。我们可以创建一个长度为numRows的字符串数组,表示Z字形排列后每一行的字符串。然后遍历原始字符串s,将每个字符按照Z字形的规律放入对应的行中。

具体步骤如下:

  1. 若numRows为1或s的长度小于等于numRows,则直接返回s作为结果。
  2. 创建一个长度为numRows的字符串数组rows,用于保存每一行的字符串。
  3. 创建一个变量rowIndex,初始值为0,表示当前所在的行。
  4. 创建一个变量goingDown,初始值为true,表示当前的方向是向下。
  5. 遍历字符串s的每个字符:
    • 将当前字符加入rows[rowIndex]中。
    • 如果当前的方向是向下且当前行不是最后一行,则向下移动到下一行(rowIndex++)。
    • 如果当前的方向是向上且当前行不是第一行,则向上移动到上一行(rowIndex--)。
    • 如果当前行是第一行或最后一行,则改变方向(goingDown = !goingDown)。
  6. 将数组rows中的每个字符串按顺序连接起来,即为结果。
class Solution {public String convert(String s, int numRows) {if (numRows == 1 || s.length() <= numRows) {return s;}String[] rows = new String[numRows];for (int i = 0; i < numRows; i++) {rows[i] = "";}int rowIndex = 0;boolean goingDown = true;for (char c : s.toCharArray()) {rows[rowIndex] += c;if (goingDown && rowIndex < numRows - 1) {rowIndex++;} else if (!goingDown && rowIndex > 0) {rowIndex--;}if (rowIndex == 0 || rowIndex == numRows - 1) {goingDown = !goingDown;}}StringBuilder result = new StringBuilder();for (String row : rows) {result.append(row);}return result.toString();}
}

复杂度分析如下:

时间复杂度:

  • String转换为char数组的时间复杂度是O(n),其中n为字符串s的长度。
  • 遍历字符数组并按规则放入对应行的时间复杂度是O(n)。
  • 将数组中的每个字符串连接起来的时间复杂度是O(numRows)。
  • 因此,总体时间复杂度为O(n)。

空间复杂度:

  • 创建了一个长度为numRows的字符串数组rows,所以额外的空间复杂度是O(numRows)。
  • 除此之外,没有使用其他额外的空间。
  • 因此,总体空间复杂度也是O(numRows)。

综上所述,该解法的时间复杂度和空间复杂度都是O(n),其中n为字符串s的长度。

LeetCode运行结果:

方法二:数学规律

除了模拟方法外,还可以使用数学规律来解决这个问题。

观察Z字形变换的规律,可以发现以下几个关键点:

  1. 第一行和最后一行中的字符之间的距离为周期性的,即间隔为2 * numRows - 2。
  2. 中间行的字符之间的距离有两个部分组成,一个是上方的字符与下方的字符之间的距离,为周期性的,间隔同样为2 * numRows - 2。另一个是斜对角方向的字符与当前字符之间的距离,为固定值,为2 * numRows - 2 - 2 * i,其中i为当前行的索引。
  3. 对于原始字符串中每个字符的位置,可以通过行索引和列索引来确定。

基于以上观察,可以直接计算每个字符在变换后字符串中的位置,然后将其按顺序放入结果字符串中。

class Solution {public String convert(String s, int numRows) {if (numRows == 1 || s.length() <= numRows) {return s;}StringBuilder result = new StringBuilder();int cycleLen = 2 * numRows - 2;int n = s.length();for (int i = 0; i < numRows; i++) {for (int j = 0; j + i < n; j += cycleLen) {result.append(s.charAt(j + i));if (i != 0 && i != numRows - 1 && j + cycleLen - i < n) {result.append(s.charAt(j + cycleLen - i));}}}return result.toString();}
}

复杂度分析如下:

时间复杂度:

  • 遍历每个字符并确定其位置的时间复杂度是O(n),其中n为字符串s的长度。
  • 在遍历过程中,对于每个字符,最多进行两次append操作。
  • 因此,总体时间复杂度仍然为O(n)。

空间复杂度:

  • 只使用了常数级别的额外空间,即StringBuilder中的空间。
  • 因此,空间复杂度是O(1)。

综上所述,使用数学规律的方法的时间复杂度和空间复杂度分别为O(n)和O(1),其中n为字符串s的长度。相比于模拟方法,这种方法在空间复杂度上有优势,因为不需要额外的数组来存储每一行的字符串。

LeetCode运行结果:

方法三:分组

除了前面介绍的方法,还可以使用分组方法来完成Z字形变换。

具体步骤如下:

  1. 创建一个长度为numRows的字符串数组rows,用来存储每一行的字符。
  2. 遍历原始字符串s,按照特定的分组规则将每个字符放入对应的分组中。
    • 第一组的长度为2 * numRows - 2。
    • 后续的每一组的长度也是2 * numRows - 2,但是每个字符在分组中的位置会有所不同。
      • 对于中间的行(行索引1到numRows-2),每个分组包含两个字符,分别位于当前行和其对称行中。
      • 对于首尾两行(行索引0和numRows-1),每个分组只包含一个字符,位于对应行中。
  3. 遍历完成后,将每一行的字符串按顺序拼接成最终的结果字符串。
class Solution {public String convert(String s, int numRows) {if (numRows == 1 || s.length() <= numRows) {return s;}String[] rows = new String[numRows];Arrays.fill(rows, "");int groupSize = 2 * numRows - 2;for (int i = 0; i < s.length(); i++) {int remain = i % groupSize;int row = remain < numRows ? remain : groupSize - remain;rows[row] += s.charAt(i);}StringBuilder result = new StringBuilder();for (String row : rows) {result.append(row);}return result.toString();}}

复杂度分析如下: 

  • 时间复杂度:

    • 遍历整个字符串s的时间复杂度为O(n)。
    • 将每个字符放入对应分组的时间复杂度为O(1)。
    • 因此,总的时间复杂度为O(n)。
  • 空间复杂度:

    • 创建了一个大小为numRows的字符串数组rows,因此空间复杂度为O(numRows) = O(n)。这里假设numRows远小于n,可以忽略。

LeetCode运行结果:

第三题

题目来源

7. 整数反转 - 力扣(LeetCode)

题目内容

解决方法

方法一:数学方法

要反转一个整数,可以使用数学方法。

具体步骤如下:

需要注意的是,该代码假设输入的整数为32位有符号整数。如果输入的整数超过了范围,或者溢出反转后的整数范围,将返回0。

  1. 初始化一个变量 res 用于存储反转后的整数。
  2. 进入循环,当原始整数不为0时,执行以下操作:
    • 通过取余运算获取原始整数的最后一位数字,保存在 digit 中。
    • 检查反转后的整数是否有可能溢出,如果溢出则返回0。具体的判断条件如下:
      • 如果 res 大于 Integer.MAX_VALUE / 10,或者当 res 等于 Integer.MAX_VALUE / 10 且 digit 大于7,则表示溢出,返回0。
      • 如果 res 小于 Integer.MIN_VALUE / 10,或者当 res 等于 Integer.MIN_VALUE / 10 且 digit 小于-8,则表示溢出,返回0。
    • 更新 res 的值,将 res 乘以10并加上 digit
    • 将原始整数除以10,以便获取下一位数字。
  3. 循环结束后,返回 res,即为反转后的整数。
class Solution {public int reverse(int x) {int res = 0;while (x != 0) {int digit = x % 10;if (res > Integer.MAX_VALUE / 10 || (res == Integer.MAX_VALUE / 10 && digit > 7)) {return 0;}if (res < Integer.MIN_VALUE / 10 || (res == Integer.MIN_VALUE / 10 && digit < -8)) {return 0;}res = res * 10 + digit;x /= 10;}return res;}
}

 复杂度分析如下: 

  • 这段代码的时间复杂度是 O(log|x|),其中 x 是输入的整数。在循环中,每次都会将原始整数除以10,因此循环的次数与输入的整数的位数相关。由于一个整数的位数大约为 log|x|(以10为底),所以循环的次数也大约为 log|x|。另外,在循环内部执行的操作包括取余运算、比较和乘法操作,这些操作的时间复杂度都可以忽略不计。因此,整体的时间复杂度可以近似地看作 O(log|x|)。
  • 空间复杂度为 O(1),因为只使用了常数个变量来存储结果和临时值,没有使用额外的数据结构。

LeetCode运行结果:

方法二:转换字符串

要实现整数反转的功能,可以按照以下步骤进行:

  1. 将输入的整数转换为字符串。
  2. 判断整数是否为负数,如果是负数,则将符号标记下来,并将整数转换为正数处理。
  3. 将字符串逆序排列。
  4. 将逆序后的字符串转换回整数。
  5. 如果原整数为负数,则将结果乘以-1。
class Solution {public int reverse(int x) {// 转换为字符串String str = Integer.toString(x);// 判断是否为负数boolean isNegative = false;if (str.charAt(0) == '-') {isNegative = true;str = str.substring(1); // 移除负号}// 逆序排列字符串StringBuilder sb = new StringBuilder(str);sb.reverse();String reversedStr = sb.toString();// 转换回整数long result = Long.parseLong(reversedStr);// 处理溢出情况if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {return 0;}// 处理负数if (isNegative) {result *= -1;}return (int)result;}
}

复杂度分析:

时间复杂度分析:

  • 转换为字符串:这个步骤的时间复杂度是O(log|x|),其中|x|是输入整数的绝对值。
  • 判断是否为负数:这个步骤的时间复杂度是O(1)。
  • 逆序排列字符串:使用StringBuilder的reverse方法,时间复杂度为O(log|x|)。
  • 将逆序后的字符串转换为长整型:使用Long.parseLong方法,时间复杂度同样为O(log|x|)。
  • 处理溢出情况、处理负数:这两个步骤的时间复杂度都是O(1)。
  • 返回结果:同样也是O(1)的时间复杂度。

综上所述,整体的时间复杂度可以视为O(log|x|)。

空间复杂度分析:

  • 字符串转换和逆序排列过程中会使用StringBuilder对象来构建字符串,所以它的空间复杂度为O(log|x|)。
  • 其他变量的空间复杂度是常数级的,不随输入规模变化。

因此,整体的空间复杂度可以视为O(log|x|)。

需要注意的是,这里的|x|是指输入整数的绝对值的位数。由于整数的位数在实际问题中通常是固定的,因此我们可以将该算法的时间复杂度和空间复杂度视为O(1)。

LeetCode运行结果:

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

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

相关文章

QT:使用行编辑器、文本编辑器、单选按钮、水平布局、垂直布局做一个小项目

widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QLineEdit> //行编辑器 #include <QTextEdit> //文本编辑器 #include <QRadioButton> //单选按钮class Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *pare…

USB总线-Linux内核USB3.0主机控制器驱动框架分析(十二)

1.概述 如下图所示&#xff0c;Linux内核中USB主机体系结构由五部分组成&#xff0c;分别为Application Software、USB Class Driver、USB Core(USB Driver)、USB Host Controller Driver、USB Host Controller。应用程序处于用户空间&#xff0c;通过系统调用访问Class Drive…

关于计算机找不到d3dx9_43.dll,无法继续执行代码修复方法

d3dx9_43.dll是一个动态链接库文件&#xff0c;它是DirectX的一个组件&#xff0c;主要用于处理游戏中的图形、声音等多媒体元素。当这个文件丢失时&#xff0c;可能会导致以下问题&#xff1a; 1. 游戏无法正常运行&#xff1a;由于d3dx9_43.dll负责处理游戏中的多媒体元素&a…

Jumpserver堡垒机

一、堡垒机概述 1、堡垒机的基本概念 堡垒机也是一台服务器&#xff0c;在一个特定的网络环境下&#xff0c;为了保障网络和数据不受来自外部和内部用户的入侵和破坏&#xff0c;而运用各种技术手段实时收集、监控网络环境中每一个组成部分&#xff08;服务器&#xff09;的系…

C进阶-数据的存储

数据类型介绍 内置类型&#xff1a; //数据类型中的内置类型 // char //字符数据类型 // short //短整型 // int //整型 // long //长整型 // long long //更长的整型 // float //单精度浮点数 // double //双精度浮点数 //数据类型中的内置类型 单位是字节 // char //字…

大厂面试之算法篇

目录 前言 算法对于前端来说重要吗&#xff1f; 期待你的答案 算法 如何学习算法 算法基础知识 时间复杂度 空间复杂度 前端 数据结构 数组 最长递增子序列 买卖股票问题 买卖股票之交易明细 硬币找零问题 数组拼接最小值 奇偶排序 两数之和 三数之和 四数之…

速码!!BGP最全学习笔记:IBGP和EBGP基本配置

实验1&#xff1a;配置IBGP和EBGP 实验目的 熟悉IBGP和EBGP的应用场景掌握IBGP和EBGP的配置方法 实验拓扑 想要华为数通配套实验拓扑和配置笔记的朋友们点赞关注&#xff0c;评论区留下邮箱发给你! 实验步骤 1.IP地址的配置 R1的配置 <Huawei>system-view …

Android之AMessage机制存/取原理(四十四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

Fiddler抓包工具配置+Jmeter基本使用

一、Fiddler抓包工具的配置和使用 在编写网关自动化脚本之前&#xff0c;得先学会如何抓包&#xff0c;这里以Fiddler为例。会抓包的同学可以跳过这一步&#xff0c;当然看看也是没坏处的…… 局域网络配置 将要进行抓包的手机与电脑连入同一局域网&#xff0c;电脑才能够抓到…

Elasticsearch(Es搜索(简单使用、全文查询、复合查询)、地理位置查询、特殊查询、聚合操作、桶聚合、管道聚合)

Elasticsearch&#xff08;三&#xff09;——Es搜索&#xff08;简单使用、全文查询、复合查询&#xff09;、地理位置查询、特殊查询、聚合操作、桶聚合、管道聚合 一、Es搜索 这里的 Es 数据博主自己上网找的&#xff0c;为了练习 Es 搜索。 1、Elasticsearch 搜索入门 …

阻塞队列-生产者消费者模型

阻塞队列介绍标准库阻塞队列使用基于阻塞队列的简单生产者消费者模型。实现一个简单型阻塞队列 &#xff08;基于数组实现&#xff09; 阻塞队列介绍 不要和之前学多线程的就绪队列搞混&#xff1b; 阻塞队列&#xff1a;也是一个队列&#xff0c;先进先出。带有特殊的功能 &…

PostgreSQL 技术内幕(十)WAL log 模块基本原理

事务日志是数据库的重要组成部分&#xff0c;记录了数据库系统中所有更改和操作的历史信息。 WAL log(Write Ahead Logging)也被称为xlog&#xff0c;是事务日志的一种&#xff0c;也是关系数据库系统中用于保证数据一致性和事务完整性的一系列技术&#xff0c;在数据库恢复、高…

若依前后端分离版搭建记录

一、如果是mysql8&#xff0c;得修改一下参数allowPublicKeyRetrieval为true&#xff0c;不然会报Public Key Retrieval is not allowed错误&#xff1a; 二、导入第二张表的数据库的时候&#xff0c;需要增加“--default-character-setutf8”参数才不会报错&#xff1a;

硕士应聘大专老师

招聘信息 当地人社局、学校&#xff08;官方&#xff09; 公众号&#xff08;推荐&#xff09;&#xff1a; 辅导员招聘 厦门人才就业信息平台 高校人才网V 公告出完没多久就要考试面试&#xff0c;提前联系当地院校&#xff0c;问是否招人。 校招南方某些学校会直接去招老师。…

DL2:A Deep Learning-Driven Scheduler for Deep Learning Clusters 阅读思考+组会

IEEE Transactions on Parallel and Distributed Systems CCF A 提问题记录 1、自己提出的问题 1.1 这篇文章解决的主要问题是什么&#xff0c;怎么理解&#xff1f; 传统的调度方法具有如下特点&#xff1a; 要么无法感知机器学习工作负载特性(如集群中的GPU的利用率)或ML…

Vue中的插槽--组件复用,内容自定义

插槽 文章目录 插槽插槽-默认插槽插槽-后备内容&#xff08;设置默认值&#xff09;插槽-具名插槽插槽–作用域插槽 插槽-默认插槽 作用&#xff1a;让组件内部的一些结构支持自定义 需求&#xff1a;要在页面中显示一个对话框,封装成一个组件&#xff08;对话框有很多功能是类…

antd/fusion表格增加圈选复制功能

背景介绍 我们存在着大量在PC页面通过表格看数据业务场景&#xff0c;表格又分为两种&#xff0c;一种是 antd / fusion 这种基于 dom 元素的表格&#xff0c;另一种是通过 canvas 绘制的类似 excel 的表格。 基于 dom 的表格功能丰富较为美观&#xff0c;能实现多表头、合并…

Spring之bean的生命周期源码解析

Spring最重要的功能就是帮助程序员创建对象&#xff08;也就是IOC&#xff09;&#xff0c;而启动Spring就是为创建Bean对象做准备&#xff0c;所以我们先明白Spring到底是怎么去创建Bean的&#xff0c;也就是先弄明白Bean的生命周期。 Bean的生命周期就是指&#xff1a;在Spr…

Nodejs 相关知识

Nodejs是一个js运行环境&#xff0c;可以让js开发后端程序&#xff0c;实现几乎其他后端语言实现的所有功能&#xff0c;能够让js与其他后端语言平起平坐。 nodejs是基于v8引擎&#xff0c;v8是Google发布的开源js引擎&#xff0c;本身就是用于chrome浏览器的js解释部分&#…

帆软FineReport决策报表之页面布局

最近在用帆软决策报表绘制首页大屏&#xff0c;记录使用过程&#xff0c;方便查看。 版本&#xff1a;FineReport10.0 第一步、页面布局 页面布局其实就是组件的排列组合&#xff0c;决策报表主区域body有两种布局方式&#xff1a;自适应布局和绝对布局。 1&#xff09;自适应…