Leetcode算法题笔记(3)

news2024/11/16 22:34:31

目录

  • 矩阵
    • 101. 生命游戏
      • 解法一
      • 解法二
    • 102. 移掉 K 位数字
      • 解法一
    • 103. 去除重复字母
      • 解法一

矩阵

101. 生命游戏

根据 百度百科 , 生命游戏 ,简称为 生命 ,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。

给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态: 1 即为 活细胞 (live),或 0 即为 死细胞 (dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:

如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你 m x n 网格面板 board 的当前状态,返回下一个状态。

进阶:

你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
在这里插入图片描述

解法一

非原地算法:将矩阵复制一份,遍历旧矩阵每个元素的周围8个元素,计算存活细胞数量,再根据规则在新矩阵上进行修改,返回新矩阵(一下阶段状态矩阵)。空间复杂度过高O(mn)。

解法二

原地算法:空间复杂度过高O(1)。可以找一个复合状态同时表示旧状态和新状态,例如定义:

  • 如果细胞从活着变为死了,则复合状态为2;
  • 如果细胞从死了变成活了,则符合状态为3;
    之后便可按照算法一遍历元素,判断周围存活元素时,需要参考过去的状态,即值为1或2。最后重新遍历矩阵,将2,3变为对应的最新状态值0 , 1
class Solution {
    public void gameOfLife(int[][] board) {
        //定义如果细胞从活着变为死了,则复合状态为2;
        //如果细胞从死了变成活了,则符合状态为3;
        int row = board.length;
        int col = board[0].length;
        int[] neighbors = {-1,0,1};

        for(int i = 0; i < row ; ++i ){
            for(int j = 0; j < col ; ++j){
                int liveCount = 0;

                for(int e = 0;  e < 3 ; ++e){
                    for(int f = 0; f < 3; ++f){
                        if(!(neighbors[e] == 0 && neighbors[f] == 0)){
                            int r = neighbors[e] + i;
                            int c = neighbors[f] + j;

                            if((r >= 0 && r < row) && (c >= 0 && c < col) && ( board[r][c] == 1 || board[r][c]  == 2)){++liveCount;}
                        }
                    }
                }
                if(board[i][j] == 1 && ( liveCount < 2 || liveCount > 3 )){
                    board[i][j] = 2;
                }else if(board[i][j] == 0 && liveCount == 3){
                    board[i][j] = 3;
                }

            }
        }

        for(int i = 0; i < row ; ++i ){
            for(int j = 0; j < col ; ++j){
                if(board[i][j] == 2) board[i][j] = 0;
                if(board[i][j] == 3) board[i][j] = 1;
            }
        }

    }
}

102. 移掉 K 位数字

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

解法一

        单调栈+贪心算法:为了得到尽可能小的数字,其和位数以及高位上的数字大小是相关的。如果前面高位数(高到低)都是升序的,那么这个数是这些每位上的数所能排列出的最小整数,例如123 是 1,2,3能组成的最小数。因此,借鉴这一点,可以利用贪心思想,遍历字符串,每次尽可能得到最小的数,直至到末尾。
        维持一个当前最小的数需要使用一个单调栈,保证数字是升序排列。如果遇到比栈顶元素还要小的数,那么栈顶元素就应该弹出移除(且k-1),直至k为0(删除完成)或者当前元素比栈顶元素大(则需要将当前元素压栈,此时栈中又是一个升序栈)。例如124532,k = 3 ,当遍历到3时,4,5需要出栈,之后为1232,此时3需要出栈,最终结果为122
        有种可能情况:遍历完字符串后,单调栈已经是升序,但是k还不为0,依然需要删除数字,那么此时直接从最低位开始删即可,因为删除一位数字的总位数将会固定,而最低位数字最大,且能保证前面的数字依旧是排列最小的数,例如12345,删除5后,结果为1234。

class Solution {
    public String removeKdigits(String num, int k) {
        Deque<Character> list = new LinkedList<>();
        int len = num.length();
        for(int i = 0; i < len; ++i){
            char c = num.charAt(i);
            // int numi = Character.getNumericValue(c);
            while( !list.isEmpty() && k > 0 && list.peek() > c ){
                list.pop();
                k--;
            }
            list.push(c);
        }

        while(k > 0){
            list.pop();
            k--;
        }

        StringBuilder res = new StringBuilder();
        boolean flag = true;//用于判断数字最前端是否是连续0
        while(!list.isEmpty()){
            char digit = list.pollLast();
            if(flag && digit == '0'){
                continue;
            }
            flag = false;
            res.append(digit);
        }

        return res.length() == 0 ? "0" : res.toString();
    }
}

103. 去除重复字母

给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的
字典序
最小(要求不能打乱其他字符的相对位置)。
在这里插入图片描述

解法一

        单调栈+贪心算法:根据题目可知,要求每个字母只能出现一次,且这些字母组成的字典序最小。当字符呈升序排列(a b c d e f…)时,字典序是最小的时候,因此可以尝试采用单调栈来维持最小字典序的子串。此外,尝试将其与贪心思想结合,遍历字符串,每次均保证当前单调栈维持的就是目前字典序最小的子串,进而推导出最终字典序最小的子串。

  • 遍历元素过程中,如果栈为空或者当前元素相较于栈顶元素是升序,则可以直接将当前元素压栈
  • 如果当前元素已经在栈中出现过,则可以直接丢弃当前元素。因为单调栈维持的是最小字典序的子串了,如果强行将该元素放入栈中,只可能会造成字典序增大或者无变化。例如栈中acd 当前c ,最多也只能让c 和 d 出栈,然后将当前c压栈,最后栈中为ac,得到的结果其实与原栈中acd前半部分几乎一样,但是少了d的信息。让当前c是否压栈对整体的最小字典序没有益处,并不能减小字典序,反而如果d是最后一个d了,那么d必须存在,则c无法压栈。因此当元素已经出现在栈中时,没有必要将其压栈处理。
  • 如果出现了与单调栈栈顶元素大小顺序不符元素,即需要看情况丢弃当前元素还是丢弃栈中的元素。如果该栈顶元素在字符串后面已经不存在同样的元素了,则说明该元素不能在被丢弃了,后续直接入栈当前元元素如果该栈顶元素在字符串后面还存在,则说明可以丢弃当前栈顶元素,由于栈中可能有连续几个比当前元素大的元素,所以可能会连续多出栈几个元素。例如 acbc ,栈中元素为ac,当前元素b,则c后面还有,因此可以弹出c ,压栈b,压栈最后一个c,即可得到比acb更小的字典序子串abc
class Solution {
    public String removeDuplicateLetters(String s) {
        Deque<Character> stack = new LinkedList<>();
        int len = s.length();
        boolean[] numVisit = new boolean[26];
        int[] count = new int[26];
        //初始化字符串中各字符的频次
        for(int i = 0; i < len ; ++i){
            count[s.charAt(i) - 'a']++;
        }

        for(int i = 0; i <len ;++i){
            char c = s.charAt(i);
            count[c - 'a']--;
            //说明元素已经存在于单调栈中,因此可以直接丢弃
            if(numVisit[c - 'a'] == true){
                continue;
            }

            //如果出现了与单调栈栈顶元素大小顺序不符元素,即需要看情况丢弃当前元素还是丢弃栈中的元素
            if(!stack.isEmpty() && stack.peek() >= c ){
                //如果元素小于栈顶元素,则说明有可能用当前元素替换栈顶元素以得到更小的字典序
                while(!stack.isEmpty() && stack.peek() > c){
                    //如果该栈顶元素在字符串后面已经不存在同样的元素了,则说明该元素不能在被丢弃了,后续直接入栈当前元素
                    if(count[stack.peek() - 'a'] == 0){
                        break;
                    }
                    //如果该栈顶元素在字符串后面还存在,则说明可以丢弃当前栈顶元素
                    numVisit[stack.poll() - 'a'] = false;
                }
                //让比之前栈顶元素更小的当前元素入栈
                stack.push(c);
                numVisit[c - 'a'] = true;
            }
            else{
                //当前元素符合单调栈中的单调性,因此直接压栈即可
                numVisit[c - 'a'] = true;
                stack.push(c);
            }
        }
        StringBuilder res = new StringBuilder();
        while(!stack.isEmpty()){
            res.append(stack.pollLast());
        }
        return res.toString();
    }
}

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

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

相关文章

Redis简介与安装到python的调用

前言 本文只不对redis的具体用法做详细描述&#xff0c;做简单的介绍&#xff0c;安装&#xff0c;和python代码调用详细使用教程可查看一下网站 https://www.runoob.com/redis/redis-tutorial.html https://pypi.org/project/redis/ 官方原版: https://redis.io/ 中文官网:…

齿轮常见故障学习笔记

大家好&#xff0c;这期咱们聊一聊齿轮常见的失效形式&#xff0c;查阅了相关的资料&#xff0c;做个笔记分享给大家&#xff0c;共同学习。 介绍 齿轮故障可能以多种方式发生。如果在设计阶段本身就尽量防止这些故障的产生&#xff0c;则可以产生改更为优化的齿轮设计。齿轮…

Top期刊:针对论文Figure图片的7个改进建议

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 通过对来自细胞生物学、生理学和植物学领域的580篇论文&#xff0c;进行检查和归纳总结&#xff0c;来自德国德累斯顿工业大学的Helena Jambor及合作者&#xff0c;在PLOS Bio…

五分钟搭建一个Suno AI音乐站点

五分钟搭建一个Suno AI音乐站点 在这个数字化时代&#xff0c;人工智能技术正以惊人的速度改变着我们的生活方式和创造方式。音乐作为一种最直接、最感性的艺术形式&#xff0c;自然也成为了人工智能技术的应用场景之一。今天&#xff0c;我们将以Vue和Node.js为基础&#xff…

第12章-ADC采集电压和显示 基于STM32的ADC—电压采集(详细讲解+HAL库)

我们的智能小车用到了ADC测量电池电压的功能&#xff0c;这章节我们做一下。 我们的一篇在这里 第一篇 什么是ADC 百度百科介绍&#xff1a; 我们知道万用表 电压表可以测量电池&#xff0c;或者电路电压。那么我们是否可以通过单片机获得电压&#xff0c;方便我 们监控电池状…

WPF学习日常篇(一)--开发界面视图布局

接下来开始日常篇&#xff0c;我在主线篇&#xff08;正文&#xff09;中说过要介绍一下我的界面排布&#xff0c;科学的排布才更科学更有效率的进行敲代码和开发。日常篇中主要记录我的一些小想法和所考虑的一些细节。 一、主界面设置 主界面分为左右两部分&#xff0c;分为…

查分数组总结

文章目录 查分数组定义应用举例LeetCode 1109 题「[航班预订统计] 查分数组定义 差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。 通过这个 diff 差分数组是可以反推出原始数组 nums 的&#xff0c;代码逻辑如下&#xff1a; int res[diff.size()]; // 根…

(2024,SDE,对抗薛定谔桥匹配,离散时间迭代马尔可夫拟合,去噪扩散 GAN)

Adversarial Schrdinger Bridge Matching 公众号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 4. 实验 0. 摘要 薛定谔桥&#xff08;Schrdinger Bridge&#xff0c;SB&…

flash-linear-attention中的Chunkwise并行算法的理解

这里提一下&#xff0c;我维护的几三个记录个人学习笔记以及社区中其它大佬们的优秀博客链接的仓库都获得了不少star&#xff0c;感谢读者们的认可&#xff0c;我也会继续在开源社区多做贡献。github主页&#xff1a;https://github.com/BBuf &#xff0c;欢迎来踩 0x0. 前言 …

MySQL——索引与事务

目录 前言 一、索引 1.索引概述 &#xff08;1&#xff09;基本概念 &#xff08;2&#xff09;索引作用 &#xff08;3&#xff09;索引特点 &#xff08;4&#xff09;适用场景 2.索引的操作 &#xff08;1&#xff09;查看索引 &#xff08;2&#xff09;创建索引…

【算法题】520 钻石争霸赛 2024 全解析

都是自己写的代码&#xff0c;发现自己的问题是做题速度还是不够快 520-1 爱之恒久远 在 520 这个特殊的日子里&#xff0c;请你直接在屏幕上输出&#xff1a;Forever and always。 输入格式&#xff1a; 本题没有输入。 输出格式&#xff1a; 在一行中输出 Forever and always…

2024年推荐的适合电脑和手机操作的线上兼职副业平台

总是会有人在找寻着线上兼职副业&#xff0c;那么在如今的2024年&#xff0c;互联网提供了诸多方便&#xff0c;无论你是宝妈、大学生、程序员、外卖小哥还是打工族&#xff0c;如果你正在寻找副业机会&#xff0c;那么这篇文章将为你提供一些适合电脑和手机操作的线上兼职副业…

[Linux]文件/文件描述符fd

一、关于文件 文件&#xff1d;内容&#xff0b;属性 那么所有对文件的操作&#xff0c;就是对内容/属性操作。内容是数据&#xff0c;属性也是数据&#xff0c;那么存储文件&#xff0c;就必须既存储内容数据&#xff0c;又存储属性数据。默认就是在磁盘中的文件。当进程访问…

知识分享:隔多久查询一次网贷大数据信用报告比较好?

随着互联网金融的快速发展&#xff0c;越来越多的人开始接触和使用网络贷款。而在这个过程中&#xff0c;网贷大数据信用报告成为了评估借款人信用状况的重要依据。那么&#xff0c;隔多久查询一次网贷大数据信用报告比较好呢?接下来随小易大数据平台小编去看看吧。 首先&…

YOLOV5 改进:替换backbone为EfficientNet

1、介绍 本章将会把yolov5的主干网络替换成EfficientNet V2,这里直接粘贴代码 详细的可以参考之前的内容:YOLOV5 改进:替换backbone(MobileNet为例)_yolov5主干网络更换为mobile-CSDN博客 更多的backbone更换参考本专栏: YOLOV5 实战项目(训练、部署、改进等等)_听风吹…

2024电工杯B题平衡膳食食谱的优化设计及评价原创论文分享

大家好&#xff0c;从昨天肝到现在&#xff0c;终于完成了2024电工杯数学建模B题的完整论文啦。 实在精力有限&#xff0c;具体的讲解大家可以去讲解视频&#xff1a; 给大家看一下目录吧&#xff1a; 目录 摘 要&#xff1a; 10 一、问题重述 14 二&#xff0e;问题分析 …

2024.05.26 第 399 场周赛

Leetcode 第 399 场周赛 优质数对的总数 I Leetcode 优质数对的总数 I 给你两个整数数组 nums1 和 nums2&#xff0c;长度分别为 n 和 m。同时给你一个正整数 k。 如果 nums1[i] 可以被 nums2[j] * k 整除&#xff0c;则称数对 (i, j) 为 优质数对&#xff08;0 < i < n…

航运复兴?大摩不信!

大摩认为&#xff0c;从供需关系来看红海危机只是推迟了航运业下行周期的到来&#xff0c;一旦干扰消除&#xff0c;行业可能重回周期性低迷。 红海危机加剧运力紧张&#xff0c;航运市场价格飞涨。 大摩在24日的一份报告中指出&#xff0c;受红海危机干扰航运市场运力&#…

加密与安全_AES RSA 密钥对生成及PEM格式的代码实现

文章目录 RSA&#xff08;非对称&#xff09;和AES&#xff08;对称&#xff09;加密算法一、RSA&#xff08;Rivest-Shamir-Adleman&#xff09;二、AES&#xff08;Advanced Encryption Standard&#xff09; RSA加密三种填充模式一、RSA填充模式二、常见的RSA填充模式组合三…