秋招突击——算法练习——8/26——图论——200-岛屿数量、994-腐烂的橘子、207-课程表、208-实现Trie

news2024/11/13 7:56:40

文章目录

    • 引言
    • 正文
      • 200-岛屿数量
        • 个人实现
      • 994、腐烂的橘子
        • 个人实现
        • 参考实现
      • 207、课程表
        • 个人实现
        • 参考实现
      • 208、实现Trie前缀树
        • 个人实现
        • 参考实现
    • 总结

引言

正文

200-岛屿数量

题目链接
在这里插入图片描述

个人实现
  • 我靠,这道题居然是腾讯一面的类似题,那道题是计算最大的岛屿面积,如果当时没做出来,现在得哭死!好在做出来了!
  • 这道题单纯使用回溯实现的,然后修改一下地图的坐标就行了!但是修改了原来的地图坐标,这样做效果并不好,但是不这样做,又必须得复制一个原来的数组,这样不行!
class Solution {
    public int[][] DIRECT = {{0,1},{0,-1},{1,0},{-1,0}};
    public void dfs(int x,int y,char[][] grid){
        if(grid[x][y] == '0' || grid[x][y] == '2') return;
        else grid[x][y] = '2';

        // 遍历对应的四个方向
        int m = grid.length;
        int n = grid[0].length;
        for(int[] dir:DIRECT){
            if(
                x + dir[0] < m && y + dir[1] < n && 
                x + dir[0] >= 0  && y + dir[1] >= 0
                )
                dfs(x + dir[0],y + dir[1],grid);
        }
    }

    public int numIslands(char[][] grid) {
        int count = 0;  
        for(int i = 0;i < grid.length;i ++){
            for(int j = 0;j < grid[0].length;j ++){
                if(grid[i][j] == '1' ) {
                    dfs(i,j,grid);
                    count ++;
                }
            }
        }
        return count;
    }
}

在这里插入图片描述

994、腐烂的橘子

  • 题目链接
    在这里插入图片描述
    注意
  • 不会存在空图的情况
个人实现

思路分析

  • 首先不能让所有橘子都变坏,就返回-1,如果不会错,笔试的话,直接返回-1即可。具体见下图,可以看到通过了88个样例。这个技巧在华师大的预推免的笔试中已经见过了,很难受!这个技巧得敏感一点!

在这里插入图片描述

  • 正常思路还是使用BFS进行遍历,知道遍历不了,应为通过BFS的遍历方式和橘子腐烂的方式更像。
class Solution {
    public int[][] DIRECTION = {{0,1},{0,-1},{1,0},{-1,0}};

    public int orangesRotting(int[][] grid) {
        Queue<int[]> q = new ArrayDeque<>();
        Queue<int[]> q2 = new ArrayDeque<>();

        int res = 0;
        // 如果弹出栈的橘子是好橘子,跳过,如果是坏橘子,执行入站
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j] == 2) {
                    // 入栈开始烂橘子
                    int count = 0;
                    q.offer(new int[] { i, j });
                    while (!q.isEmpty()) {
                        int[] curNode = q.poll();
                        int x = curNode[0];
                        int y = curNode[1];
                        for (int[] dir : DIRECTION) {
                            // 遍历四个可以扩展的方向
                            if (x + dir[0] >= 0 && x + dir[0] < grid.length &&
                                    y + dir[1] >= 0 && y + dir[1] < grid[0].length) {
                                // 遍历到好橘子,先改变状态,然后直接入站        
                                if (grid[x + dir[0]][y + dir[1]] == 1) {
                                    grid[x + dir[0]][y + dir[1]] = 2;
                                    q2.offer(new int[] { x + dir[0], y + dir[1] });
                                }
                            }
                        }
                        // 这里需要交换对应的节点
                        if(q.isEmpty() && !q2.isEmpty()){
                            Queue<int[]> temp = q;
                            q = q2;
                            q2 = temp;
                            count ++;
                        }
                    }
                    res = Math.max(res,count ++);
                }
            }
        }
         for (int i = 0; i < grid.length; i++) 
            for (int j = 0; j < grid[0].length; j++)
                if(grid[i][j] == 1) return -1; 
        return res;
    }
}

在这里插入图片描述
总结

  • 这里只能过一半,并不能过所有的样例,因为存在多个烂橘子,然后同时开始腐坏周围的橘子的情况,所以这里就不能抓住一个烂橘子,然后进行遍历,应该是先加上所有的烂橘子,然后所有烂橘子每次都想外扩展一圈,知道没有好橘子了,然后在遍历一下,但是面试的时候可能已经挂了,这里已经没时间了,直接看的样例吧!
参考实现
  • 这里先遍历一次,然后计算一下好橘子和烂橘子的数量,同时将所有的烂橘子加入到一个列表中,然后每一分钟,将所有烂橘子的周围的好橘子都变烂,然后加入到列表中,直到列表为空!
  • 具体实现如下,这里还是自己在原来的代码上修改的!
class Solution {
    public int[][] DIRECTION = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };

    public int orangesRotting(int[][] grid) {
        Queue<int[]> q = new ArrayDeque<>();
        int freshNum = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j] == 1)
                    freshNum++;
                if (grid[i][j] == 2)
                    q.offer(new int[] { i, j });
            }
        }
        int orangeNum = q.size() + freshNum;
        if(orangeNum == 0)  return 0;

        int count = -1;
        while (!q.isEmpty()) {
            count ++;
            int n = q.size();
            for (int i = 0; i < n; i++) {
                int[] curNode = q.poll();
                int x = curNode[0];
                int y = curNode[1];
                for (int[] dir : DIRECTION) {
                    // 遍历四个可以扩展的方向
                    if (x + dir[0] >= 0 && x + dir[0] < grid.length &&
                            y + dir[1] >= 0 && y + dir[1] < grid[0].length) {
                        // 遍历到好橘子,先改变状态,然后直接入站
                        if (grid[x + dir[0]][y + dir[1]] == 1) {
                            grid[x + dir[0]][y + dir[1]] = 2;
                            freshNum --;
                            q.offer(new int[] { x + dir[0], y + dir[1] });
                        }
                    }
                }
            }
        }

        if(freshNum != 0) return -1;
        return count;
    }
}

在这里插入图片描述

207、课程表

  • 题目链接
    在这里插入图片描述
个人实现

思路分析

  • 前缀课程这个想到了并查集,但是这个是检测是否成环的,这个有点忘记了,成环我记得有一个特定的算法,想想看!
  • 使用并查集,然后进行判定,父节点是否是自己!

在这里插入图片描述

上述两种情况并不好进行鉴别,这里应该修改一下,如果是初始状态,就默认是-1,然后如果是其他节点,就不是-1,看看行不行!

class Solution {
    int[] f;
    boolean flag = false;
    
    public int find(int idx){
        if(f[idx] == idx ){
            flag = true;
            return idx;
        }
        if(f[idx] == -1){
            return idx;
        }else{
            return find(f[idx]);
        }
    }

    public void union(int a,int b){
        // a节点是子节点,b节点是父节点
        
        // 找到对应的父亲节点
        int fa = find(a);
        int fb = find(b);
        if(fa == fb)    {
            flag = true;
        }

        // 设置对应的父亲节点
        f[fb] = fa;
    }
    
    public boolean canFinish(int numCourses, int[][] prerequisites) {
    
        // 创建并初始化父节点的数组
        f = new int[numCourses];
        for(int i = 0;i < numCourses;i ++) f[i] = -1;
        
        // 绑定父亲节点之间的关系
        for(int[] pre:prerequisites)    union(pre[0],pre[1]);

        // 这里要判定一下,是否没一门课都有自己的前导课程
        if(flag)    return false;
        return true;

    }
}

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

  • 确实没有环,但是插入3的关系时,还是出了问题,如果按照我这样写,3的先导课程已经插入过了,下次插入,会找到的祖先相同,直接返回false

又修改了一下,这里仅仅区分原始的单个节点成环状态,如果某个节点匹配到自己,就是实际上成环,直接退出

具体如下

class Solution {
    int[] f;
    
    public int find(int idx){
        if(f[idx] == -1 || f[idx] == idx){
            return idx;
        }else{
            return find(f[idx]);
        }
    }

    public void union(int a,int b){
        // a节点是子节点,b节点是父节点
        
        // 找到对应的父亲节点
        int fa = find(a);
        int fb = find(b);

        // 设置对应的父亲节点
        f[fb] = fa;
    }
    
    public boolean canFinish(int numCourses, int[][] prerequisites) {
    
        // 创建并初始化父节点的数组
        f = new int[numCourses];
        for(int i = 0;i < numCourses;i ++) f[i] = -1;
        
        // 绑定父亲节点之间的关系
        for(int[] pre:prerequisites)    union(pre[0],pre[1]);

        // 这里要判定一下,是否没一门课都有自己的前导课程
        for(int i = 0 ;i < numCourses;i ++) if(f[i] == i)   return false;
        return true;

    }
}

在这里插入图片描述
在这里插入图片描述
上述算法不行的,因为会出现一个问题,就是一个节点会有多个父节点,但是使用并查集,只能保存一个父节点,所以还是只能想到DFS或者BFS,但是不想这样做,没有任何意义!

参考实现

无向图成环——染色原理-三色

有向图求拓扑排序的问题——这是一个模版题

  • 遍历所有入度为零的点,对应子节点入度减一,入度为零加入队列,不能遍历完所有节点,就是有环

下图是针对成环的度数操作
在这里插入图片描述
下图是针对不成环的操作
在这里插入图片描述

class Solution {
    
    public boolean canFinish(int n, int[][] prerequisites) {
        // 创建邻接表,并进行赋值
        List<List<Integer>> grid = new ArrayList<>();
        int[] inNum = new int[n + 1];
        for(int i = 0;i <= n;i ++)  grid.add(new ArrayList<>());
        for(int[] edge: prerequisites){
            grid.get(edge[0]).add(edge[1]);
            inNum[edge[1]] ++;
        }

        // 遍历所有的节点,找到所有入度为零的点,加入队列进行遍历
        Queue<Integer> q = new ArrayDeque<>();
        for(int i = 0;i < n;i ++) 
            if(inNum[i] == 0)
                q.offer(i);

        // 然后遍历队列中的点,并将其子节点的入度减一
        int visitedNum = q.size();
        while(!q.isEmpty()){
            int curNode = q.poll();
            // 遍历当前节点的所有后继子节点,并进行访问
            for(int i :grid.get(curNode)){
                inNum[i] --;
                if(inNum[i] == 0)   {
                    q.offer(i);
                    visitedNum ++;
                }
            }
        } 

        if(visitedNum == n) return true;
        return false;
    }
}

在这里插入图片描述
总结

  • 这类图论的题目,这些基础的定理想起来了,就是会做,没想起来,只能硬做,没什么办法,具体需要考虑的因素也就只有出度、入度,然后成环也就是不同的情况而已!

208、实现Trie前缀树

  • 题目链接
    在这里插入图片描述
    注意
  • 这个会不会有多个字符串插入?会的
  • startwith是判定是否为前缀
  • search是找是否存在对应的字符串
个人实现

思路分析

  • 如果只有一个search,使用一个map就能够简单实现,找得到就是true,找不到就是false。或者说使用一个set也是完全可以的。
  • 现在如果只有一个startwith,就需要建造一个类似霍夫曼匹配树的东西,具体见下图。
    • 但是这个链表,太费空间了,想想每一个节点都要有对应的指针的往下才行,不过先实现一下,能通过就行!

在这里插入图片描述

个人实现

class Trie {
    class Node{
        char v;
        Map<Character,Node> map;
        Node(char c){
            v = c;
            map = new HashMap<>();
        }
        void put(Node next){
            map.put(next.v,next);
        }
    }
    Set<String> set;
    Map<Character,Node> sourMap;

    public Trie() {
        sourMap = new HashMap<>();
        set = new HashSet<>();

    }
    
    public void insert(String word) {
        set.add(word);
        // 先找到第一个字母对应的链表的位置
        char curChar = word.charAt(0);
        Node curNode;
        if(sourMap.containsKey(curChar)){
            // 包含当前节点
            curNode = sourMap.get(curChar);
        }else{
            // 不包含当前节点
            curNode  = new Node(curChar);
            sourMap.put(curChar,curNode);
        }
        // 构造对应的链表节点 
        for(int i = 1;i < word.length();i ++){
            char nextChar = word.charAt(i);
            // 判断当前的curNode是否包含了对应的节点的
            Node nextNode = null;
            if(!curNode.map.containsKey(nextChar))
            {
                nextNode = new Node(nextChar);
                curNode.put(nextNode);
            }else{
                nextNode = curNode.map.get(nextChar);
            }
            curNode = nextNode;
        }
    }
    
    public boolean search(String word) {
        return set.contains(word);
    }
    
    public boolean startsWith(String prefix) {
        char curChar = prefix.charAt(0);
        if(!sourMap.containsKey(curChar))   return false;
        Node curNode = sourMap.get(curChar);
        for(int i = 1;i < prefix.length();i ++){
            char nextChar = prefix.charAt(i);
            // 判断当前的curNode是否包含了对应的节点的
            if(!curNode.map.containsKey(nextChar))
            {
                return false;
            }
            curNode = curNode.map.get(nextChar);
        }
        return true;
    }
}

总结

  • 靠,我都惊讶了,一次过了,逻辑没啥问题!难得!
  • 总觉得我实现的不够光彩,还是有很多的问题,空间复杂度太高了,真的爆炸!
参考实现
  • 基本的思路还是一样的,不过增加了一个叶子节点的boolean状态值,判定是否存在对应的以叶子节点为结尾的序列是否存在。
  • 这里是使用数组来保存对应的后继节点的,然后默认是26个小写字母,所以会使用对应的字符串序列进行表示!
class Trie {
    class Node{
        boolean isExist;
        Node[] son;
        Node(){
            isExist = false;
            son = new Node[26];
        }
    }

    Node root;
    
    public Trie() {
       root = new Node();
    }
    
    public void insert(String word) {
        Node curNode = root;
        for(char x:word.toCharArray()){
            int idx = x - 'a';
            if(curNode.son[idx] == null){
                curNode.son[idx] = new Node();
            }
            curNode = curNode.son[idx];
        }
        curNode.isExist = true;
    }
    
    public boolean search(String word) {
        Node curNode = root;
        for(char x:word.toCharArray()){
            int idx = x - 'a';
            if(curNode.son[idx] == null){
                return false;
            }
            curNode = curNode.son[idx];
        }
        return curNode.isExist;
    }
    
    public boolean startsWith(String prefix) {
        Node curNode = root;
        for(char x:prefix.toCharArray()){
            int idx = x - 'a';
            if(curNode.son[idx] == null)    return false;
            curNode = curNode.son[idx];
        }
        return true;
    }
}

在这里插入图片描述
总结

  • 这个代码效率确实更高,写起来更加简洁!

总结

  • hot100的图论基本上都过了,总体来说还是其他部分要简单,继续二刷其他题目!保证每道题都能刷个两三遍!这样笔试还有手撕就不害怕了!

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

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

相关文章

《分析模式》2024中译本-前言-01(加红色标注)

写在前面 今天开始&#xff0c;我们逐渐发布一些《分析模式》2024中译本的译文。 红色字体标出的文字&#xff0c;表示我认为之前的译本可能会让读者产生误解的地方。 感兴趣的读者&#xff0c;可以对照之前译本以及原文&#xff0c;捉摸一下为什么要标红。 主要原因当然是…

基于SpringBoot+Vue+MySQL的小区物业管理系统

系统背景 在当今信息化高速发展的时代&#xff0c;小区物业管理正经历着从传统模式向智能化、高效化转型的深刻变革。这一转变的核心驱动力&#xff0c;正是小区物业管理系统的全面智能化升级。该系统不仅极大地提升了物业管理的效率与精确度&#xff0c;还深刻重塑了物业与业主…

数分基础(03-1)客户特征分析

文章目录 客户特征分析1. 数据集2. 思路与步骤2.1 特征工程2.2 识别方法2.3 可视化 3. 分析准备3.1 读取数据集3.2 识别不同客户群体3.2.1 使用K-Means聚类进行初步细分3.2.2 关于聚类方法&#xff08;1&#xff09;特征缩放1&#xff09;平衡特征对模型的影响力&#xff0c;避…

通过ICMP判断网络故障

一、ICMP协议 Internet控制消息协议ICMP(Internet Control Message Protocol)是IP协议的辅助协议。 ICMP协议用来在网络设备间传递各种差错和控制信息&#xff0c;对于收集各种网络信息、诊断和排除各种网络故障等方面起着至关重要的作用。 TypeCode描述备注00Echo Replyping…

C++从入门到起飞之——list使用 全方位剖析!

​ &#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1、迭代器 2、push_back与emplace_back 3、list成员函数sort与库sort比较 4、merge 5、uniqu…

2024117读书笔记|《李煜词(果麦经典)》——一壶酒,一竿身,快活如侬有几人?一片芳心千万绪,人间没个安排处

2024117读书笔记|《李煜词&#xff08;果麦经典&#xff09;》——一壶酒&#xff0c;一竿身&#xff0c;快活如侬有几人&#xff1f;一片芳心千万绪&#xff0c;人间没个安排处 《李煜词&#xff08;果麦经典&#xff09;》李煜的词很美&#xff0c;插图也不错&#xff0c;很值…

基于粒子群优化算法的六自由度机械臂三维空间避障规划

摘要&#xff1a;本研究旨在解决机械臂在复杂环境中避障路径规划的问题。本文提出了一种利用粒子群优化算法&#xff08;PSO&#xff09;进行机械臂避障规划的方法&#xff0c;通过建立机械臂的运动模型&#xff0c;将避障问题转化为优化问题。PSO算法通过模拟群体中个体的社会…

ggml 简介

ggml是一个用 C 和 C 编写、专注于 Transformer 架构模型推理的机器学习库。该项目完全开源&#xff0c;处于活跃的开发阶段&#xff0c;开发社区也在不断壮大。ggml 和 PyTorch、TensorFlow 等机器学习库比较相似&#xff0c;但由于目前处于开发的早期阶段&#xff0c;一些底层…

8月28c++

c手动封装顺序表 #include <iostream>using namespace std; using datatype int;//类型重命名struct SeqList { private:datatype *data;//顺序表数组int size0;//数组大小int len0;//顺序表实际长度 public:void init(int s);//初始化函数bool empty();//判空函数bool …

python有主函数吗

python和C/Java不一样&#xff0c;没有主函数一说&#xff0c;也就是说python语句执行不是从所谓的主函数main开始的。 当运行单个python文件时&#xff0c;如运行a.py&#xff0c;这个时候a的一个属性__name__是__main__。 当调用某个python文件时&#xff0c;如b.py调用a.p…

HDD介绍

HDD是“Hard Disk Drive”的缩写&#xff0c;意为“硬盘驱动器”&#xff0c;是计算机中用于存储数据和程序的主要设备之一。 硬盘有机械硬盘(Hard Disk Drive&#xff0c;HDD)和固态硬盘(SSD)之分。机械硬盘即是传统普通硬盘&#xff0c;主要由&#xff1a;盘片&#xff0c;磁…

2024年华侨生联考英语真题全析:难度变化与备考策略

导读 在前面我们和大家一起分享了2024年华侨生联考各科真题的难度情况。今天我们就来和大家具体的看一下2024年港澳台华侨生联考英语真题试卷具体分析哈。 听力部分 今年的听力和去年的听力总体难度差别不大&#xff0c;一段听力材料对应一道听力题目&#xff08;简称一对一…

谐波电抗器选择的最佳方法

选择谐波电抗器的最佳方法取决于系统的具体要求和条件。 以下是选择谐波电抗器时需要考虑的关键因素和方法&#xff1a; 1、确定系统谐波频率 谐波分析&#xff1a;使用谐波分析仪测量系统中的谐波频率&#xff0c;确定主要的谐波频率和幅值。谐波电抗器的选择需要针对这些谐…

2024年6月GSEP(python)一级认证真题讲解

注意&#xff01;做题时长为2小时&#xff0c;孩子做完题目后对照讲解视频和讲解分析&#xff0c;针对薄弱点&#xff0c;进行有效的专项提高。 &#x1f451;讲解视频 &#xff08;暂无&#xff09; &#x1f451;讲解分析 1 单选题&#xff08;每题 2 分&#xff0c;共 3…

【CVPR‘23】CompletionFormer:用于深度补全的 Transformer 网络!已开源

【CVPR23】CompletionFormer:用于深度补全的 Transformer 网络! 摘要方法3.1 RGB 和深度嵌入3.2 联合卷积注意力和 Transformer 编码器3.3 解码器3.4 SPN 精化和损失函数主要贡献实验结果论文地址:https://openaccess.thecvf.com/content/CVPR2023/papers/Zhang_CompletionF…

C语言指针重学

学习要纲:建议掌握 gdb调试(b ,d ,fin ,bt ,print ,awatch ,up ,down ,set pretty等) SourceInsight软件看代码(全局搜索 文件搜索等) git如何调取分支合并(git branch,git blame,git log,git pull,git reset --hard等) 等内容,下面是对于指针的一个重新学习. C语言的指针&…

如何使用ssm实现基于java web的计算机office课程平台设计与实现+vue

TOC ssm277基于java web的计算机office课程平台设计与实现vue 绪论 1.1 研究背景 现在大家正处于互联网加的时代&#xff0c;这个时代它就是一个信息内容无比丰富&#xff0c;信息处理与管理变得越加高效的网络化的时代&#xff0c;这个时代让大家的生活不仅变得更加地便利…

WireShark网络分析~部署方式

一、《Wireshark网络分析就这么简单》 第一章学习 声明&#xff1a;文章只限于网络学习和实验&#xff0c;请遵守《网络安全法》。 第一章问题一&#xff1a;两台服务器A和B的网络配置如下(见图1)&#xff0c;B的子网掩码本应该是255.255.255.0&#xff0c;被不小心配成了255.…

LeetCode 热题100-37 二叉树的最大深度

二叉树的最大深度 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&#xff1a;ro…

py 可视化图层

五张图&#xff1a;数据资源可联系1493175691qq.com import numpy as np import matplotlib.pyplot as plt from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter import cartopy.crs as ccrs import cartopy.feature as cfeature from cartopy.io.shaperead…