279.完全平方数
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
问题分析
可以将每个整数看成图中的一个节点,如果两个整数之差为一个平方数,那么这两个整数所在的节点就有一条边。
要求解最小的平方数数量,就是求解从节点 n 到节点 0 的最短路径。
class Solution {
public int numSquares(int n) {
List<Integer> squares = generateSquares(n);
Queue<Integer> queue = new LinkedList<>();
boolean[] marked = new boolean[n + 1];
queue.add(n);
marked[n] = true;
int level = 0;
while (!queue.isEmpty()) {
int size = queue.size();
level++;
while (size-- > 0) {
int cur = queue.poll();
for (int s : squares) {
int next = cur - s;
if (next < 0) {
break;
}
if (next == 0) {
return level;
}
if (marked[next]) {
continue;
}
marked[next] = true;
queue.add(next);
}
}
}
return n;
}
/**
* 生成小于 n 的平方数序列
* @return 1,4,9,...
*/
private List<Integer> generateSquares(int n) {
List<Integer> squares = new ArrayList<>();
int square = 1;
int diff = 3;
while (square <= n) {
squares.add(square);
square += diff;
diff += 2;
}
return squares;
}
}
1091. 二进制矩阵中的最短路径
问题
给你一个 n x n 的二进制矩阵 grid 中,返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径,返回 -1 。
二进制矩阵中的 畅通路径 是一条从 左上角 单元格(即,(0, 0))到 右下角 单元格(即,(n - 1, n - 1))的路径,该路径同时满足下述要求:
- 路径途经的所有单元格都的值都是 0 。
- 路径中所有相邻的单元格应当在 8 个方向之一 上连通(即,相邻两单元之间彼此不同且共享一条边或者一个角)。
畅通路径的长度 是该路径途经的单元格总数。
代码
class Solution{
public int shortestPathBinaryMatrix(int[][] grids) {
if (grids == null || grids.length == 0 || grids[0].length == 0) {
return -1;
}
int[][] direction = {{1, -1}, {1, 0}, {1, 1}, {0, -1}, {0, 1}, {-1, -1}, {-1, 0}, {-1, 1}};
int m = grids.length, n = grids[0].length;
Queue<Pair<Integer, Integer>> queue = new LinkedList<>();
queue.add(new Pair<>(0, 0));
int pathLength = 0;
while (!queue.isEmpty()) {
int size = queue.size();
pathLength++;
while (size-- > 0) {
Pair<Integer, Integer> cur = queue.poll();
int cr = cur.getKey(), cc = cur.getValue();
if (grids[cr][cc] == 1) {
continue;
}
if (cr == m - 1 && cc == n - 1) {
return pathLength;
}
grids[cr][cc] = 1; // 标记
for (int[] d : direction) {
int nr = cr + d[0], nc = cc + d[1];
if (nr < 0 || nr >= m || nc < 0 || nc >= n) {
continue;
}
queue.add(new Pair<>(nr, nc));
}
}
}
return -1;
}
}
// 下面的为超时代码
// class Solution {
// int[][] d = {{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
// int max = -1;
// public int shortestPathBinaryMatrix(int[][] grid) {
// int[][] find = new int[grid.length][grid.length];
// for(int i = 0; i < grid.length; ++i){
// Arrays.fill(find[i], 0);
// }
// if(grid[0][0] == 1) {
// return -1;
// }
// trace(grid,find,1,0,0);
// return max;
// }
// public void trace(int[][] grid, int[][] find, int cur, int x, int y){
// if(x == grid.length-1 && y == grid.length-1){
// max = (max == -1 || max > cur) ? cur : max;
// //System.out.println(max);
// }
// if(max != -1 && cur > max){
// return ;
// }
// for(int[] num : d){
// if(help(grid, find, x+num[0], y+num[1])){
// find[x+num[0]][y+num[1]] = 1;
// trace(grid, find, cur + 1, x+num[0], y+num[1]);
// find[x+num[0]][y+num[1]] = 0;
// }
// }
// return ;
// }
// public boolean help(int[][] grid, int[][] find, int x, int y){
// if(x < 0 || x >= grid.length || y < 0 || y >= grid.length){
// return false;
// }
// if(find[x][y] == 1 || grid[x][y] == 1){
// return false;
// }
// return true;
// }
// }