java算法(三十九)

1、给定一个用数字表示的迷宫矩阵,其中-2是入口,-3是出口,-1是障碍物,0表示道路,>0的表示传送门,处于传送门的位置可以像道路一样从上下左右走,相比道路传送门可以一步就传送到另外一个传送门的位置。比如上面的例子:第一行的1可以直接跳到行末的1。

输入:

4 3

1 0 -1 1

-2 0 -1 -3

2 2 0 0

输出:

3

代码如下:

package com.cc.demo;

import java.util.*;

public class test024 {
    /**
     * test:
     4 3
     1 0 -1 1
     -2 0 -1 -3
     2 2 0 0
     */

    // 存储位置
    static class Pos{
        int x;
        int y;
        public Pos(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    private static final int INF = 2000*2000;
    // 下,上,右,左
    private static int[][] move = new int[][]{{0,1}, {0,-1}, {1,0}, {-1,0}};
    private static Map<Integer, ArrayList<Pos>> map;

    public static void main(String[] args) {
        // 这是我自己封装的读矩阵的函数,会先读入行和列,再按照行和列读入矩阵
        // 在写笔试的时候可以把一些经常用到的读取函数提前写好,
        // 可以节省很多处理输入的时间(写笔试的一点小Trick)
        int[][] matrix = readMatrix(true);
        for(int i=0; i<matrix.length; i++){
            for(int j=0; j<matrix[0].length; j++){
                System.out.print(matrix[i][j]+" ");
            }
            System.out.println();
        }
        map = new HashMap<>();
        int row = matrix.length;
        int col = matrix[0].length;

        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++){
                // 主要是为了存储传送门,顺道把入口的位置也都存了
                if(map.containsKey(matrix[i][j])){
                    map.get(matrix[i][j]).add(new Pos(i,j));
                }else{
                    ArrayList<Pos> poss = new ArrayList<>();
                    poss.add(new Pos(i,j));
                    map.put(matrix[i][j],poss);
                }
            }
        }
        // 找到所有的入口
        ArrayList<Pos> poss = map.get(-2);
        int min = INF;
        // BFS的做法,遍历入口,找到到达出口的最短距离
        for(Pos pos:poss){
            min = Math.min(min, searchGate(matrix, pos.x, pos.y));
        }
        System.out.println(min);
    }

    private static int[][] readMatrix(boolean flag) {
        Scanner sc = new Scanner(System.in);
        int len1 = sc.nextInt();
        int len2 = sc.nextInt();
        int[][] input = new int[len2][len1];
        if(flag){
            for(int i=0; i<len2; i++){
                for(int j=0; j<len1; j++){
                    input[i][j] = sc.nextInt();
                }
            }
        }
        return input;
    }

    // BFS的做法,i,j是迷宫入口位置
    public static int searchGate(int[][] matrix, int i ,int j){
        int res = 0;
        Queue<Pos> queue = new LinkedList<>();
        int row = matrix.length;
        int col = matrix[0].length;
        // 用于标记一个位置是否被遍历过
        boolean[][] visited = new boolean[row][col];
        queue.offer(new Pos(i, j));
        visited[i][j] = true;

        while (!queue.isEmpty()) {
            int size = queue.size();
            // 处理下一层
            for (int k = 0; k < size; k++) {
                Pos pos = queue.poll();
                if (matrix[pos.x][pos.y] == -3) return res;
                // 处理上下左右的情况
                for (int[] m : move) {
                    int x = pos.x + m[0];
                    int y = pos.y + m[1];
                    // 检测是否到边界,以及有没有遇到障碍,有没有被遍历过
                    if (x >= 0 && x < row && y >= 0 && y < col
                            && !visited[x][y] && matrix[x][y] != -1) {
                        // 添加到队列中以便下次遍历
                        queue.offer(new Pos(x, y));
                        visited[x][y] = true;
                    }
                }
                // 处理传送门的情况
                if (matrix[pos.x][pos.y] > 0) {
                    // 多个传送门出口,map存储的是传送门的ID和对应的位置
                    ArrayList<Pos> poss = map.get(matrix[pos.x][pos.y]);
                    for (Pos p : poss) {
                        // 遍历到自己,或者传送门已经被遍历过都不会再通过传送门
                        if (p.x == pos.x && p.y == pos.y) continue;
                        if (visited[p.x][p.y]) continue;

                        // 将传送门封锁
                        queue.offer(new Pos(p.x, p.y));
                        visited[p.x][p.y] = true;
                    }
                }
            }
            res++;
        }
        return -1;
    }
}

2、最长上升子序列-删除一个数

给定一个无序的整数数组,删除其中某一个数后,找到其中最长上升子序列的长度。

示例:

输入: [10,9,2,5,3,7,101,18],删除10
输出: 4 
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

输入: [10,2,5,3,7,101,18],删除9
输出: 4 
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

import java.util.Random;
import java.util.Scanner;

public class test025 {
    public static void main(String[] args) {
        int[] nums = new int[]{10,9,2,5,3,7,101,18};
        int[] d_nums = new int[nums.length-1];
        int max = 0;
        for(int i=0; i<nums.length; i++){
            System.out.println("需要删除的元素为:"+nums[i]);
            d_nums = delete(nums, nums[i]);
            for(int j=0; j<d_nums.length; j++){
                System.out.print(d_nums[j]+" ");
            }
            max = Math.max(max,lengthOfLis(d_nums));
            System.out.println("max="+max);
            System.out.println();
        }

        System.out.println("删除一个元素后的最长上升子序列的长度为:"+max);
    }

    private static int[] delete(int[] nums, int value) {
        int j=0;
        int[] dnums = new int[nums.length-1];
        for(int i=0; i<nums.length; i++){
            if(nums[i] != value){
                dnums[j] = nums[i];
                j++;
            }
        }
        return dnums;
    }

    private static int lengthOfLis(int[] nums) {
        int len = 1, n = nums.length;
        if (n == 0) return 0;
        int[] d = new int[n+1];
        for(int i=0; i<n+1; i++){
            d[i] = 0;
        }
        d[len] = nums[0];
        for (int i = 1; i < n; ++i) {
            if (nums[i] > d[len]) d[++len] = nums[i];
            else{
                int l = 1, r = len, pos = 0; // 如果找不到说明所有的数都比 nums[i] 大,此时要更新 d[1],所以这里将 pos 设为 0
                while (l <= r) {
                    int mid = (l + r) >> 1;
                    if (d[mid] < nums[i]) {
                        pos = mid;
                        l = mid + 1;
                    }
                    else r = mid - 1;
                }
                d[pos + 1] = nums[i];
            }
        }
        return len;
    }
}
算法 文章被收录于专栏

根据自己所见所闻进行算法归纳总结

全部评论

相关推荐

bLanK的小号:建议自己写一个比较新颖的项目,比如思维导图,在线文档,仿造postman,仿造一个组件库
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客企业服务