图论part4|827. 最大人工岛、127. 单词接龙、463. 岛屿的周长

news2025/3/16 6:03:46

827. 最大人工岛

  • 🔗:827. 最大人工岛 - 力扣(LeetCode)827. 最大人工岛 - 给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。返回执行此操作后,grid 中最大的岛屿面积是多少?岛屿 由一组上、下、左、右四个方向相连的 1 形成。 示例 1:输入: grid = [[1, 0], [0, 1]]输出: 3解释: 将一格0变成1,最终连通两个小岛得到面积为 3 的岛屿。示例 2:输入: grid = [[1, 1], [1, 0]]输出: 4解释: 将一格0变成1,岛屿的面积扩大为 4。示例 3:输入: grid = [[1, 1], [1, 1]]输出: 4解释: 没有0可以让我们变成1,面积依然为 4。 提示: * n == grid.length * n == grid[i].length * 1 <= n <= 500 * grid[i][j] 为 0 或 1https://leetcode.cn/problems/making-a-large-island/description/
  • 思路:
  • 代码:        
class Solution {
    /**
        思路:
            1. 先把已经存在的岛找出来,并且计算他们的面积(dfs)
            2. 遍历为0的点,计算加上附近的岛的面积之后的最大面积
            3. 去重:避免把一个相邻的岛的面积计算两遍
     */
    private final int[][] dirs = {{-1,0},{1,0},{0,1},{0,-1}};

    public int largestIsland(int[][] grid) {
        int n = grid.length;
        // 计算每一个存在的岛的面积
        List<Integer> area = new ArrayList<>();
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                if(grid[i][j] == 1)//找到小岛
                    area.add(dfs(grid, i, j, area.size()+2));
            }
        }
        // 
        int maxSquare = 0;
        Set<Integer> s = new HashSet<>();
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                //遍历为0的点,计算加上附近的岛的面积之后的最大面积
                if(grid[i][j] == 0){
                    int square = 1;
                    s.clear();
                    for(int[] dir: dirs){
                        int newi = dir[0] + i;
                        int newj = dir[1] + j;
                        if(newi>=0 && newj>=0 && newi<grid.length && newj < grid.length && grid[newi][newj]!=0 && s.add(grid[newi][newj])){
                            square += area.get(grid[newi][newj]-2);
                        }
                    }
                    maxSquare = Math.max(square, maxSquare);
                }
            }
        }
        // 考虑小岛不需要添加任何1的情况
        return maxSquare == 0 ? n*n : maxSquare;
    }

    private int dfs(int[][] grid, int row, int col, int island){
        // 标记小岛的编号
        grid[row][col] = island;

        int square = 1;
        for(int[] dir: dirs){
            int newr = row + dir[0];
            int newc = col + dir[1];
            if(newc>=0 && newr>=0 && newc<grid.length && newr < grid.length && grid[newr][newc]==1){
                // 计算岛屿的大小
                square += dfs(grid, newr, newc, island);
            }
        }
        return square;
    }
}

127.  单词接龙 

  • 🔗:127. 单词接龙 - 力扣(LeetCode)127. 单词接龙 - 字典 wordList 中从单词 beginWord 到 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk: * 每一对相邻的单词只差一个字母。 *  对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord 不需要在 wordList 中。 * sk == endWord给你两个单词 beginWord 和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0 。 示例 1:输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]输出:5解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。示例 2:输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]输出:0解释:endWord "cog" 不在字典中,所以无法进行转换。 提示: * 1 <= beginWord.length <= 10 * endWord.length == beginWord.length * 1 <= wordList.length <= 5000 * wordList[i].length == beginWord.length * beginWord、endWord 和 wordList[i] 由小写英文字母组成 * beginWord != endWord * wordList 中的所有字符串 互不相同https://leetcode.cn/problems/word-ladder/description/
  • 思路1:广度优先遍历
    • 用图论的思想去看待这道题,返回begin-->end的最短路径
  • 代码1(广度优先遍历)        
class Solution {
    /**
        beginword: -->   -->       -->    --> endword
            hit      hot      dot      dog       cog
        用图论的思想去看待这道题,begin--》end的最短路径
     */

    // to judge whether there is an edge
    private boolean isEdge(String cur, String next){
        if(cur.length()!=next.length()) return false;
        int diff = 0;
        for(int i=0; i<cur.length(); i++){
            if(diff > 1) return false;
            if(cur.charAt(i) != next.charAt(i)){
                diff++;
            }
        }
        return diff == 1;
    }

    // 
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> visited = new HashSet<>();
        if(!wordList.contains(endWord)) return 0;

        Queue<String> neighbours = new LinkedList<>();
        neighbours.add(beginWord);
        visited.add(beginWord);
        int length = 1;
        
        while(!neighbours.isEmpty()){
            int size = neighbours.size();
            for(int i=0; i<size; i++){
                String currentword = neighbours.poll();
                if(isEdge(currentword,endWord)) return length+1;
                for(String word: new HashSet<>(wordList)){
                    if(visited.contains(word)) continue;
                    if(isEdge(currentword,word)){
                        neighbours.add(word);
                        visited.add(word);
                    }
                }
            }
            // 现在的数值和endword间有边

            
            length++;
        }
        return 0;
    }
}
  • 思路2: 优化方式--用双向bfs缩短遍历的流程
    • 1. 除了visited(所有访问过的节点)之外,采用startvisited和endvisited存储前后向遍历的节点(非全部节点,而是要处理的新一层的节点)
    • 交替处理startvisited和endvisited中需要处理的数据,每次处理节点数小的那个list
    • 如果startvisited的下一层(nextvisited)中,包含endvisited中的元素,则表示找到了最短的路径
    • 图示:(来源weiwei)
  • 代码2:
    • public class Solution {
      
          public int ladderLength(String beginWord, String endWord, List<String> wordList) {
              // 第 1 步:先将 wordList 放到哈希表里,便于判断某个单词是否在 wordList 里
              Set<String> wordSet = new HashSet<>(wordList);
              if (wordSet.size() == 0 || !wordSet.contains(endWord)) {
                  return 0;
              }
      
              // 第 2 步:已经访问过的 word 添加到 visited 哈希表里
              Set<String> visited = new HashSet<>();
              // 分别用左边和右边扩散的哈希表代替单向 BFS 里的队列,它们在双向 BFS 的过程中交替使用
              Set<String> beginVisited = new HashSet<>();
              beginVisited.add(beginWord);
              Set<String> endVisited = new HashSet<>();
              endVisited.add(endWord);
      
              // 第 3 步:执行双向 BFS,左右交替扩散的步数之和为所求
              int step = 1;
              while (!beginVisited.isEmpty() && !endVisited.isEmpty()) {
                  // 优先选择小的哈希表进行扩散,考虑到的情况更少
                  if (beginVisited.size() > endVisited.size()) {
                      Set<String> temp = beginVisited;
                      beginVisited = endVisited;
                      endVisited = temp;
                  }
      
                  // 逻辑到这里,保证 beginVisited 是相对较小的集合,nextLevelVisited 在扩散完成以后,会成为新的 beginVisited
                  Set<String> nextLevelVisited = new HashSet<>();
                  for (String word : beginVisited) {
                      if (changeWordEveryOneLetter(word, endVisited, visited, wordSet, nextLevelVisited)) {
                          return step + 1;
                      }
                  }
      
                  // 原来的 beginVisited 废弃,从 nextLevelVisited 开始新的双向 BFS
                  beginVisited = nextLevelVisited;
                  step++;
              }
              return 0;
          }
      
      
          /**
           * 尝试对 word 修改每一个字符,看看是不是能落在 endVisited 中,扩展得到的新的 word 添加到 nextLevelVisited 里
           *
           * @param word
           * @param endVisited
           * @param visited
           * @param wordSet
           * @param nextLevelVisited
           * @return
           */
          private boolean changeWordEveryOneLetter(String word, Set<String> endVisited,
                                                   Set<String> visited,
                                                   Set<String> wordSet,
                                                   Set<String> nextLevelVisited) {
              char[] charArray = word.toCharArray();
              for (int i = 0; i < word.length(); i++) {
                  char originChar = charArray[i];
                  for (char c = 'a'; c <= 'z'; c++) {
                      if (originChar == c) {
                          continue;
                      }
                      charArray[i] = c;
                      String nextWord = String.valueOf(charArray);
                      if (wordSet.contains(nextWord)) {
                          if (endVisited.contains(nextWord)) {
                              return true;
                          }
                          if (!visited.contains(nextWord)) {
                              nextLevelVisited.add(nextWord);
                              visited.add(nextWord);
                          }
                      }
                  }
                  // 恢复,下次再用
                  charArray[i] = originChar;
              }
              return false;
          }
      }

105. 有向图的完全可达性 

  • 🔗:105. 有向图的完全可达性https://kamacoder.com/problempage.php?pid=1177
  • 思路:不难做,主要练习一下acm模式,用的是广度优先的搜索方式,用深度是一样的
  • 代码:
    import java.util.*;
    
    class Main{
        private static Set<Integer> visited = new HashSet<>();
    
        public static void main(String[] args){
            Scanner scanner = new Scanner(System.in);
            int num_node = scanner.nextInt();
            int num_edge = scanner.nextInt();
            // if there is only 1 node
            //if(num_node==1) return 1;
            List<int[]> edges  = new ArrayList<>();
    
            for(int i=0 ;i<num_edge; i++){
                int[] edge = new int[2];
                edge[0] = scanner.nextInt();
                edge[1] = scanner.nextInt();
                edges.add(edge);
            }
    
    
            int currentNode = 1;
            Queue<Integer> que = new LinkedList<>();
            que.add(currentNode);
            visited.add(currentNode);
            
            while(!que.isEmpty()){
                int size = que.size();
                for(int j=0; j<size; j++){
                    currentNode = que.poll();
                    
                    for(int[] edge1: edges){
                        //
                        // System.out.println(edge1[0]+" "+edge1[1]);
                        if(edge1[0] == currentNode){
                            // 如果加不进去代表重复visited了
                            if(visited.add(edge1[1])){
                                que.add(edge1[1]);
                                
                            }
                        }
                    }
                }
            }
    
            if(visited.size()==num_node)
                System.out.println(1);
            else
                System.out.println(-1);
    
        }
    
    }

463. 岛屿的周长

  • 🔗:463. 岛屿的周长 - 力扣(LeetCode)463. 岛屿的周长 - 给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。 示例 1:[https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/12/island.png]输入:grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]输出:16解释:它的周长是上面图片中的 16 个黄色的边示例 2:输入:grid = [[1]]输出:4示例 3:输入:grid = [[1,0]]输出:4 提示: * row == grid.length * col == grid[i].length * 1 <= row, col <= 100 * grid[i][j] 为 0 或 1https://leetcode.cn/problems/island-perimeter/description/
  • 思路:深度优先搜索
    • dfs遍历的方式可扩展至统计多个岛屿各自的周长。

  • 代码:
    class Solution {
        int[][] dirs = {{-1,0},{1,0},{0,1},{0,-1}};
    
        public int islandPerimeter(int[][] grid) {
            int circle = 0;
            int m = grid.length;
            int n = grid[0].length;
            for(int i=0; i<m; i++){
                for(int j=0; j<n; j++){
                    if(grid[i][j]==1){
                        circle = dfs(grid, i, j);
                        return circle;
                    }
                }
            }
            return circle;    
        }
    
        private int dfs(int[][] grid, int row, int column){
            if(grid[row][column]==2) return 0;
            int circle = 0;
            grid[row][column] = 2;
            for(int[] dir: dirs){
                int x = row + dir[0];
                int y = column + dir[1];
                if(x<0 || y<0 || x >= grid.length || y >= grid[0].length || grid[x][y] == 0){
                    circle += 1;
                }
                else if(grid[x][y] == 1){
                    circle += dfs(grid, x, y);
                }
            }
            return circle;
        }
    }

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

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

相关文章

Java高级-05.反射的作用、应用场景

一.反射的作用 二.案例 Student.class package com.njau.d2_reflect;public class Student {private String name;private int age;private char sex;private double height;private String hobby;public Student(String name, int age, char sex, double height, String …

cherry-studio - 多模型支持的跨平台 AI 桌面助手

GitHub&#xff1a;https://github.com/CherryHQ/cherry-studio 更多AI开源软件&#xff1a;发现分享好用的AI工具、AI开源软件、AI模型、AI变现 - 小众AI 一款支持多种大语言模型服务的跨平台桌面客户端&#xff0c;兼容 Windows、Linux 和 macOS 系统。它支持主流云端模型&am…

Uniapp 开发 App 端上架用户隐私协议实现指南

文章目录 引言一、为什么需要用户隐私协议&#xff1f;二、Uniapp 中实现用户隐私协议的步骤2.1 编写隐私协议内容2.2 在 Uniapp 中集成隐私协议2.3 DCloud数据采集说明2.4 配置方式3.1 Apple App Store3.2 Google Play Store 四、常见问题与解决方案4.1 隐私协议内容不完整4.2…

LeetCode 环形链表II:为什么双指针第二次会在环的入口相遇?

快慢指针 为什么相遇后让快指针回到起点&#xff0c;再让快指针和慢指针都一步一步地走&#xff0c;它们就会在环的入口相遇&#xff1f; 复杂度 时间复杂度: O(n) 空间复杂度: O(1) public ListNode detectCycle(ListNode head) {ListNode slow head, fast head;ListNode …

如何处理PHP中的编码问题

如何处理PHP中的编码问题 在PHP开发过程中&#xff0c;编码问题是一个常见且棘手的问题。无论是处理用户输入、数据库交互&#xff0c;还是与外部API通信&#xff0c;编码问题都可能导致数据乱码、解析错误甚至安全漏洞。本文将深入探讨PHP中的编码问题&#xff0c;并提供一些…

【动手学强化学习】part8-PPO(Proximal Policy Optimization)近端策略优化算法

阐述、总结【动手学强化学习】章节内容的学习情况&#xff0c;复现并理解代码。 文章目录 一、算法背景1.1 算法目标1.2 存在问题1.3 解决方法 二、PPO-截断算法2.1 必要说明2.2 伪代码算法流程简述 2.3 算法代码2.4 运行结果2.5 算法流程说明 三、疑问四、总结 一、算法背景 …

游戏引擎学习第159天

回顾与今天的计划 我们在完成一款游戏的制作。这个游戏没有使用任何引擎或新库&#xff0c;而是从零开始编写的完整游戏代码库&#xff0c;您可以自行编译它&#xff0c;并且它是一个完整的游戏。更特别的是&#xff0c;这个游戏甚至没有使用显卡&#xff0c;所有的渲染工作都…

内网攻防——红日靶场(一)

在学习内网的过程中有着诸多不了解的内容。希望能借下面的靶场来步入内网的大门。 一、准备阶段 首先准备好我们的虚拟机 之前有学过关于&#xff1a;工作组、域、DC的概念。 了解一下此时的网络拓扑图 1.设置网络VMnet1和Vmnet8 将VMnet1作为内网&#xff0c;VMnet8作为外…

协议-LoRa-Lorawan

是什么? LoRa是低功耗广域网通信技术中的一种,是Semtech公司专有的一种基于扩频技术的超远距离无线传输技术。LoRaWAN是为LoRa远距离通信网络设计的一套通讯协议和系统架构。它是一种媒体访问控制(MAC)层协议。LoRa = PHY Layer LoRaWAN = MAC Layer功耗最低,传输最远 ![ …

redis主从搭建

1. 哨兵 1.1 ⼈⼯恢复主节点故障 Redis 的主从复制模式下&#xff0c;⼀旦主节点由于故障不能提供服务&#xff0c;需要⼈⼯进⾏主从切换&#xff0c;同时⼤量 的客⼾端需要被通知切换到新的主节点上&#xff0c;对于上了⼀定规模的应⽤来说&#xff0c;这种⽅案是⽆法接受的&…

Linux中Gdb调试工具常用指令大全

1.gdb的安装 如果你是root用户直接用指令 &#xff1a;yum install gdb &#xff1b;如果你是普通用户用指令&#xff1a;sudo yum install gdb&#xff1b; 2.gdb调试前可以对你的makefile文件进行编写&#xff1a; 下面展示为11.c文件编写的makefile文件&#xff1a; code…

操作系统-八股

进程基础&#xff1a; 进程定义&#xff1a;运行中的程序&#xff0c;有独立的内存空间和地址&#xff0c;是系统进行资源调度和分配的基本单位。 并发&#xff0c;并行 并发就是单核上面轮询&#xff0c;并行就是同时执行&#xff08;多核&#xff09;&#xff1b; 进程上下…

ICLR2025 | SLMRec: 重新思考大语言模型在推荐系统中的价值

note 问题背景&#xff1a;序列推荐&#xff08;SR&#xff09;任务旨在预测用户可能的下一个交互项目。近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;在SR系统中表现出色&#xff0c;但它们巨大的规模使得在实际平台中应用变得低效和不切实际。 研究动机&…

71.HarmonyOS NEXT PicturePreviewImage组件深度剖析:从架构设计到核心代码实现

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT PicturePreviewImage组件深度剖析&#xff1a;从架构设计到核心代码实现 (一) 文章目录 HarmonyOS NEXT PicturePreviewImage组件深…

简单实现京东登录页面

Entry Component struct Index {State message: string ;build() { Column(){//顶部区域Row(){Image($r(app.media.jd_cancel)).width(20).height(20)Text(帮助)}.width(100%).justifyContent(FlexAlign.SpaceBetween)//logo图标Image($r(app.media.jd_logo)).width(250).heig…

9.贪心算法

简单贪心 1.P10452 货仓选址 - 洛谷 #include<iostream> #include<algorithm> using namespace std;typedef long long LL; const int N 1e510; LL a[N]; LL n;int main() {cin>>n;for(int i 1;i < n;i)cin>>a[i];sort(a1,a1n);//排序 LL sum 0…

大模型训练全流程深度解析

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。https://www.captainbed.cn/north 文章目录 1. 大模型训练概览1.1 训练流程总览1.2 关键技术指标 2. 数据准备2.1 数据收集与清洗2.2 数据…

每日一题---单词搜索(深搜)

单词搜索 给出一个二维字符数组和一个单词&#xff0c;判断单词是否在数组中出现&#xff0c; 单词由相邻单元格的字母连接而成&#xff0c;相邻单元指的是上下左右相邻。同一单元格的字母不能多次使用。 数据范围&#xff1a; 0 < 行长度 < 100 0 < 列长度 <…

插入排序c++

插入排序的时间复杂度为O&#xff08;N^2&#xff09;&#xff0c;和冒泡排序的时间复杂度相同&#xff0c;但是在某些情况下插入排序会更优。 插入排序的原理是&#xff1a;第1次在0~0范围内排序&#xff0c;第2次在0~1范围内排序&#xff0c;第3次在0~2范围内排序……相当于…

Swagger 从 .NET 9 中删除:有哪些替代方案

微软已经放弃了对 .NET 9 中 Swagger UI 包 Swashbuckle 的支持。他们声称该项目“不再由社区所有者积极维护”并且“问题尚未得到解决”。 这意味着当您使用 .NET 9 模板创建 Web API 时&#xff0c;您将不再拥有 UI 来测试您的 API 端点。 我们将调查是否可以在 .NET 9 中使用…