代码随想录算法训练营第三十二天 | 全是没接触过的知识点,要复习

news2024/11/18 16:23:51

以下题目多次复习

  • 200 岛屿数量
    • 未看解答自己编写的青春版
    • 重点
      • 本题的解题思路,也是之前没有接触过的,四字总结:学会感染!
    • 题解的代码
    • 日后复习重新编写
  • 32 最长有效括号
    • 未看解答自己编写的青春版
    • 重点
      • 这道题,动态规划的思路真的很巧妙,没有想明白的地方就在于,如果s[i-1]是右括号的情况,这时应该去寻找与之匹配的左括号,如果存在,index = i-1-dp[i-1],这点一定要搞懂!
    • 题解的代码
    • 日后复习重新编写
  • 994 腐烂的橘子
    • 未看解答自己编写的青春版
    • 重点
      • 这种题目用DFS很绕,作为初学者来说,还是先学习BFS。
    • 题解的代码
    • 日后复习重新编写
  • 207 课程表
    • 未看解答自己编写的青春版
    • 重点
      • 太牛逼了,这道题我叹为观止,着重复习。
    • 题解的代码
    • 日后复习重新编写
  • 一段用于复制的标题
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后复习重新编写

200 岛屿数量

未看解答自己编写的青春版

没思路,目前没有系统学过DFS和BFS,不过大致思路应该了解,不知道怎么用在本题上。

重点

没有想到用感染函数!什么DFS,BFS,就是递归就可以了!没有想到可以改变 grid 值啊!
在这里插入图片描述

本题的解题思路,也是之前没有接触过的,四字总结:学会感染!

题解的代码

class Solution {
    public int numIslands(char[][] grid) {
        int islandNum = 0;
        for(int i = 0; i < grid.length; i++){
            for(int j = 0; j < grid[0].length; j++){
                if(grid[i][j] == '1'){
                    infect(grid, i, j);
                    islandNum++;
                }
            }
        }
        return islandNum;
    }
    //感染函数
    public void infect(char[][] grid, int i, int j){
        if(i < 0 || i >= grid.length ||
           j < 0 || j >= grid[0].length || grid[i][j] != '1'){
            return;
        }
        grid[i][j] = '2';
        infect(grid, i + 1, j);
        infect(grid, i - 1, j);
        infect(grid, i, j + 1);
        infect(grid, i, j - 1);
    }
}

日后复习重新编写

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        def infect(grid,i,j,m,n):
            if i < 0 or i >= m or j < 0 or j >= n or grid[i][j] != '1':
                return

            grid[i][j] = '2'
            infect(grid,i+1,j,m,n)
            infect(grid,i,j+1,m,n)
            infect(grid,i-1,j,m,n)
            infect(grid,i,j-1,m,n)

        m = len(grid)
        n = len(grid[0])
        res = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == '1':
                    res += 1
                    infect(grid,i,j,m,n)
        return res

32 最长有效括号

未看解答自己编写的青春版

没写出来。能意识到有两种思路:栈和动态规划。动态规划想不清楚递推逻辑,栈的话,编写思路还是走的“有效括号匹配”,让字符入栈了,这是错误的!因为字符串在遍历的时候,有下标信息,下标之差就是最大长度!栈里应该存放下标信息!

错误的代码:

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        if s == '':
            return 0       
        res = []
        stack = []
        for i in s :
            if i == '(':
                res.append(-1)
                stack.append(i)
            else :               
                if stack == [] :
                    res.append(-1)
                    stack.append(i)
                    continue
                temp = stack.pop()
                if temp == '(':  
                    number = res.pop()
                    if number < 0 :
                        res.append(2)
                    else :
                        res.pop()
                        res.append(2+number)
                else :  
                    res.append(-1)
                    stack = []
        maxi = 0
        count = 0
        for i in res :
            if i < 0 :
                count = 0
            else :
                count += i
                maxi = max(maxi,count)
                    
        return maxi

重点

在这里插入图片描述
在这里插入图片描述

这道题,动态规划的思路真的很巧妙,没有想明白的地方就在于,如果s[i-1]是右括号的情况,这时应该去寻找与之匹配的左括号,如果存在,index = i-1-dp[i-1],这点一定要搞懂!

题解的代码

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        res = 0
        stack = [-1]
        for i, c in enumerate(s):
            if c == "(":
                stack.append(i)
            else:
                stack.pop()
                if not stack:
                    stack.append(i)
                else:
                    res = max(res, i - stack[-1])
        return res
class Solution:
    def longestValidParentheses(self, s: str) -> int:
        dp = [0] * len(s)
        for i in range(1, len(s)):
            if s[i] == ")":
                if s[i - 1] == "(":
                    dp[i] = dp[i - 2] + 2
                else:
                    j = i - 1 - dp[i - 1]
                    if j >= 0 and s[j] == "(":
                        dp[i] = dp[j - 1] + dp[i - 1] + 2
        return max(dp + [0])  # 避免max([])的报错

日后复习重新编写

994 腐烂的橘子

未看解答自己编写的青春版

做出来了,是用的和上一题相类似的想法。只不过我觉得这题不能用递归来解。

class Solution:
    def orangesRotting(self, grid: List[List[int]]) -> int:

        def is_right(grid,m,n):
            for i in range(m):
                for j in range(n):
                    if grid[i][j]==1:
                        if i!=0 and grid[i-1][j] > 1 :
                            return True
                        if j!=0 and grid[i][j-1] > 1 :
                            return True
                        if i!=m-1 and grid[i+1][j] > 1:
                            return True
                        if j!=n-1 and grid[i][j+1] > 1:
                            return True
                        
            return False
        res = 2
        m = len(grid)
        n = len(grid[0])
        while is_right(grid,m,n):
            for i in range(m):
                for j in range(n):
                    if grid[i][j]==res:
                        if i!=0 and grid[i-1][j] == 1:
                            grid[i-1][j] = res+1                            
                        if j!=0 and grid[i][j-1] == 1:
                            grid[i][j-1] = res+1                           
                        if i!=m-1 and grid[i+1][j] == 1:
                            grid[i+1][j] = res+1                           
                        if j!=n-1 and grid[i][j+1] == 1:
                            grid[i][j+1] = res+1                                
            res += 1
                    
        for i in range(m):
            for j in range(n):
                if grid[i][j]==1:
                    return -1
        #print(grid)
        return res-2

重点

这种需要一圈一圈往外传播的一般用BFS解, 先找到起始所有腐烂的橘子,然后循环处理,把新腐烂的橘子加入下一次循环的队列中, 当下一次循环的队列为空时,说明不能继续腐烂了, 判断一下还有没有新鲜的橘子,如果有,就返回-1,否则返回分钟数。

class Solution(object):
    def orangesRotting(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        dx = [1, -1, 0, 0]
        dy = [0, 0, 1, -1]
        rotlist = list()
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 2:
                    rotlist.append([i, j])
        minute = 0
        while(rotlist): #BFS循环
            newrotlist = list()
            for rotnode in rotlist:
                x0 = rotnode[0]
                y0 = rotnode[1]
                
                for k in range(4):
                    x = x0 + dx[k]
                    y = y0 + dy[k]
                    
                    if 0 <= x < len(grid) and 0 <= y < len(grid[0]) and grid[x][y] == 1:
                        grid[x][y] = 2
                        newrotlist.append([x,y])
            if not newrotlist:
                break
                
            rotlist = newrotlist[:]
            minute += 1
            
        for row in grid:
            for i in row:
                if i == 1:#还有新鲜的
                    return -1
        return minute

这种题目用DFS很绕,作为初学者来说,还是先学习BFS。

题解的代码

日后复习重新编写

207 课程表

未看解答自己编写的青春版

没思路,感觉用栈模拟是可以的,但是不知道怎么开启循环,也就是说,不知道怎样遍历所有情况。

重点

看了看评论,完全是我没接触过的点。
在这里插入图片描述
在这里插入图片描述

class Solution(object):

    # 思想:该方法的每一步总是输出当前无前趋(即入度为零)的顶点

    def canFinish(self, numCourses, prerequisites):
        """
        :type numCourses: int 课程门数
        :type prerequisites: List[List[int]] 课程与课程之间的关系
        :rtype: bool
        """
        # 课程的长度
        clen = len(prerequisites)
        if clen == 0:
            # 没有课程,当然可以完成课程的学习
            return True
        # 入度数组,一开始全部为 0
        in_degrees = [0 for _ in range(numCourses)]
        # 邻接表
        adj = [set() for _ in range(numCourses)]

        # 想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]
        # [0,1] 表示 1 在先,0 在后
        # 注意:邻接表存放的是后继 successor 结点的集合
        for second, first in prerequisites:
            in_degrees[second] += 1
            adj[first].add(second)

        # print("in_degrees", in_degrees)
        # 首先遍历一遍,把所有入度为 0 的结点加入队列
        res = []
        queue = []
        for i in range(numCourses):
            if in_degrees[i] == 0:
                queue.append(i)
        counter = 0
        while queue:
            top = queue.pop(0)
            counter += 1

            for successor in adj[top]:
                in_degrees[successor] -= 1
                if in_degrees[successor] == 0:
                    queue.append(successor)

        return counter == numCourses
class Solution(object):

    # 这里使用逆邻接表

    def canFinish(self, numCourses, prerequisites):
        """
        :type numCourses: int 课程门数
        :type prerequisites: List[List[int]] 课程与课程之间的关系
        :rtype: bool
        """
        # 课程的长度
        clen = len(prerequisites)
        if clen == 0:
            # 没有课程,当然可以完成课程的学习
            return True
        # 深度优先遍历,判断结点是否访问过
        # 这里要设置 3 个状态
        # 0 就对应 False ,表示结点没有访问过
        # 1 就对应 True ,表示结点已经访问过,在深度优先遍历结束以后才置为 1
        # 2 表示当前正在遍历的结点,如果在深度优先遍历的过程中,
        # 有遇到状态为 2 的结点,就表示这个图中存在环
        visited = [0 for _ in range(numCourses)]

        # 逆邻接表,存的是每个结点的前驱结点的集合
        # 想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]
        # 1 在前,0 在后
        inverse_adj = [set() for _ in range(numCourses)]
        for second, first in prerequisites:
            inverse_adj[second].add(first)

        for i in range(numCourses):
            # 在遍历的过程中,如果发现有环,就退出
            if self.__dfs(i, inverse_adj, visited):
                return False
        return True

    def __dfs(self, vertex, inverse_adj, visited):
        """
        注意:这个递归方法的返回值是返回是否有环
        :param vertex: 结点的索引
        :param inverse_adj: 逆邻接表,记录的是当前结点的前驱结点的集合
        :param visited: 记录了结点是否被访问过,2 表示当前正在 DFS 这个结点
        :return: 是否有环
        """
        # 2 表示这个结点正在访问
        if visited[vertex] == 2:
            # 表示遇到环
            return True
        if visited[vertex] == 1:
            return False

        visited[vertex] = 2
        for precursor in inverse_adj[vertex]:
            # 如果有环,就返回 True 表示有环
            if self.__dfs(precursor, inverse_adj, visited):
                return True

        # 1 表示访问结束
        visited[vertex] = 1
        return False

总体来说的思路:

统计每个课被指向次数,初始被指向次数为0的肯定是安全的(不在环上)。

每被安全课程指向一次,被指次数减一,

如果被指次数减到0,说明该课程全部指向都来自安全课程,则它也是安全的。

依此进行队列循环。

太牛逼了,这道题我叹为观止,着重复习。

题解的代码

日后复习重新编写

一段用于复制的标题

未看解答自己编写的青春版

搞不懂这道题在干嘛,我也不知道我在写什么,因为根本不了解前缀树是个什么玩意,但是AC了。

class Trie:
    def __init__(self):
        self.tire = []
        
    def insert(self, word: str) -> None:
        self.tire.append(word)
       

    def search(self, word: str) -> bool:
        if word in self.tire:
            return True
        return False


    def startsWith(self, prefix: str) -> bool:
        n = len(prefix)
        for i in self.tire :
            if len(i)>= n :
                if i[:n]==prefix:
                    return True
        return False

重点

先放一篇博客吧,讲前缀树的,讲的很好。
前缀树博客讲解

大致的思路如下:
在这里插入图片描述
在这里插入图片描述

class Trie:
    def __init__(self):
        # For empty string `""`
        self.trie = {'flag': True}

    def insert(self, word: str) -> None:
        """
        Inserts a word into the trie.
        """
        node = self.trie
        for char in word:
            if char in node:
                node = node[char]
            else:
                node[char] = {}
                node = node[char]
        # Indentify whether path is a word
        node['flag'] = True

    def search(self, word: str) -> bool:
        """
        Returns if the word is in the trie.
        """
        node = self.trie
        for char in word:
            if char in node: node = node[char]
            else: return False
        return node.get('flag', False)

    def startsWith(self, prefix: str) -> bool:
        """
        Returns if there is any word in the trie that starts with the given prefix.
        """
        node = self.trie
        for char in prefix:
            if char in node: node = node[char]
            else: return False
        return True

题解的代码

日后复习重新编写

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

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

相关文章

19-2.vuex

目录 1 安装 2 挂载 2.1 vue2写法 2.2 vue3写法 3 state 3.1 声明数据 3.2 使用数据 3.3 处理数据 4 mutations 4.1 基本使用 4.2 传递参数 4.3 mutations中不能写异步的代码 5 actions 5.1 基本使用 5.2 传递参数 6 getters Vuex是做全局数据…

CAS原理解析

CAS是一种乐观锁机制&#xff0c;一种比较并交换的过程和理念&#xff0c;用来解决线程安全问题&#xff0c;具体来讲就是对共享变量值的安全更新机制。能够保证原子、可见、一致性。这种交换过程是在Unsafe类中实现。 从一段简单的代码开始来对源码做分析 public static void…

坚鹏:常德市银行业协会BLM银行数字化转型战略培训圆满结束

常德市银行业协会BLM银行数字化转型战略培训圆满结束 在数字化转型背景下&#xff0c;常德市银行业协会为了落实监管政策《关于银行业保险业数字化转型的指导意见》&#xff0c;充分认识到学习银行银行数字化转型战略的价值和重要性&#xff0c;特别举办《2023年数字化转型战略…

06 Ubuntu22.04上的miniconda3安装、深度学习常用环境配置

下载脚本 我依然是在清华镜像当中寻找的脚本。这里找脚本真的十分方便&#xff0c;我十分推荐。 wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh 下载十分快速&#xff0c;10秒解决问题 运行miniconda3安装脚本 赋予执…

邀请媒体现场报道,有哪些作用?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 邀请媒体现场报道活动具有多种重要作用和意义&#xff0c;可以为你的活动带来广泛的曝光和正面影响。以下是一些邀请媒体现场报道的作用和意义&#xff1a; 1. 增加活动曝光度&#xff…

Android 自定义按钮(可滑动、点击)

按钮图片素材 https://download.csdn.net/download/Lan_Se_Tian_Ma/88151085 px 和 dp 转换工具类&#xff08;Java&#xff09; // px 和 dp 转换工具类 public class DensityUtil {/*** 根据手机的分辨率从 dip 的单位 转成为 px(像素)*/public static int dip2px(Conte…

C 语言多线程(上)

一&#xff0c;线程创建 1.1 每一个线程都有一个唯一的线程ID&#xff0c;ID类型为pthread_t&#xff0c;这个ID是一个无符号长整形数&#xff0c;如果想要得到当前线程的线程ID&#xff0c;可以调用如下函数&#xff1a; pthread_t pthread_self(void); // 返回当前线程的线…

如何设计一个自动化测试框架?

一个成熟的测试框架主要由 4 部分组成&#xff1a;基础模块、管理模块、运行模块和统计模块 基础模块 底层核心库 一般指用于操作被测试应用程序的第三方库&#xff0c;例如在 Web 端的 Selenium/WebDriver。如API端的Requests 对象库 PO模式中的页面对象 可重用组件 如一些…

JavaScript 手撕大厂面试题数组扁平化以及增加版本 plus

前言 现在的前端面试手撕题是一个必要环节&#xff0c;有点时候八股回答的不错但是手撕题没写出来就会让面试官印象分大减&#xff0c;很可能就挂了… 概念 数组的扁平化其实就是将一个多层嵌套的数组转换为只有一层的数组 比如&#xff1a; [1, [2, [3, [4, 5]]]] > [1…

张量Tensor 深度学习

1 张量的定义 张量tensor理论是数学的一个分支学科&#xff0c;在力学中有重要的应用。张量这一术语源于力学&#xff0c;最初是用来表示弹性介质中各点应力状态的&#xff0c;后来张量理论发展成为力学和物理学的一个有力数学工具。 张量&#xff08;Tensor&#xff09;是一个…

WAF绕过-工具特征-菜刀+冰蝎+哥斯拉

WAF绕过主要集中在信息收集&#xff0c;漏洞发现&#xff0c;漏洞利用&#xff0c;权限控制四个阶段。 1、什么是WAF&#xff1f; Web Application Firewall&#xff08;web应用防火墙&#xff09;&#xff0c;一种公认的说法是“web应用防火墙通过执行一系列针对HTTP/HTTPS的安…

当服务器域名出现解析错误的问题该怎么办?

​  域名解析是互联网用户接收他们正在寻找的域的地址的过程。更准确地说&#xff0c;域名解析是人们在浏览器中输入时使用的域名与网站IP地址之间的转换过程。您需要站点的 IP 地址才能知道它所在的位置并加载它。但&#xff0c;在这个过程中&#xff0c;可能会出现多种因素…

leetcode(力扣)剑指 Offer 16. 数值的整数次方 (快速幂)

文章目录 题目描述思路分析完整代码 题目描述 实现 pow(x, n) &#xff0c;即计算 x 的 n 次幂函数&#xff08;即&#xff0c;xn&#xff09;。不得使用库函数&#xff0c;同时不需要考虑大数问题。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n 10 输出&#xff1a;10…

Scratch 教程 -- 如何绘制像素画

1.像素画的定义 像素画就是以1像素的正方形为最小单位画的画&#xff0c;且物体有明显的分界线 这是像素画 这不是像素画 来看这两个法棍 这是像素画 这不是像素画 为什么第二个不是像素画&#xff1f;因为不能区分边缘和物体&#xff0c;它们之间有很多过渡色。 中间的过渡色属…

JUC并发编程之volatile详解

目录 1. volatile 1.1 volatile关键字的作用 1.1.1 变量可见性 1.1.2 禁止指令重排序 1.2 volatile可见性案例 1.3 volatile非原子性案例 1.4 volatile 禁止重排序 1.5 volatile 日常使用场景 送书活动 1. volatile 在并发编程中&#xff0c;多线程操作共享的变量时&a…

SAP MIRO 报错 Allowed posting periods:xx xxx

背景&#xff1a;在八月初&#xff0c;七月份财务账期没关&#xff0c;七月份物料帐期已关 用户在做MIRO的时候&#xff0c;无法开票成功&#xff0c;报错&#xff1a; Allowed posting periods:xx xxx 但是集团要求&#xff0c;这些帐应该记在七月份 查询相关资料得知。MI…

PLUS模型 | 历史土地利用数据,进行多情景模式下的未来土地利用预测

工业革命以来&#xff0c;社会生产力迅速提高&#xff0c;人类活动频繁&#xff0c;此外人口与日俱增对土地的需求与改造更加强烈&#xff0c;人-地关系日益紧张。此外&#xff0c;土地资源的不合理开发利用更是造成了水土流失、植被退化、水资源短缺、区域气候变化、生物多样性…

【嵌入式学习笔记】嵌入式入门3——串口

1.数据通信的基础概念 1.1.串行/并行通信 数据通信按数据通信方式分类&#xff1a;串行通信、并行通信 1.2.单工/半双工/全双工通信 数据通信按数据传输方向分类&#xff1a;单工通信、半双工通信、全双工通信 单工通信&#xff1a;数据只能沿一个方向传输半双工通信&…

支持中文创成式填充 AI版PS 2023 v25.0安装教程

抖音保姆级视频教程: https://v.douyin.com/iJdUjg2o/ PS 2023 v25.0安装包地址&#xff1a; 链接: https://pan.baidu.com/s/1PXgVHDHdMIRcDzV4IfGAQw?pwd2023 提取码: 2023 如有疑问请加交流请加QQ群&#xff1a;814894746 安装教程总结&#xff1a; 卸载之前的PS beta版…

C++11 通用工具

通用工具 目录 pair和tuple智能指针数值极值type trait 和type utility辅助函数clock和timerbitset随机数 1 pair和Tuple 1.1 pair 头文件 #include<utility>pair定义 pair<string,string> author{James","joyce"};)] --> pair操作 1.2 tup…