怒刷LeetCode的第24天(Java版)

news2024/11/20 12:37:27

目录

第一题

题目来源

题目内容

解决方法

方法一:反向遍历

方法二:字符串操作函数

方法三:正则表达式

第二题

题目来源

题目内容

解决方法

方法一:模拟

方法二:递归

方法三:迭代

方法四:数学规律

第三题

题目来源

题目内容

解决方法

方法一:回溯算法

方法二:迭代


第一题

题目来源

58. 最后一个单词的长度 - 力扣(LeetCode)

题目内容

解决方法

方法一:反向遍历

具体的思路是:

  1. 先去除字符串两端的空格,确保字符串没有多余的空格。

  2. 从字符串的最后开始向前遍历,找到第一个非空格字符的位置。

  3. 继续向前遍历,直到遇到空格字符或者到达字符串的开头,记录下遍历过程中的字符数。

  4. 返回记录的字符数,即为最后一个单词的长度。

class Solution {
public int lengthOfLastWord(String s) {
    // 去除字符串两端的空格
    s = s.trim();

    // 遍历字符串,找到最后一个单词的长度
    int length = 0;
    for (int i = s.length() - 1; i >= 0; i--) {
        if (s.charAt(i) == ' ') {
            break;
        }
        length++;
    }

    return length;
}
}

复杂度分析:

时间复杂度分析:

  • 字符串去除两端空格的操作的时间复杂度是 O(n),其中 n 是字符串的长度。
  • 从字符串的最后开始向前遍历,直到找到最后一个单词的长度,最坏情况下需要遍历整个字符串,时间复杂度也是 O(n)。 因此,总的时间复杂度为 O(n)。

空间复杂度分析:

  • 代码中没有使用任何额外的数据结构,只使用了常数级别的额外空间。 因此,空间复杂度为 O(1)。

综上所述,该算法的时间复杂度为 O(n),空间复杂度为 O(1)。

LeetCode运行结果:

方法二:字符串操作函数

除了上述的方法外,还可以使用Java内置的字符串操作函数来解决这个问题。具体的思路是:

  1. 先去除字符串两端的空格,确保字符串没有多余的空格。

  2. 使用Java的 split() 函数将字符串按照空格分割成多个单词,并保存在一个字符串数组中。

  3. 如果字符串数组不为空,则最后一个单词即为数组中的最后一个元素。

  4. 返回最后一个单词的长度。

class Solution {
public int lengthOfLastWord(String s) {
    // 去除字符串两端的空格
    s = s.trim();

    // 分割字符串并获取最后一个单词的长度
    String[] words = s.split(" ");
    if (words.length == 0) {
        return 0;
    }
    return words[words.length - 1].length();
}

}

复杂度分析:

时间复杂度分析:

  • 字符串去除两端空格的操作的时间复杂度是 O(n),其中 n 是字符串的长度。
  • split() 函数的时间复杂度取决于字符串的长度和分隔符的数量。在这里,分隔符是空格,因此最坏情况下需要遍历整个字符串一次,并且需要额外的时间将结果存储到数组中。所以,split() 函数的时间复杂度为 O(n)。
  • 获取最后一个单词的长度只需要常数时间。 因此,总的时间复杂度为 O(n)。

空间复杂度分析:

  • 代码中使用了一个字符串数组来存储分割后的单词,数组的大小取决于字符串中单词的数量。在最坏情况下,单词的数量与字符串的长度相当,因此空间复杂度为 O(n)。
  • 另外,还需要额外的空间存储去除两端空格后的字符串。 综上所述,总的空间复杂度为 O(n)。

综上所述,该算法的时间复杂度为 O(n),空间复杂度为 O(n)。

LeetCode运行结果:

方法三:正则表达式

还可以使用正则表达式来解决这个问题。具体的思路是:

  1. 使用正则表达式 \\s+ 将字符串以空格作为分隔符拆分成多个单词。
  2. 如果拆分后的单词数组为空,说明字符串中没有单词,直接返回 0。
  3. 如果不为空,则取最后一个单词并返回其长度。
class Solution {
public int lengthOfLastWord(String s) {
    String[] words = s.split("\\s+");
    if (words.length == 0) {
        return 0;
    }
    String lastWord = words[words.length - 1];
    return lastWord.length();
}
}

复杂度分析:

  • 使用正则表达式的做法,时间复杂度为 O(n),其中 n 是字符串的长度。需要将整个字符串拆分成多个单词,同时只需要遍历一次。
  • 空间复杂度为 O(k),其中 k 是字符串中单词的数量。需要用数组存储拆分后的单词,因此空间复杂度取决于单词的数量。

LeetCode运行结果:

第二题

题目来源

59. 螺旋矩阵 II - 力扣(LeetCode)

题目内容

解决方法

方法一:模拟

这道题可以使用模拟的方法来生成螺旋矩阵。具体的步骤如下:

  1. 初始化一个空的 n x n 矩阵 matrix。

  2. 定义四个变量 topbottomleftright,分别表示当前螺旋轮廓的上边界、下边界、左边界和右边界。

  3. 初始化变量 num 为 1,表示当前要填入的数字。

  4. 进行循环,当 num 小于等于 n 的平方时,进行以下操作:

    • 从左到右遍历上边界,将 num 填入 matrix[top][i],并将 num 自增 1。

    • 上边界下移一行。

    • 若上边界超出下边界,则结束循环。

    • 从上到下遍历右边界,将 num 填入 matrix[i][right],并将 num 自增 1。

    • 右边界左移一列。

    • 若右边界超出左边界,则结束循环。

    • 从右到左遍历下边界,将 num 填入 matrix[bottom][i],并将 num 自增 1。

    • 下边界上移一行。

    • 若下边界超出上边界,则结束循环。

    • 从下到上遍历左边界,将 num 填入 matrix[i][left],并将 num 自增 1。

    • 左边界右移一列。

    • 若左边界超出右边界,则结束循环。

  5. 返回生成的螺旋矩阵 matrix。

class Solution {
public int[][] generateMatrix(int n) {
    int[][] matrix = new int[n][n];
    int top = 0, bottom = n - 1, left = 0, right = n - 1;
    int num = 1;

    while (num <= n * n) {
        for (int i = left; i <= right; i++) {
            matrix[top][i] = num++;
        }
        top++;
        if (top > bottom) {
            break;
        }

        for (int i = top; i <= bottom; i++) {
            matrix[i][right] = num++;
        }
        right--;
        if (right < left) {
            break;
        }

        for (int i = right; i >= left; i--) {
            matrix[bottom][i] = num++;
        }
        bottom--;
        if (bottom < top) {
            break;
        }

        for (int i = bottom; i >= top; i--) {
            matrix[i][left] = num++;
        }
        left++;
        if (left > right) {
            break;
        }
    }

    return matrix;
}

}

复杂度分析:

  • 对于给定的整数 n,我们需要填充 n^2 个元素到螺旋矩阵中。因此,时间复杂度为 O(n^2)。
  • 在空间复杂度方面,我们使用了一个 n x n 的矩阵来保存结果。因此,空间复杂度也为 O(n^2)。

综上所述,该算法的时间复杂度和空间复杂度均为 O(n^2)。

LeetCode运行结果:

方法二:递归

除了模拟法之外,还可以使用递归的方法来生成螺旋矩阵。

具体的思路是,每次递归生成最外层的螺旋轮廓,并将其剥离,然后对剩余的内部矩阵进行递归生成。直到矩阵为空或只剩下一个元素时结束递归。

class Solution {
public int[][] generateMatrix(int n) {
    int[][] matrix = new int[n][n];
    generateMatrix(matrix, 0, n - 1, 1);
    return matrix;
}

private void generateMatrix(int[][] matrix, int start, int end, int num) {
    if (start > end) {
        return;
    }

    // 生成最外层的螺旋轮廓
    for (int i = start; i <= end; i++) {
        matrix[start][i] = num++;
    }
    for (int i = start + 1; i <= end; i++) {
        matrix[i][end] = num++;
    }
    for (int i = end - 1; i >= start; i--) {
        matrix[end][i] = num++;
    }
    for (int i = end - 1; i > start; i--) {
        matrix[i][start] = num++;
    }

    // 递归生成内部矩阵
    generateMatrix(matrix, start + 1, end - 1, num);
}

}

复杂度分析:

  • 由于递归方法每次递归都会生成最外层的螺旋轮廓,并将其剥离,因此矩阵中的每个元素都会被遍历一次,时间复杂度为 O(n^2)。
  • 在空间复杂度方面,由于递归方法并不需要额外的空间来存储状态,因此仅需要使用一个 n x n 的矩阵来保存结果。因此,空间复杂度也为 O(n^2)。

综上所述,该算法的时间复杂度和空间复杂度均为 O(n^2)。

LeetCode运行结果:

方法三:迭代

除了模拟和递归之外,还可以使用迭代的方法来生成螺旋矩阵。该方法使用四个变量表示当前要填入的数字、当前螺旋轮廓的上、下、左、右边界,并按照规律依次填入数字。

class Solution {
public int[][] generateMatrix(int n) {
    int[][] matrix = new int[n][n];
    int num = 1;
    int top = 0, bottom = n - 1, left = 0, right = n - 1;

    while (num <= n * n) {
        // 从左到右填入上边界
        for (int i = left; i <= right; i++) {
            matrix[top][i] = num++;
        }
        top++;

        // 从上到下填入右边界
        for (int i = top; i <= bottom; i++) {
            matrix[i][right] = num++;
        }
        right--;

        // 从右到左填入下边界
        for (int i = right; i >= left; i--) {
            matrix[bottom][i] = num++;
        }
        bottom--;

        // 从下到上填入左边界
        for (int i = bottom; i >= top; i--) {
            matrix[i][left] = num++;
        }
        left++;
    }

    return matrix;
}


}

复杂度分析:

对于迭代方法来说,时间复杂度和空间复杂度仍然为O(n^2)。

  • 由于需要遍历每个元素,并填入正确的数字,时间复杂度为O(n^2)。
  • 在空间复杂度方面,仅需要使用一个 n x n 大小的矩阵来保存结果,因此空间复杂度也为O(n^2)。

综上所述,迭代方法的时间复杂度和空间复杂度均为O(n^2)。

LeetCode运行结果:

方法四:数学规律

除了模拟、递归和迭代之外,还可以使用数学规律的方法来生成螺旋矩阵。

在这种方法中,可以将生成螺旋矩阵的过程看作是按层进行填充的过程。首先确定每一层的起始位置和结束位置,并根据数学规律逐步填入数字。

class Solution {
public int[][] generateMatrix(int n) {
    int[][] matrix = new int[n][n];
    int num = 1;
    int startRow = 0, endRow = n - 1, startCol = 0, endCol = n - 1;

    while (startRow <= endRow && startCol <= endCol) {
        // 填充当前层的上边界
        for (int i = startCol; i <= endCol; i++) {
            matrix[startRow][i] = num++;
        }
        startRow++;

        // 填充当前层的右边界
        for (int i = startRow; i <= endRow; i++) {
            matrix[i][endCol] = num++;
        }
        endCol--;

        if (startRow <= endRow) {
            // 填充当前层的下边界
            for (int i = endCol; i >= startCol; i--) {
                matrix[endRow][i] = num++;
            }
            endRow--;
        }

        if (startCol <= endCol) {
            // 填充当前层的左边界
            for (int i = endRow; i >= startRow; i--) {
                matrix[i][startCol] = num++;
            }
            startCol++;
        }
    }

    return matrix;
}

}

复杂度分析:

对于数学规律方法来说,时间复杂度和空间复杂度仍然为O(n^2)。

  • 由于需要遍历每个元素,并填入正确的数字,时间复杂度为O(n^2)。
  • 在空间复杂度方面,仅需要使用一个 n x n 大小的矩阵来保存结果,因此空间复杂度也为O(n^2)。

综上所述,数学规律方法的时间复杂度和空间复杂度均为O(n^2)。

LeetCode运行结果:

第三题

题目来源

60. 排列序列 - 力扣(LeetCode)

题目内容

解决方法

方法一:回溯算法

题目要求按照大小顺序列出所有排列情况,并找出第k个排列。

我们可以使用回溯算法来解决这个问题。具体步骤如下:

  1. 创建一个布尔数组used,用于标记数字是否已经被使用过。
  2. 创建一个字符串permutation,用于保存当前的排列结果。
  3. 创建一个整数count,用于计数当前的排列序号。
  4. 定义递归函数backtrack,参数为当前处理的数字num和目标排列的长度n
    • 如果num等于n,表示已经生成了一个完整的排列,此时count加一。
      • 如果count等于k,说明已经找到了第k个排列,将permutation作为结果返回。
    • 遍历数字1n
      • 如果当前数字没有被使用过(即used[i]false),则将其加入到permutation中,并将used[i]标记为true,然后递归调用backtrack(num + 1, n)
        • 如果得到了结果,直接返回结果。
      • 回溯:将当前数字从permutation中移除,并将used[i]标记为false
  5. 返回空字符串作为结果。
class Solution {
    public String getPermutation(int n, int k) {
        boolean[] used = new boolean[n + 1];
        StringBuilder permutation = new StringBuilder();
        int[] count = new int[1];

        backtrack(0, n, k, used, permutation, count);

        return permutation.toString();
    }

    private boolean backtrack(int num, int n, int k, boolean[] used, StringBuilder permutation, int[] count) {
        if (num == n) {
            count[0]++;
            if (count[0] == k) {
                return true;
            }
            return false;
        }

        for (int i = 1; i <= n; i++) {
            if (!used[i]) {
                permutation.append(i);
                used[i] = true;

                if (backtrack(num + 1, n, k, used, permutation, count)) {
                    return true;
                }

                permutation.deleteCharAt(permutation.length() - 1);
                used[i] = false;
            }
        }

        return false;
    }
}

复杂度分析:

设n为给定数字的大小。

  • 时间复杂度分析:回溯过程中,我们需要找到第k个排列,因此最坏情况下需要生成所有的n!个排列。每个排列的生成需要O(n)的时间,因此总的时间复杂度为O(n * n!)。
  • 空间复杂度分析:回溯过程中,我们使用了一个布尔数组used、一个字符串permutation和一个整数count来保存状态和结果。其中,布尔数组used的空间复杂度为O(n),字符串permutation的空间复杂度为O(n),整数count的空间复杂度为O(1)。因此总的空间复杂度为O(n)。

综上所述,该算法的时间复杂度为O(n * n!),空间复杂度为O(n)。由于n的范围限制为1 <= n <= 9,因此算法的运行时间是可以接受的。

LeetCode运行结果:

方法二:迭代

除了回溯算法,我们还可以使用迭代的思路来解决这个问题。

该方法首先通过迭代生成了数字列表和阶乘数组,然后进行迭代过程来计算每一位上的数字,并将其加入到结果中,直到得到第k个排列。

class Solution {
    public String getPermutation(int n, int k) {
        // 初始化数字列表和阶乘数组
        List<Integer> nums = new ArrayList<>();
        int[] factorials = new int[n+1];
        factorials[0] = 1;
        for (int i = 1; i <= n; i++) {
            nums.add(i);
            factorials[i] = factorials[i-1] * i;
        }

        // k需要减一,方便对索引的计算
        k--;

        StringBuilder sb = new StringBuilder();
        for (int i = n; i >= 1; i--) {
            int index = k / factorials[i-1]; // 当前位上的数字在数字列表中的索引
            sb.append(nums.remove(index)); // 将当前位上的数字加入到结果中
            k %= factorials[i-1]; // 更新k
        }

        return sb.toString();
    }
}

复杂度分析:

时间复杂度分析:

  • 计算阶乘数组:需要对数字从 1 到 n 进行遍历,所以时间复杂度为 O(n)。
  • 迭代过程:需要进行 n 次迭代,每次迭代的时间复杂度为 O(n),因为要遍历剩余数字列表来确定当前位上的数字。所以总的时间复杂度为 O(n^2)。

空间复杂度分析:

  • 存储阶乘数组:阶乘数组长度为 n+1,所以空间复杂度为 O(n)。

综上所述,该算法的时间复杂度为 O(n^2),空间复杂度为 O(n)。

LeetCode运行结果:

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

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

相关文章

VS Code更改软件的语言

刚刚安装好的 vscode 默认是英文&#xff0c;可以安装中文扩展包。如图&#xff1a; 重启即可更换为中文。 如果想切换为英文&#xff0c;可以 Ctrl Shift P&#xff0c;打开命令面板。 输入 Configure DIsplay Language&#xff0c;如图&#xff1a; 可以在中英文之间切换…

【C语言】什么是宏定义?(#define详解)

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:C语言 ⚙️操作环境:Visual Studio 2022 ​ 目录 一.什么是宏定义 二.宏定义的组成 第1部分 第2部分 第3部分 三.宏定义的应用 &#x1f38f;类对象宏 &#x1f38f;类函数宏 1.求两个数中的较大值 2.求一个数的…

【短文】在Linux中怎么查看文件信息

2023年10月6日&#xff0c;周五晚上 ls -l filename 通过这条命令可以简略地查看文件信息 stat filename 通过这条命令可以详细地查看文件信息

NFS 原理和配置

NFS 原理介绍 NFS network file system 网络文件系统 基于RPC协议&#xff0c;RPC remote procedure call 。 RPC存在的意义在于解决NFS服务端和客户端通信多端口并且端口不固定的问题。因为NFS的服务端和客户端通信的时候&#xff0c;并不是只有一个端口&#xff…

【云计算网络安全】DDoS 缓解解析:DDoS 攻击缓解策略、选择最佳提供商和关键考虑因素

文章目录 一、前言二、什么是 DDoS 缓解三、DDoS 缓解阶段四、如何选择 DDoS 缓解提供商4.1 网络容量4.2 处理能力4.3 可扩展性4.4 灵活性4.5 可靠性4.6 其他考虑因素4.6.1 定价4.6.2 所专注的方向 文末送书《数据要素安全流通》本书编撰背景本书亮点本书主要内容 一、前言 云…

电脑提示MSVCP100.dll丢失错误怎么解决?分享四个解决方法帮你搞定

在平时我们使用电脑中&#xff0c;经常会遇到各种问题&#xff0c;比如msvcp100.dll文件丢失&#xff0c;那这个msvcp100.dll文件丢失需要怎么修复解决呢&#xff1f;和msvcp100.dll为什么会丢失呢&#xff0c;下面我一点点为大家解答与介绍解决msvcp100.dll丢失问题的方法。 一…

什么,这年头还有人不知道404

写在前面 哥&#xff0c;来帮我看看&#xff0c;这个请求怎么404了&#xff0c;明明接口路径是对的啊&#xff01;一个下午&#xff0c;组里的小哥突然让我帮忙看这个问题&#xff0c;我不禁一惊&#xff0c;啥&#xff0c;这年头了还有人搞不定404&#xff0c;如有还有&#…

【二】spring boot-设计思想

spring boot-设计思想 简介&#xff1a;现在越来越多的人开始分析spring boot源码&#xff0c;拿到项目之后就有点无从下手了&#xff0c;这里介绍一下springboot源码的项目结构 一、项目结构 从上图可以看到&#xff0c;源码分为两个模块&#xff1a; spring-boot-project&a…

最强的电脑/手机/汽车/机器人芯片-2023

车规级芯片、手机芯片、电脑芯片比较_汽车芯片和电脑芯片的区别-CSDN博客 全文资源来源网络。 电脑&#xff1a; 图片引用。 CPU 基准测试性能层次结构根据性能对当前和上一代英特尔和 AMD 处理器进行排名&#xff0c;包括所有最适合游戏的 CPU。在 CPU 排名图表和表格下方&…

2023年【安全员-A证】报名考试及安全员-A证免费试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 安全员-A证报名考试考前必练&#xff01;安全生产模拟考试一点通每个月更新安全员-A证免费试题题目及答案&#xff01;多做几遍&#xff0c;其实通过安全员-A证作业考试题库很简单。 1、【多选题】2014年2月&#xff…

【亲测有效】C盘容量满了,给C盘扩容!!!

前言 相信有很多小伙伴用自己电脑的时候明明不往C盘装东西&#xff0c;但是C盘还是慢慢的变红了&#xff0c;我也是因为C盘满了而备受困扰。又不知道如何解决或者怕自己鼓捣着磁盘数据没了。闲来无事&#xff0c;我查了一些资料&#xff0c;终于将我的C盘容量扩充了且数据保存…

k8s-9 ingress-nginx

nodeport 默认端口 nodeport默认端口是30000-32767&#xff0c;超出会报错 添加如下参数&#xff0c;端口范围可以自定义 externalname ingress-nginx 通过一个外部的vip 地址 访问到集群内的多个service 一种全局的、为了代理不同后端 Service 而设置的负载均衡服务&…

FLASH模拟EEPROM

STM32本身没有自带EEPROM&#xff0c;但是STM32具有IAP&#xff08;在应用编程&#xff09;功能&#xff0c;所以可以把它的FLASH当做EEPROM来使用。 STM32 FLASH简介 不同型号的STM32&#xff0c;其FLASH容量也有所不同&#xff0c;最大的达到1024K字节。 MiniSTM32开发板选…

打破思维局限性,产品背景、需求、功能实现逻辑手拿把掐!

在一个完整的测试流程中&#xff0c;测试用例是很核心的一个产出物。一份优秀的测试用例&#xff0c;能确保软件产品质量的可控。 但由于每个人思维局限性&#xff0c;对产品背景、需求、功能实现逻辑等理解深度不一致&#xff0c;编写的测试用例或多或少存在一些遗漏点&#…

C/C++学习 -- SHA-256算法

SHA-256算法概述 SHA-256代表"Secure Hash Algorithm 256-bit"&#xff0c;是一种安全的哈希算法&#xff0c;输出固定长度的256位&#xff08;32字节&#xff09;哈希值。SHA-256被广泛用于加密、数字签名、密码学以及区块链等领域&#xff0c;因为它提供了高度的安…

小程序如何关联视频号小店,实现商品同步

​随着短视频平台的兴起&#xff0c;视频号小店成为了很多商家推广产品和服务的新渠道。下面介绍如何将小程序与视频号小店关联起来&#xff0c;实现商品的同步。 1. 关联视频号小店。在小程序管理员后台->营销管理->视频号小店页面&#xff0c;点击双向箭头&#xff0c…

STM32+USB3300复位枚举异常的问题

关键字&#xff1a;STM32F4&#xff0c;STM32H7&#xff0c;USB3300&#xff0c;USBHS&#xff0c;Reset复位 F4和H7用的都是DWC2的USBIP&#xff0c;我的板子上3300单片机工作的很好&#xff0c;插入枚举一切正常&#xff0c;但是设备收到上位机的复位命令后&#xff0c;单片…

【Java 进阶篇】使用 JDBCTemplate 执行 DML 语句详解

JDBCTemplate 是 Spring 框架中的一个核心模块&#xff0c;用于简化 JDBC 编程&#xff0c;使数据库操作更加便捷和高效。在本文中&#xff0c;我们将重点介绍如何使用 JDBCTemplate 执行 DML&#xff08;Data Manipulation Language&#xff09;语句&#xff0c;包括插入、更新…

面试题:你是如何计划和组织一个大型的软件测试项目的?

今天我们讲个软件测试的面试问题&#xff1a;你是如何计划和组织一个大型的软件测试项目的&#xff1f; 这种题目&#xff0c;就是看你的流程梳理&#xff0c;一定要在回答的步骤前面加上1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;自己就能很清晰&#xff0c;面试…

程序员如何从容地面对裁员?我有6个小建议

2023年3月&#xff0c;世界银行发布了一份题为《长期下行的增长前景&#xff1a;趋势、期望和政策》的报告&#xff0c;首次全面评估了未来全球的经济发展趋势。报告描述的趋势令人担忧&#xff1a;推动过去三十年进步和繁荣的所有经济力量几乎都在消退 2022年至2030年的全球潜…