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

以下题目多次复习

  • 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

题解的代码

日后复习重新编写

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小鹏遭遇“动荡”,自动驾驶副总裁吴新宙离职,现已完成团队过渡

根据最新消息&#xff0c;小鹏汽车的自动驾驶副总裁吴新宙宣布将加入全球GPU芯片巨头英伟达。吴新宙将成为该公司全球副总裁&#xff0c;直接向英伟达全球CEO黄仁勋汇报。小鹏汽车董事长何小鹏和吴新宙本人已在微博上确认该消息&#xff0c;并解释离职原因涉及家庭和多方面因素…

Spark提交流程

客户端通过脚本将任务提交到yarn执行&#xff0c;yarn启动APPMaster&#xff0c;APPMaster启动Driver线程&#xff0c;Driver负责初始化SparkContext并进行任务的切分和分配任务&#xff0c;交给Executor进行计算。

质数(判定质数 分解质因数 筛质数)

这里写目录标题 一、判定质数思路分析代码实现 二、分解质因数思路分析典型题目代码实现 三、质数筛经典题目思路分析1. 朴素筛法2. 埃氏筛法3. 欧拉筛法 一、判定质数 思路分析 由于每个合数的因子是成对出现的&#xff0c;即如果 d d d 是 n n n 的因子&#xff0c;那么 …

Qt实现引导界面UITour

介绍 最近做了一款键鼠自动化&#xff0c;想第一次安装打开后搞一个引导界面&#xff0c;找了好多资料没啥参考&#xff0c;偶然发现qt有引导界面如下图。 Qt整挺好&#xff0c;但是未找到源码&#xff0c;真的不想手撸&#xff0c;(源码找到了但是Qt整起来太复杂,没法拿来直接…

Python系统学习1-2

目录 一、硬件 二、软件&#xff1a;程序文档 三、基础知识 四、python执行过程 五、Pycharm使用技巧 一、硬件 计算机五大部件&#xff1a;运算器&#xff0c;存储器&#xff0c;控制器、输入设备&#xff0c;输出设备。 运算器和控制器 集成在CPU中。 存储&#xff1a…

Qt Creator 11 开放源码集成开发环境新增集成终端和 GitHub Copilot 支持

导读Qt 项目今天发布了 Qt Creator 11&#xff0c;这是一款开源、免费、跨平台 IDE&#xff08;集成开发环境&#xff09;软件的最新稳定版本&#xff0c;适用于 GNU/Linux、macOS 和 Windows 平台。 Qt Creator 11 的亮点包括支持标签、多外壳、颜色和字体的集成终端模拟器&am…

hcip——BGP实验

要求 1.搭建toop 2.地址规划 路由器AS接口地址R11 loop0:1.1.1.1 24 loop1 : 192.168.1.1 24 g0/0/0 12.0.0.1 24 R22 64512 g0/0/0: 12.0.0.2 24 g/0/01: 172.16.0.2 19 g0/0/2: 172.16.96.2 19 R32 64512g0/0/0: 172.16.0.3 19 g0/0/1:1…

在使用Python爬虫时遇到解析错误解决办法汇总

在进行Python爬虫任务时&#xff0c;遇到解析错误是常见的问题之一。解析错误可能是由于网页结构变化、编码问题、XPath选择器错误等原因导致的。为了帮助您解决这个问题&#xff0c;本文将提供一些实用的解决办法&#xff0c;并给出相关的代码示例&#xff0c;希望对您的爬虫任…

实现Feed流的三种模式:拉模式、推模式和推拉结合模式

在互联网产品中&#xff0c;Feed流是一种常见的功能&#xff0c;它可以帮助我们实时获取我们关注的用户的最新动态。Feed流的实现有多种模式&#xff0c;包括拉模式、推模式和推拉结合模式。在本文中&#xff0c;我们将详细介绍这三种模式&#xff0c;并通过Java代码示例来实现…

Centos7 安装man中文版手册

查找man中文安装包&#xff1a; yum search man-pages 安装man-pages-zh-CN.noarch: yum install -y man-pages-zh-CN.noarch

05|Oracle学习(UNIQUE约束)

1. UNIQUE约束介绍 也叫&#xff1a;唯一键约束&#xff0c;用于限定数据表中字段值的唯一性。 1.1 UNIQUE和primary key区别&#xff1a; 主键/联合主键每张表中只有一个。UNIQUE约束可以在一张表中&#xff0c;多个字段中存在。例如&#xff1a;学生的电话、身份证号都是…

091.粉刷房子

一、题目 剑指 Offer II 091. 粉刷房子 - 力扣&#xff08;LeetCode&#xff09; 二、代码 class Solution { public:int minCost(vector<vector<int>>& costs) {int row costs.size();int col costs[0].size();if (row 1)return min(min(costs[0][0], cos…

Mybatis ,Mybatis-plus列表多字段排序,包含sql以及warpper

根据 mybatis 根据多字段排序已经wrapper 根据多字段排序 首先根据咱们返回前端的数据列来规划好排序字段 如下&#xff1a; 这里的字段为返回VO的字段,要转换成数据库字段然后加入到排序中 示例&#xff0c;穿了 surname,cerRank 多字段,然后是倒序 false 首先创建好映射&am…

Python元编程-装饰器介绍、使用

目录 一、Python元编程装饰器介绍 二、装饰器使用 1. 实现认证和授权功能 2.实现缓存功能 3.实现日志输出功能 三、附录 1. logging.basicConfig介绍 2. 精确到毫秒&#xff0c;打印时间 方法一&#xff1a;使用datetime 方法二&#xff1a;使用time 一、Python元编程…

【Git】git reflog git log

前言 日常开发过程中&#xff0c;我们经常会遇到要进行版本回退的情况&#xff0c;这时候需要使用git reflog和git reset 命令 git reflog 常用命令&#xff1a; 1、git reflog -n 查看多少条 2、git reflog show origin 查看远程历史变动 git log 什么都不加默认显示当前分…

Python实现GA遗传算法优化循环神经网络回归模型(LSTM回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世…

代码随想录算法训练营之JAVA|第十八天| 235. 二叉搜索树的最近公共祖先

今天是第 天刷leetcode&#xff0c;立个flag&#xff0c;打卡60天&#xff0c;如果做不到&#xff0c;完成一件评论区点赞最高的挑战。 算法挑战链接 235. 二叉搜索树的最近公共祖先https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/descriptio…

springboot自定义错误消息

为了提供自定义错误消息提示&#xff0c;springboot在resources目录下&#xff0c;有一个文件ValidationMessages.properties 用于存储 验证错误的消息提示&#xff1a; 比如&#xff1a; 这样一个ValidationMessage.properties username.notempty用户名不能为空 username.len…

互联网宠物医院系统开发:数字化时代下宠物医疗的革新之路

随着人们对宠物关爱意识的提高&#xff0c;宠物医疗服务的需求也日益增加。传统的宠物医院存在排队等待、预约难、信息不透明等问题&#xff0c;给宠物主人带来了诸多不便。而互联网宠物医院系统的开发&#xff0c;则可以带来许多便利和好处。下面将介绍互联网宠物医院系统开发…

前端生成图片验证码怎么做?

##题记&#xff1a;我们实现一个功能首先想一下我们需要做哪些工作&#xff0c;比如我们需要生成一个随机的图片验证码&#xff0c;我们需要一个就是点击事件获取验证码&#xff0c;通过接口我们去获取图片路径进行渲染就行&#xff0c;这里边还要牵扯一件事情就是获取一个随机…