Day47 | 110.字符串接龙 105.有向图的完全可达性 106.岛屿的周长

news2024/9/21 12:45:02

110.字符串接龙

110. 字符串接龙

题目

题目描述

字典 strList 中从字符串 beginStr 和 endStr 的转换序列是一个按下述规格形成的序列: 

1. 序列中第一个字符串是 beginStr。

2. 序列中最后一个字符串是 endStr。 

3. 每次转换只能改变一个字符。 

4. 转换过程中的中间字符串必须是字典 strList 中的字符串,且strList里的每个字符串只用使用一次。 

给你两个字符串 beginStr 和 endStr 和一个字典 strList,找到从 beginStr 到 endStr 的最短转换序列中的字符串数目。如果不存在这样的转换序列,返回 0。

输入描述

第一行包含一个整数 N,表示字典 strList 中的字符串数量。 第二行包含两个字符串,用空格隔开,分别代表 beginStr 和 endStr。 后续 N 行,每行一个字符串,代表 strList 中的字符串。

输出描述

输出一个整数,代表从 beginStr 转换到 endStr 需要的最短转换序列中的字符串数量。如果不存在这样的转换序列,则输出 0。

思路

  1. 初始化
    • 使用HashSetset)来存储wordList中的所有单词,以便快速检查某个单词是否存在于列表中。
    • 使用Queuequeue)来存储待处理的单词,这些单词是当前已经找到但尚未探索完所有可能变化的单词。
    • 使用HashMapvisitMap)来记录每个单词被访问时的路径长度(即距离起始单词的步数)。
  2. BFS过程
    • 将起始单词加入队列和访问记录中,并设置其路径长度为1。
    • 循环处理队列中的单词,直到队列为空。
    • 对于每个单词,尝试替换其每个位置的字符为'a'到'z'之间的所有字符,生成新的单词。
    • 检查新单词是否为目标单词,如果是,则返回当前路径长度加1。
    • 如果新单词存在于set中且之前未被访问过,则将其加入队列和访问记录中,并更新其路径长度。
  3. 结果
    • 如果遍历完所有可能的单词后仍未找到目标单词,则返回0,表示无法从起始单词到达目标单词。

代码

import java.util.*;

public class Main {
    // BFS方法
    public static int ladderLength(String beginWord, String endWord, List<String> wordList) {
        // 使用set作为查询容器,效率更高
        HashSet<String> set = new HashSet<>(wordList);
        
        // 声明一个queue存储每次变更一个字符得到的且存在于容器中的新字符串
        Queue<String> queue = new LinkedList<>();
        
        // 声明一个hashMap存储遍历到的字符串以及所走过的路径path
        HashMap<String, Integer> visitMap = new HashMap<>();
        queue.offer(beginWord);
        visitMap.put(beginWord, 1);
        
        while (!queue.isEmpty()) {
            String curWord = queue.poll();
            int path = visitMap.get(curWord);

            for (int i = 0; i < curWord.length(); i++) {
                char[] ch = curWord.toCharArray();
                // 每个位置尝试26个字母
                for (char k = 'a'; k <= 'z'; k++) {
                    ch[i] = k;

                    String newWord = new String(ch);
                    if (newWord.equals(endWord)) return path + 1;
                    
                    // 如果这个新字符串存在于容器且之前未被访问到
                    if (set.contains(newWord) && !visitMap.containsKey(newWord)) {
                        visitMap.put(newWord, path + 1);
                        queue.offer(newWord);
                    }
                }
            }
        }

        return 0;
    }
    
    public static void main (String[] args) {
        /* code */
        // 接收输入
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        sc.nextLine();
        String[] strs = sc.nextLine().split(" ");
        
        List<String> wordList = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            wordList.add(sc.nextLine());
        }
        
        // wordList.add(strs[1]);
        
        // 打印结果
        int result = ladderLength(strs[0], strs[1], wordList);
        System.out.println(result);
    }
}

易错点

  1. 输入处理
    • 在读取N(单词列表的大小)后,需要调用sc.nextLine()来跳过行尾的换行符,否则在读取第一个单词时会出错。
    • 题目中可能未明确说明,但通常假设strs[0]是起始单词,strs[1]是目标单词,而剩余的单词在wordList中。然而,在你的代码中,你直接从sc.nextLine()读取了所有单词(除了N),这可能不是题目意图。你应该根据题目要求来读取这些单词。
  2. 字符串处理
    • 在替换字符时,需要确保使用字符数组来避免在循环中多次创建新的字符串对象。
    • 替换字符后,应检查新生成的单词是否存在于set中且之前未被访问过。
  3. 边界条件
    • 如果wordList为空或未包含起始单词和目标单词,应返回适当的值(通常是0,表示无法到达)。
    • 如果起始单词和目标单词相同,应返回1(因为不需要任何变化)。

105.有向图的完全可达性

105. 有向图的完全可达性

题目

题目描述

给定一个有向图,包含 N 个节点,节点编号分别为 1,2,...,N。现从 1 号节点开始,如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。

输入描述

第一行包含两个正整数,表示节点数量 N 和边的数量 K。 后续 K 行,每行两个正整数 s 和 t,表示从 s 节点有一条边单向连接到 t 节点。

输出描述

如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。

思路

  1. 输入处理:首先,程序通过Scanner类读取图的节点数n和边数m。然后,它初始化一个大小为n+1List<List<Integer>>类型的邻接表graph,其中每个内部列表代表一个节点的所有邻居节点。由于节点编号从1开始,但数组索引从0开始,因此需要大小为n+1的列表数组。

  2. 构建邻接表:通过读取每对相连的节点st,将t添加到s的邻居列表中。注意,这里的st是节点编号,不是索引,因此它们可以直接用作graph的索引(尽管实际上它们被用作索引时减1,因为内部索引是从0开始的)。

  3. 深度优先搜索:从节点1开始进行深度优先搜索。在搜索过程中,使用一个布尔数组visited来跟踪哪些节点已经被访问过。对于每个节点,如果它尚未被访问,则标记为已访问,并递归地访问其所有邻居。

  4. 检查访问情况:在DFS完成后,程序遍历visited数组,检查是否有任何节点未被访问。如果有任何节点未被访问,则输出-1表示不是所有节点都可从起始节点访问;如果所有节点都被访问,则输出1

代码

import java.util.ArrayList;  
import java.util.Arrays;  
import java.util.List;  
import java.util.Scanner;  
  
public class Main {  
  
    static void dfs(List<List<Integer>> graph, int key, boolean[] visited) {  
        if (visited[key]) {  
            return;  
        }  
        visited[key] = true;  
        List<Integer> keys = graph.get(key);  
        for (int neighbor : keys) {  
            // 深度优先搜索遍历  
            dfs(graph, neighbor, visited);  
        }  
    }  
  
    public static void main(String[] args) {  
        Scanner scanner = new Scanner(System.in);  
        int n = scanner.nextInt();  
        int m = scanner.nextInt();  
  
        // 节点编号从1到n,但数组索引从0开始,所以申请 n+1 这么大的数组  
        List<List<Integer>> graph = new ArrayList<>(n + 1);  
        for (int i = 0; i <= n; i++) {  
            graph.add(new ArrayList<>());  
        }  
  
        while (m-- > 0) {  
            int s = scanner.nextInt();  
            int t = scanner.nextInt();  
            // 使用邻接表 ,表示 s -> t 是相连的  
            graph.get(s).add(t);  
        }  
  
        boolean[] visited = new boolean[n + 1];  
        dfs(graph, 1, visited);  
  
        // 检查是否都访问到了  
        boolean allVisited = true;  
        for (int i = 1; i <= n; i++) {  
            if (!visited[i]) {  
                System.out.println(-1);  
                allVisited = false;  
                break;  
            }  
        }  
        if (allVisited) {  
            System.out.println(1);  
        }  
  
        scanner.close();  
    }  
}

易错点

  1. 索引与节点编号的混淆:在这个问题中,节点编号是从1开始的,但数组索引是从0开始的。这可能导致在处理输入时出错,尤其是当直接使用节点编号作为索引时。然而,在这个特定的代码中,由于graph的索引被正确地处理(即graph.get(s)中的s是节点编号,但内部自动减1以用作索引),这个错误被避免了。

  2. 邻接表的构建:在构建邻接表时,必须确保每个节点都有一个对应的空列表。在这个例子中,通过初始化一个大小为n+1ArrayList<ArrayList<Integer>>来确保这一点。

  3. DFS的递归深度:如果图是高度递归的(例如,存在很长的路径或循环),那么DFS可能会导致堆栈溢出。虽然在这个简单的例子中不太可能出现,但在处理大型或复杂的图时需要注意。

106.岛屿的周长

106. 岛屿的周长

题目

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。

你可以假设矩阵外均被水包围。在矩阵中恰好拥有一个岛屿,假设组成岛屿的陆地边长都为 1,请计算岛屿的周长。岛屿内部没有水域。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。

输出描述

输出一个整数,表示岛屿的周长。

思路

目的是计算一个二维网格中所有值为1的单元格的周长总和。程序首先通过标准输入接收网格的行数M和列数N,然后读取网格的具体内容(即每个单元格的值)。接下来,程序遍历整个网格,对于每个值为1的单元格,它调用helper函数来计算该单元格的周长,并将所有值为1的单元格的周长累加到result变量中。最后,程序输出总周长。

代码

import java.util.*;

public class Main {
    // 每次遍历到1,探索其周围4个方向,并记录周长,最终合计
    // 声明全局变量,dirs表示4个方向
    static int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    // 统计每单个1的周长
    static int count;
    
    // 探索其周围4个方向,并记录周长
    public static void helper(int[][] grid, int x, int y) {
        for (int[] dir : dirs) {
            int nx = x + dir[0];
            int ny = y + dir[1];
            
            // 遇到边界或者水,周长加一
            if (nx < 0 || nx >= grid.length || ny < 0 || ny >= grid[0].length
                || grid[nx][ny] == 0) {
                count++;
            }
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        // 接收输入
        int M = sc.nextInt();
        int N = sc.nextInt();

        int[][] grid = new int[M][N];
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                grid[i][j] = sc.nextInt();
            }
        }

        int result = 0; // 总周长
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                if (grid[i][j] == 1) {
                    count = 0;
                    helper(grid, i, j);
                    // 更新总周长
                    result += count;
                }
            }
        }
        
        // 打印结果
        System.out.println(result);
    }
}

易错点

  1. 全局变量count的线程安全问题
    在这个程序中,count被用作全局变量来存储单个值为1的单元格的周长。由于Java的static变量是类级别的,而不是实例级别的,因此它在这个上下文中是安全的,因为程序是单线程的。然而,在多线程环境中,这种使用全局变量的方式可能会导致竞态条件。在这个特定程序中,由于不存在多线程,所以这不是一个问题。

  2. 边界条件处理
    helper函数正确地处理了边界条件和值为0的单元格,这是计算周长所必需的。然而,如果网格的大小(MN)为0或负数,程序将抛出异常。虽然这种情况在常规输入中不太可能发生,但最好添加一些额外的检查来确保输入的有效性。

总结

明天继续图论!

继续加油

成功的人不是赢在起点,而是坚持到终点

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

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

相关文章

数据结构-时间、空间复杂度-详解

数据结构-时间复杂度-详解 1.前言1.1数据结构与算法1.2如何衡量一个算法的好坏1.3复杂度 2.时间复杂度2.1是什么2.2大O符号只保留最高阶项不带系数常数次为O(1) 2.3示例示例2.1示例2.2示例2.3示例2.4 2.4题目 3.空间复杂度3.1是什么3.2大O符号3.3示例示例1示例2示例3示例4 4.题…

用4种不同视角理解矩阵乘法

目录 1. 背景 2. 线性方程组视角&#xff08;向量点积视角&#xff09; 3. 列向量观点视角 4. 向量变换视角&#xff08;矩阵函数&#xff09; 5. 坐标变换视角 1. 背景 矩阵诞生于线性方程组的求解&#xff0c;最基本的运算方法来自于高斯消元法&#xff0c;所以矩阵整个…

一些问题的解决方案【持续更新ing】

一些问题的解决方案【持续更新ing】 WindowsCUDA 安装失败解决方案VS 添加现有项无反应无法定位程序输入点 于动态链接库 xxx.exe 上不同工具集生成的库无法通用更改只读属性 UbuntuVTK cmake 过程中找不到QT5目录Ubuntu添加环境变量&#xff08;永久最简单&#xff09;Wandb强…

书橱系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;图书信息管理&#xff0c;图书类型管理&#xff0c;电子书论坛&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;图书信息&#xff0c;电子书论坛&#xff0c;我的 开发系统…

SSRF实验

SSRF实验 SSRF概述实验测试结果 SSRF概述 SSRF服务端请求伪造&#xff0c;是因为网页提供的参数可以获取其他资源&#xff0c;接受网址在本地解析&#xff0c;来获取服务器本身的资源&#xff0c;但解析没过滤导致出现的问题 主要有几个方面的方法 dict 协议是一个在线网络字…

旅游社交小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;每日签到管理&#xff0c;景点推荐管理&#xff0c;景点分类管理&#xff0c;防疫查询管理&#xff0c;美食推荐管理&#xff0c;酒店推荐管理&#xff0c;周边推荐管理 微信端账…

C语言高手参考手册:网络编程高级话题与技术细节(续)

在前两篇文章中&#xff0c;我们介绍了基本的网络编程概念和一些高级话题。本文将继续深入探讨网络编程的高级话题和技术细节&#xff0c;包括更复杂的错误处理策略、高级I/O模型、高级多路复用技术、高级套接字选项、安全编程的最佳实践以及网络编程的调试技巧等。 1. 高级错…

探索数据结构:跳表的分析与实现

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 跳表的概念 **跳表(Skiplist)**是在有序链表基础上增加了“跳跃”功…

【数据存储】大/小端存储与字节顺序转换函数详解

学习目的是使用&#xff0c;网络编程中主机字节顺序与网络字节顺序转换这块就用到了这些概念及其函数&#xff01; 【Linux网络编程入门】Day5_socket编程基础 文章目录&#xff1a; 大端存储与小端存储 1.1 低地址与高地址 1.2 数据的高位与低位 1.3 大端存储 1.3.1 定义 1.…

轻松打造一个可以切换AI平台的网站

亮色主题 暗色主题 停止按键 设置界面 浏览器缓存设置 Kimi 通义千问 ChatGPT 手机版 部分代码如下&#xff1a; # -*- coding: utf-8 -*- from flask import Flask, request, jsonify, render_template, Response import requests import json import os from gevent import p…

Go反射四讲---第二讲:反射与结构体,使用反射如何操纵结构体?

反射-结构体 这是我们反射四讲的第二讲&#xff0c;本次给大家讲解如何使用反射处理结构体。 使用反射如何输出结构体的字段名字和值,使用反射如何给结构体字段设置值。 为了确保反射输出所有的字段名字和值&#xff0c;关键在于一点只有 Kind Struct 的才有。 注意&#…

Neo4J下载安装

Windows 版本 1、 下载链接安装JDK 下载链接 https://download.oracle.com/java/22/latest/jdk-22_windows-x64_bin.msi 下载完毕后默认安装即可 2、 下载Neo4J 进入Neo4j Deployment Center - Graph Database & Analytics下载页面&#xff0c;选择社区版&#xff0c;…

CentOS全面停服,国产化提速,央国企信创即时通讯/协同门户如何选型?

01. CentOS停服带来安全新风险&#xff0c; 国产操作系统迎来新的发展机遇 2024年6月30日&#xff0c;CentOS 7版本全面停服&#xff0c;于2014年发布的开源类服务器操作系统——CentOS全系列版本生命周期画上了句号。国内大量基于CentOS开发和适配的服务器及平台&#xff0c…

笔记小结:《利用python进行数据分析》之使用pandas和seaborn绘图

matplotlib实际上是一种比较低级的工具。要绘制一张图表&#xff0c;你组装一些基本组件就行&#xff1a;数据展示&#xff08;即图表类型&#xff1a;线型图、柱状图、盒形图、散布图、等值线图等&#xff09;、图例、标题、刻度标签以及其他注解型信息。 在pandas中&#xf…

pyyaml:Python 中的 YAML 处理大师

文章目录 pyyaml&#xff1a;Python 中的 YAML 处理大师背景&#xff1a;为何选择 pyyaml&#xff1f;pyyaml 是什么&#xff1f;如何安装 pyyaml&#xff1f;五个简单的 pyyaml 库函数使用方法1. 加载 YAML 数据2. 转储 YAML 数据3. 从文件加载 YAML4. 将数据写入 YAML 文件5.…

Cockos Reaper:开启专业数字音频制作之旅

Cockos Reaper 是一款备受赞誉的专业数字音频制作软件&#xff0c;适用于 Mac 和 Windows 系统。它以其强大的功能和高度的灵活性&#xff0c;成为众多音乐人和音频制作人的首选工具。 在音乐创作方面&#xff0c;Reaper 提供了丰富的虚拟乐器和音频效果插件&#xff0c;让你能…

如何使用ssm实现ssm框架的购物网站+vue

TOC ssm113ssm框架的购物网站vue 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化管理。…

AI 绘画神器 Midjourney 基础使用手册

一、前提条件 需要魔法&#xff1a; 新用户可免费创作 25 张图片&#xff0c;超过需要办会员版权问题&#xff1a;会员生成的图片版权归创作者所有 二、注册/链接 服务器 温馨提示&#xff1a;下方多图预警 1. 注册、创建服务器 ① 打开Midjourney官网&#xff0c;右下角…

机器学习入门指南:如何构建智能预测模型

【机器学习】&#xff1a;入门从零开始的指南 随着人工智能的快速发展&#xff0c;机器学习&#xff08;Machine Learning&#xff09;已经成为技术领域的热点话题。无论是推荐系统、语音识别、自动驾驶汽车&#xff0c;还是自然语言处理&#xff0c;机器学习的应用随处可见。…

minio文件存储

文章目录 参考安装与部署springboot整合miniopom.xmlapplication.ymlMinioPropertiesMinioConfigMinioApp测试基本功能bucket是否存在创建bucket修改bucket的访问权限查询所有的bucket删除指定的bucket上传文件到minio查看对象的描述信息获取文件的预签名访问地址后台获取minio…