怒刷LeetCode的第3天(Java版)

news2025/1/12 19:04:37

目录

第一题

题目来源

题目内容

解决方法

方法一:动态规划

第二题

题目来源

题目内容

解决方法

方法一:模拟

方法二:数学规律

方法三:分组

第三题

题目来源

题目内容

解决方法

方法一:数学方法

方法二:转换字符串


第一题

题目来源

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.coloradmin.cn/o/1016939.html

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

相关文章

001-项目介绍

项目介绍 文章目录 项目介绍编写目的小小说明 项目介绍目前状态目录项目介绍第一代第二代第三代软件部署硬件篇 总结 关键字&#xff1a; Qt、 Qml、 分享、 记录、 目录 编写目的 这是我目前参与的一个真实项目&#xff0c;而且我非常幸运地能够从头到尾地参与其中。在面…

微信小程序|自定义弹窗组件

目录 引言小程序的流行和重要性自定义弹出组件作为提升用户体验和界面交互的有效方式什么是自定义弹出组件自定义弹出组件的概念弹出层组件在小程序中的作用和优势为什么需要自定义弹出组件现有的标准弹窗组件的局限性自定义弹出组件在解决这些问题上的优势最佳实践和注意事项避…

Shell脚本编写:从零到精通

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

C#-WinForm-发送邮件

登录QQ邮箱——设置——开启“POP3/SMTP服务” 登陆QQ邮箱→打开设置→开启“POP3/SMTP服务”&#xff0c;获取“授权码” 简单总结一下&#xff1a; 1、使用SmtpClient发送电子邮件是很简单的&#xff0c;只要正确创建了MailMessage对象和SmtpClient就可以很容易的发送出去电…

Mybatis-Plus入门(1)

单表的CRUD功能代码重复度很高&#xff0c;也没有什么难度。而这部分代码量往往比较大&#xff0c;开发起来比较费时。因此&#xff0c;目前企业中都会使用一些组件来简化或省略单表的CRUD开发工作。目前在国内使用较多的一个组件就是MybatisPlus. 官方网站如下&#xff1a; 简…

超级好用绘图工具(Draw.io+Github)

超级好用绘图工具&#xff08;Draw.ioGithub&#xff09; 方案简介 绘图工具&#xff1a;Draw.io 存储方式&#xff1a; Github 1 Draw.io 1.2 简介 ​ 是一款免费开源的在线流程图绘制软件&#xff0c;可以用于创建流程图、组织结构图、网络图、UML图等各种类型的图表。…

【面试题】forEach能跳出循环吗?

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 【国庆头像】- 国庆爱国 程序员头像&#xff01;总有一款适合你&#xff01; 如果面试官&#xff0c;或者有人问你foreach怎么跳出循环&#xff0c;请你…

LeetCode 2596. 检查骑士巡视方案

【LetMeFly】2596.检查骑士巡视方案 力扣题目链接&#xff1a;https://leetcode.cn/problems/check-knight-tour-configuration/ 骑士在一张 n x n 的棋盘上巡视。在有效的巡视方案中&#xff0c;骑士会从棋盘的 左上角 出发&#xff0c;并且访问棋盘上的每个格子 恰好一次 。…

关于感恩教师的演讲稿格式及范例

关于感恩教师的演讲稿格式及范例 感恩教师的演讲稿格式应该是&#xff1a;开头感谢听众&#xff0c;正文部分根据题目内容书写&#xff0c;结尾部分再次感谢听众。 以下是一篇关于感恩教师的演讲稿的例子&#xff1a; 尊敬的老师&#xff0c;亲爱的同学们&#xff1a; 大家好…

循环结构在反汇编中特征

本文将使用IDA分析C语言中循环结构(do while&#xff0c;while&#xff0c;for)在反汇编中的特征 目录 IDA分析 do whhile 循环 IDA分析 while 循环 IDA分析 for 循环 do while while和for哪个效率高 IDA分析 do whhile 循环 测试代码 #include <stdio.h> int main…

基于SSM框架的《超市订单管理系统》Web项目开发(第二天)完成登录模块和用户退出模块

《超市订单管理系统》&#xff08;第二天&#xff09; 基于SSM框架的Web项目开发 ​ 昨天我们实现了登录功能&#xff0c;但是用的是模拟数据。今天我们要链接数据库整合SpirngMybatis&#xff0c;读取数据库中的真实数据&#xff0c;用来跟我们输入的userCode和userPassword进…

iText实战--根据绝对位置添加内容

3.1 direct content 概念简介 pdf内容的4个层级 层级1&#xff1a;在text和graphics底下&#xff0c;PdfWriter.getDirectContentUnder() 层级2&#xff1a;graphics层&#xff0c;Chunk, Images背景&#xff0c;PdfPCell的边界等 层级3&#xff1a;text层&#xff0c;Chun…

2023年商会研究报告

第一章 行业发展概况 1.1 定义和功能 商会&#xff0c;通常被称为商业协会或商业会所&#xff0c;是由具有相似的行业、商业、贸易、专业或地理背景的企业和商家所组成的组织。这些组织的核心目标是促进其会员之间的交流、合作和互助&#xff0c;进而推动相关行业或商业领域的…

Docker Swarm集群部署

Docker Swarm集群部署 任务平台 3台虚拟机&#xff0c;一台作为manager 节点&#xff0c;另两台作为work节点。 文章目录 Docker Swarm集群部署安装docker配置防火墙开放端口在 manager 节点创建 Swarm 集群创建用于swarm服务的自定义的overlay网络测试跨主机容器通信 安装do…

Python教程:@符号的用法

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ python源码、视频教程、插件安装教程、资料我都准备好了&#xff0c;直接在文末名片自取就可 符号在 Pyth…

LLC谐振变换器软启动过程分析与问题处理

启动步骤 1.使用Burst模式升压至200V—稳定的充电5S钟&#xff0c;保证所有电容完全充满。 Burst模式过程&#xff1a;1.开启一次脉冲发送–>判断母线电压大小&#xff0c;确定下次启动脉冲的时间档位–>连续启停控制–>不断给电容充电–>进入200V稳定充电状态–…

Acwing.240 食物链(并查集)

题目 动物王国中有三类动物A,B,C&#xff0c;这三类动物的食物链构成了有趣的环形。A吃B&#xff0c;B吃C&#xff0c;C吃A。 现有N个动物&#xff0c;以1–N编号。 每个动物都是A,B,C中的一种&#xff0c;但是我们并不知道它到底是哪一种。有人用两种说法对这N个动物所构 成…

深度融入垂直行业是物联网未来发展必由之路

三年疫情&#xff0c;打断了很多企业的发展进程。但是疫情已过似乎整个业界生态有了一个很大变化。有一个朋友前一段时间参加深圳电子展后有一个感悟&#xff0c;说的很好&#xff1a;“疫情后有很大变化&#xff0c;疫情后&#xff0c;整个环境状态和疫情前有很大不同。无论企…

opencv练习-案例

import cv2 as cv import numpy as np from matplotlib import pyplot as plt %matplotlib inline图像分割是计算机将图像分割成多个区域的过程 使用阈值分割图像&#xff0c;产生两个区域 打开图像文件 img cv.imread(snake.png,cv.IMREAD_COLOR) gray cv.cvtColor(img,c…

OmniShade - Mobile Optimized Shader

OmniShade Pro是一款专为移动设备设计的高性能着色器。它包含多种技术,使其几乎可以实现从现实到卡通到动漫的任何外观,但由于自适应系统仅计算任何功能集所需的内容,它的速度也非常快。 它旨在弥合Unity的标准着色器和移动着色器之间的差距,但由于其高级别的风格化、组合…