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;
}
}

本文探讨了两个算法问题:一是给定数字迷宫矩阵,描述了如何处理入口、出口、障碍物和传送门;二是无序整数数组中删除一个数后的最长上升子序列长度计算。通过示例解释了具体操作和解决方案。

被折叠的 条评论
为什么被折叠?



