首页 > 其他分享 >LeetCode题练习与总结:移掉 K 位数字--402

LeetCode题练习与总结:移掉 K 位数字--402

时间:2024-11-17 22:48:04浏览次数:3  
标签:数字 -- 复杂度 栈顶 num 402 字符串 移掉 stack

一、题目描述

给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。

 

示例 1 :

输入:num = "1432219", k = 3
输出:"1219"
解释:移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219 。

示例 2 :

输入:num = "10200", k = 1
输出:"200"
解释:移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。

示例 3 :

输入:num = "10", k = 2
输出:"0"
解释:从原数字移除所有的数字,剩余为空就是 0 。

提示:

  • 1 <= k <= num.length <= 10^5
  • num 仅由若干位数字(0 - 9)组成
  • 除了 0 本身之外,num 不含任何前导零

二、解题思路

这个问题可以通过贪心算法和栈来解决。我们希望剩下的数字尽可能小,因此我们应该从左到右扫描数字,并且尽可能地保留较小的数字。具体步骤如下:

  1. 使用一个栈来保存最终的数字。
  2. 遍历输入的字符串数字。
  3. 对于当前数字,如果它小于栈顶元素,并且我们可以移除更多的数字(即 k > 0),那么我们就移除栈顶元素。这样可以保证栈中的数字始终是递增的,从而保证最后得到的数字是最小的。
  4. 如果当前数字大于或等于栈顶元素,或者 k 为 0,则将当前数字压入栈中。
  5. 遍历完成后,如果 k 仍然大于 0,则从栈顶移除额外的 k 个数字。
  6. 将栈中的数字转换为字符串,并去除前导零。
  7. 如果栈为空,则返回 “0”。

三、具体代码

import java.util.Stack;

class Solution {
    public String removeKdigits(String num, int k) {
        Stack<Character> stack = new Stack<>();
        for (char c : num.toCharArray()) {
            // 当栈不为空,k大于0,并且栈顶元素大于当前元素时,弹出栈顶元素
            while (!stack.isEmpty() && k > 0 && stack.peek() > c) {
                stack.pop();
                k--;
            }
            // 当前字符不为'0'或者栈不为空时,将当前字符入栈
            if (c != '0' || !stack.isEmpty()) {
                stack.push(c);
            }
        }
        
        // 如果k还大于0,继续弹出栈顶元素
        while (!stack.isEmpty() && k > 0) {
            stack.pop();
            k--;
        }
        
        // 如果栈为空,返回"0"
        if (stack.isEmpty()) {
            return "0";
        }
        
        // 构建结果字符串
        StringBuilder sb = new StringBuilder();
        while (!stack.isEmpty()) {
            sb.append(stack.pop());
        }
        
        // 由于栈是逆序的,需要反转字符串
        return sb.reverse().toString();
    }
}

这段代码首先使用一个栈来维护一个递增的数字序列,然后通过遍历输入字符串,并按照贪心策略进行操作,最后将栈中的元素转换成字符串,并返回结果。注意,在构建结果字符串时,需要反转字符串,因为栈中保存的数字是逆序的。同时,在处理过程中,我们还要注意去除前导零。

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 遍历字符串 num 中的每个字符,需要 O(n) 的时间,其中 n 是字符串 num 的长度。
  • 在每次遍历中,可能会进入一个循环,该循环会将栈顶元素弹出,直到不再满足条件。在最坏的情况下,这个循环可能执行 k 次。由于每次循环中都会减少 k 的值,因此这个循环总共最多执行 n 次(每个元素最多被弹出一次)。所以,这个循环对总时间复杂度的贡献是 O(n)。
  • 最后,将栈中的元素转移到 StringBuilder 中,并反转字符串,这需要 O(n) 的时间。

综上所述,总的时间复杂度是 O(n) + O(n) + O(n) = O(n),其中 n 是字符串 num 的长度。

2. 空间复杂度
  • 使用了一个栈来存储数字,在最坏的情况下,如果 k 为 0,即不需要移除任何数字,那么栈中会存储所有的 n 个字符。因此,栈的空间复杂度是 O(n)。
  • 使用了一个 StringBuilder 来构建最终的结果字符串,在最坏的情况下,它也会存储 n 个字符。因此,StringBuilder 的空间复杂度是 O(n)。

由于这两个数据结构是独立使用的,它们的空间复杂度是叠加的,因此总的空间复杂度是 O(n) + O(n) = O(n),其中 n 是字符串 num 的长度。

五、总结知识点

  • 数据结构 - 栈(Stack)

    • 栈是一种后进先出(LIFO)的数据结构,用于解决特定类型的问题,如括号匹配、逆序输出、函数调用等。
    • 在这段代码中,栈用于维护一个递增的数字序列,从而帮助找到最小的数字。
  • 贪心算法

    • 贪心算法是一种在每一步选择中都采取当前状态下最好或最优的选择,从而希望导致结果是全局最好或最优的算法。
    • 在这个问题中,通过比较当前字符与栈顶字符,如果当前字符更小并且允许移除数字(k > 0),则移除栈顶字符,以保持剩余数字尽可能小。
  • 字符串处理

    • 使用 toCharArray() 方法将字符串转换为字符数组,以便于遍历。
    • 使用 StringBuilder 类来构建最终的字符串结果,这是因为 StringBuilder 在频繁修改字符串时比 String 更高效。
  • 循环和条件判断

    • 使用 for 循环来遍历字符串中的每个字符。
    • 使用 while 循环来处理栈操作,直到满足特定条件为止。
    • 使用 if 语句和逻辑运算符来检查条件,如栈是否为空、k 是否大于 0 以及栈顶元素是否大于当前字符。
  • 边界条件处理

    • 在将字符压入栈之前,检查字符是否为 ‘0’,以避免结果字符串中出现前导零。
    • 在处理完所有字符后,如果 k 仍然大于 0,则继续从栈中移除元素,直到 k 为 0。
    • 如果栈为空,则返回 “0”,这是处理特殊情况的一种方式,例如输入字符串全是 ‘0’ 或 k 等于字符串长度。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

标签:数字,--,复杂度,栈顶,num,402,字符串,移掉,stack
From: https://blog.csdn.net/weixin_62860386/article/details/143815995

相关文章

  • #HarmonyOS篇:状态管理
    状态管理概要状态变量:被状态装饰器装饰的变量,状态变量值的改变会引起UI的渲染更新。常规变量:没有被状态装饰器装饰的变量,通常应用于辅助计算。数据源/同步源:状态变量的原始来源,可以同步给不同的状态数据。命名参数机制:父组件通过指定参数传递给子组件的状态变量,为父子传......
  • #HarmonyOS篇: 主题图标库&资源分类与访问
    主题图标库https://developer.huawei.com/consumer/cn/design/harmonyos-symbol/资源分类与访问地址https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/resource-categories-and-access-V5base目录是默认存在的目录,二级子目录element用于存放字符串......
  • #Ts篇: ts学习再梳理
    ts类型梳理类型声明的写法,一律为在标识符后面添加“冒号+类型”。函数参数和返回值,也是这样来声明类型。functiontoString(num:number):string{returnString(num);}上面示例中,函数toString()的参数num的类型是number。参数列表的圆括号后面,声明了返回值的类......
  • 论文7—《基于改进YOLOv5s的自然环境下猕猴桃花朵检测方法》文献阅读分析报告
    论文报告:基于改进YOLOv5s的自然环境下猕猴桃花朵检测方法基于改进YOLOv5s的自然环境下猕猴桃花朵检测方法摘要国内外研究现状1.授粉技术研究2.目标检测算法研究3.猕猴桃花朵检测研究研究目的研究问题使用的研究方法试验研究结果文献结论创新点和对现有研究的贡献创......
  • 芒果Ultralytics最新YOLO11算法原理解析-包含最新详细-结构图,以及内附YOLO11各部分细
    YOLO11系列是YOLO家族中最先进的(SOTA)、最轻量级、最高效的模型,其表现优于其前辈。它由Ultralytics创建,该组织发布了YOLOv8,这是迄今为止最稳定、使用最广泛的YOLO变体。YOLO11将延续YOLO系列的传奇。在本文中,我们将探讨YOLO11文章目录YOLO11架构、YOLO11......
  • JavaScript中的迭代器和生成器
    迭代器和生成器迭代器在JavaScript中迭代器是一个对象,它是一个使用了next()方法实现了迭代器协议的的对象(方法名是约定的,必须是next,不能是其他的)。JavaScript中可以使用迭代器的常见对象有Array、Map、Set、String。我们可以通过Symbol.iterator属性获取当前实例的迭代器......
  • 进行web开发所必须要掌握的基本常识-01
    web开发基础web开发的两种模式服务器渲染的开发模式(前后端不分离)服务器端渲染的开发模式,就是由**服务器发送给客户端HTML页面,页面是由服务器端把页面结构和数据动态拼接**而成的。优点1.前端页面可以**快速渲染、首屏加载速度快**。因为页面是由后端动态生成的HTML,浏......
  • 【linux学习指南】 进程间通信&&匿名管道&&理解管道的本质
    文章目录......
  • STM32微控制器GPIO库函数
    STM32微控制器GPIO库函数目录概述GPIO库函数基础HAL库与标准外设库GPIO库函数分类GPIO数学基础电阻分压公式输入电流计算输出驱动能力功率计算RC时间常数GPIO应用实例LED控制按钮输入与中断串行通信PWM信号生成常见问题与解决方法GPIO引脚无法正确读取输入状......
  • 东胜物流软件 GetDataListCA SQL注入漏洞复现
    0x01产品简介东胜物流软件是青岛东胜伟业软件有限公司一款集订单管理、仓库管理、运输管理等多种功能于一体的物流管理软件。该公司初创于2004年11月(前身为青岛景宏物流信息技术有限公司),专注于航运物流相关环节的产品和服务。东胜物流信息管理系统货代版采用MS-SQLserver大型......