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; } }
算法 文章被收录于专栏
根据自己所见所闻进行算法归纳总结