代码随想录算法训练营第五十九天| 110. 字符串接龙、105. 有向图的完全可达性、106. 岛屿的周长

[KamaCoder] 110. 字符串接龙

[KamaCoder] 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。

输入示例
6
abc def
efc
dbc
ebc
dec
dfc
yhn
输出示例
4

数据范围:

2 <= N <= 500

[KamaCoder] 110. 字符串接龙

自己看到题目的第一想法

    只要能构建从 beginStr 到 endStr 的邻接矩阵, 就可以知道所有路劲了. 但是构建邻接矩阵成了难题.

看完代码随想录之后的想法

    从 beginStr 开始, 从左往右替换 beginStr 中的每一个字符, 如果替换后的字符串 word 在 strList 中存在对应的字符串, 说明可以从 beginStr 改变一个字符到达对应的字符串. 使用一个 Map<String, Integer> 记录住到达 word 的路劲长度. 这样不停的遍历, 直到第一次遇到 word.equals(endStr) 则找到了对应的路劲.

import java.util.Scanner;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;


public class Main {
    private static int[][] dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String beginStr = "";
        String endStr = "";
        Set<String> dicStrs = new HashSet<>();
        while (scanner.hasNext()) {
            int dicSize = scanner.nextInt();
            scanner.nextLine();
            String[] dicStrArrays = scanner.nextLine().split(" ");
            beginStr = dicStrArrays[0];
            endStr = dicStrArrays[1];
            for (int i = 0; i < dicSize; i++) {
                dicStrs.add(scanner.nextLine());
            }
        }
        
        Map<String, Integer> wordPath = new HashMap<>();
        Deque<String> words = new LinkedList<>();
        String word;
        words.addLast(beginStr);
        wordPath.put(beginStr, 1);
        while(!words.isEmpty()) {
            String currentWord = words.pop();
            StringBuilder wordBuilder = null;
            for (int i = 0; i < currentWord.length(); i++) {
                wordBuilder = new StringBuilder(currentWord);
                for (int j = 0; j < 26; j++) {
                    wordBuilder.setCharAt(i, (char)(j + 'a'));
                    word = wordBuilder.toString();
                    if (wordPath.containsKey(word)) {
                        continue;
                    }
                    if (word.equals(endStr)) {
                        System.out.println(wordPath.get(currentWord) + 1);
                        return;
                    }
                    if (!dicStrs.contains(word)) {
                        continue;
                    }
                    wordPath.put(word, wordPath.get(currentWord) + 1);
                    words.addLast(word);
                }
            }
        }
        System.out.println(0);
    }
}

自己实现过程中遇到哪些困难

    整体不难, 一周半过后还完全可以靠逻辑快速 AC.

[KamaCoder] 105. 有向图的完全可达性

[KamaCoder] 105. 有向图的完全可达性 文章解释

题目描述

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

输入描述

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

输出描述

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

输入示例
4 4
1 2
2 1
1 3
2 4
输出示例
1

数据范围:

1 <= N <= 100;
1 <= K <= 2000。

[KamaCoder] 105. 有向图的完全可达性

自己看到题目的第一想法

    无.

看完代码随想录之后的想法

    利用 dfs 不停的往前遍历, 同时因为是双向图, 对于遍历过的节点需要记录一下, 避免死循环.

import java.util.ArrayList;
import java.util.Scanner;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

// 邻接表 dfs
public class Main {
    private static int[][] dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int nodeCount = 0;
        Map<Integer, List<Integer>> nodes = new HashMap<>();
        while (scanner.hasNext()) {
            nodeCount = scanner.nextInt();
            int sideCount = scanner.nextInt();
            for (int i = 0; i < sideCount; i++) {
                int node = scanner.nextInt();
                List<Integer> toNodes = nodes.get(node);
                if (toNodes == null) {
                    toNodes = new ArrayList<>();
                    nodes.put(node, toNodes);
                }
                toNodes.add(scanner.nextInt());
            }
        }
        
        boolean[] visited = new boolean[nodeCount + 1];
        visited[0] = true;
        dfs(nodes, 1, visited);
        for (int i = 1; i < visited.length; i++) {
            if (!visited[i]) {
                System.out.println(-1);
                return;
            }
        }
        System.out.println(1);
    }
    private static void dfs(Map<Integer, List<Integer>> nodes, int node, boolean[] visited) {
        if (visited[node]) {
            return;
        }
        visited[node] = true;
        List<Integer> toNodes = nodes.get(node);
        if (toNodes == null) {
            return;
        }
        for (Integer newNode : toNodes) {
            dfs(nodes, newNode, visited);
        }
    }
}
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;


// 邻接矩阵 dfs
public class Main {
    private static int[][] dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int[][] nodes = null;
        while (scanner.hasNext()) {
            int nodeCount = scanner.nextInt();
            int sideCount = scanner.nextInt();
            nodes = new int[nodeCount + 1][nodeCount + 1];
            for (int i = 0; i < sideCount; i++) {
                nodes[scanner.nextInt()][scanner.nextInt()] = 1;
            }
        }
        boolean[] visited = new boolean[nodes.length];
        visited[0] = true;
        dfs(nodes, 1, visited);
        for (int i = 1; i < visited.length; i++) {
            if (!visited[i]) {
                System.out.println(-1);
                return;
            }
        }
        System.out.println(1);
    }
    private static void dfs(int[][] nodes, int node, boolean[] visited) {
        if (visited[node]) {
            return;
        }
        visited[node] = true;
        for (int i = 1; i < nodes[node].length; i++) {
            if (nodes[node][i] == 1) {
                dfs(nodes, i, visited);   
            }
        }
    }
}
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

// 邻接表 bfs
public class Main {
    private static int[][] dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int nodeCount = 0;
        Map<Integer, List<Integer>> nodes = new HashMap<>();
        while (scanner.hasNext()) {
            nodeCount = scanner.nextInt();
            int sideCount = scanner.nextInt();
            for (int i = 0; i < sideCount; i++) {
                int node = scanner.nextInt();
                List<Integer> toNodes = nodes.get(node);
                if (toNodes == null) {
                    toNodes = new ArrayList<>();
                    nodes.put(node, toNodes);
                }
                toNodes.add(scanner.nextInt());
            }
        }
        
        boolean[] visited = new boolean[nodeCount + 1];
        visited[0] = true;
        bfs(nodes, 1, visited);
        for (int i = 1; i < visited.length; i++) {
            if (!visited[i]) {
                System.out.println(-1);
                return;
            }
        }
        System.out.println(1);
    }
    private static void bfs(Map<Integer, List<Integer>> nodes, int node, boolean[] visited) {
        Deque<Integer> fromNodes = new LinkedList<>();
        fromNodes.add(node);
        visited[node] = true;
        while (!fromNodes.isEmpty()) {
            int fromNode = fromNodes.pop();
            List<Integer> toNodes = nodes.get(fromNode);
            if (toNodes == null) {
                continue;
            }
            for (Integer newNode : toNodes) {
                if (visited[newNode]) {
                    continue;
                }
                fromNodes.add(newNode);
                visited[newNode] = true;
            }
        }
    }
}

自己实现过程中遇到哪些困难 

    无

[KamaCoder] 106. 岛屿的周长

[KamaCoder] 106. 岛屿的周长 文章解释

题目描述

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

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

输入描述

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

输出描述

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

输入示例
5 5
0 0 0 0 0 
0 1 0 1 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
输出示例
14

数据范围:

1 <= M, N <= 50。

[KamaCoder] 106. 岛屿的周长

 

自己看到题目的第一想法

    当前陆地的上下左右方向, 每个方向有一个海水, 则周长+1;

看完代码随想录之后的想法

    方法1是一样的想法. 方法2通过计算陆地个数, 用陆地个数*4-相邻陆地个数*2计算.

import java.util.Scanner;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;


public class Main {
    private static int[][] dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int[][] nodes = null;
        boolean[][] visited = null;
        while (scanner.hasNext()) {
            nodes = new int[scanner.nextInt()][scanner.nextInt()];
            visited = new boolean[nodes.length][nodes[0].length];
            for (int i = 0; i < nodes.length; i++) {
                for (int j = 0; j < nodes[i].length; j++) {
                    nodes[i][j] = scanner.nextInt();
                }
            }
        }
        for (int i = 0; i < nodes.length; i++) {
            for (int j = 0; j < nodes[i].length; j++) {
                if (nodes[i][j] != 1) {
                    continue;
                }
                System.out.println(dfs(nodes, visited, i, j));
                return;
            }
        }
        System.out.println(0);
    }
    
    private static int dfs(int[][] nodes, boolean[][] visited, int x, int y) {
        if (visited[x][y]) {
            return 0;
        }
        visited[x][y] = true;
        int newX;
        int newY;
        int perimeter = 0;
        for (int i = 0; i < dir.length; i++) {
            newX = x + dir[i][0];
            newY = y + dir[i][1];
            if (newX < 0 || newX >= nodes.length || newY < 0 || newY >= nodes[newX].length) {
                perimeter++;
                continue;
            }
            if (nodes[newX][newY] == 0) {
                perimeter++;
            } else {
                perimeter += dfs(nodes, visited, newX, newY);
            }
        }
        return perimeter;
    }
}
import java.util.Scanner;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

// 巧妙记边法
public class Main {
    private static int[][] dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int[][] nodes = null;
        boolean[][] visited = null;
        while (scanner.hasNext()) {
            nodes = new int[scanner.nextInt()][scanner.nextInt()];
            visited = new boolean[nodes.length][nodes[0].length];
            for (int i = 0; i < nodes.length; i++) {
                for (int j = 0; j < nodes[i].length; j++) {
                    nodes[i][j] = scanner.nextInt();
                }
            }
        }
        int count = 0;
        int duplicate = 0;
        for (int i = 0; i < nodes.length; i++) {
            for (int j = 0; j < nodes[i].length; j++) {
                if (nodes[i][j] != 1) {
                    continue;
                }
                count++;
                int newX;
                int newY;
                for (int k = 0; k < 2; k++) {
                    newX = i + dir[k][0];
                    newY = j + dir[k][1];
                    if (newX >= nodes.length || newY >= nodes[newX].length) {
                        continue;
                    }
                    if (nodes[newX][newY] == 1) {
                        duplicate++;
                    }
                }
            }
        }
        System.out.println(count * 4 - duplicate * 2);
    }
}

自己实现过程中遇到哪些困难

    每个相邻的岛屿, 边是重复计算了2次, 一开始算成一次了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值