LeetCode第二天
只记录中高等难度的题(高等怕的很,暂时中等)
一、22. 括号生成
22. 括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3
输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”]
示例 2:
输入:n = 1
输出:[“()”]
class Solution {
public List<String> generateParenthesis(int n) {
List<String> res = new ArrayList<>();
packtrack(res,new StringBuilder(),0,0,n);
return res;
}
public void packtrack(List<String> res,StringBuilder cur,int open,int close,int max){
if(cur.length() == max*2){
res.add(cur.toString());
return;
}
if(open<max){
cur.append('(');
packtrack(res,cur,open+1,close,max);
//一种情况结束后要把字符串对应位置的字符还原
cur.deleteCharAt(cur.length()-1);
}
if(close<open){
cur.append(')');
packtrack(res,cur,open,close+1,max);
//一种情况结束后要把字符串对应位置的字符还原
cur.deleteCharAt(cur.length()-1);
}
}
}
个人题解:
回溯法。因为括号对称,所以如果左括号没满,就可以加左括号;如果右括号小于左括号的数量,就加左括号。先作死加左括号到max,然后就开始往上回溯。
回溯重点:完成一种情况之后需要把改变的东西变回原样
二、198. 打家劫舍
198. 打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:
输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。偷窃到的最高金额 = 2 + 9 + 1 = 12 。
class Solution {
public int rob(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int length = nums.length;
if (length == 1) {
return nums[0];
}
int[] dp = new int[length];
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for (int i = 2; i < length; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[length - 1];
}
}
个人题解:
动态规划。沿街,所以要从第一间房子开始算,用一个数组存从头到某一个位置的最大收益,所以其实算某一个房子偷还是不偷主要就是看这个房子的收益加上前面第二间房子的最大收益跟它前一间房子的收益谁大。算到最后一间房子的最大收益就是所有房子的最大收益,也就是结果。
三、688. 骑士在棋盘上的概率
688. 骑士在棋盘上的概率
在一个 n x n 的国际象棋棋盘上,一个骑士从单元格 (row, column) 开始,并尝试进行 k 次移动。行和列是 从 0 开始 的,所以左上单元格是 (0,0) ,右下单元格是 (n - 1, n - 1) 。
象棋骑士有8种可能的走法,如下图所示。每次移动在基本方向上是两个单元格,然后在正交方向上是一个单元格。
每次骑士要移动时,它都会随机从8种可能的移动中选择一种(即使棋子会离开棋盘),然后移动到那里。
骑士继续移动,直到它走了 k 步或离开了棋盘。
返回 骑士在棋盘停止移动后仍留在棋盘上的概率 。
示例 1:
输入: n = 3, k = 2, row = 0, column = 0
输出: 0.0625
解释: 有两步(到(1,2),(2,1))可以让骑士留在棋盘上。在每一个位置上,也有两种移动可以让骑士留在棋盘上。骑士留在棋盘上的总概率是0.0625。
示例 2:
输入: n = 1, k = 0, row = 0, column = 0
输出: 1.00000
class Solution {
static int[][] dirs = {{-2, -1}, {-2, 1}, {2, -1}, {2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}};
public double knightProbability(int n, int k, int row, int column) {
double[][][] dp = new double[k + 1][n][n];
//循环步数
for (int step = 0; step <= k; step++) {
//双重循环 循环dp数组
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//step!=0就出边界的情况已经被上面的双重循环排除了 这个时候的概率为0
if (step == 0) {
dp[step][i][j] = 1;
} else {
//循环8个方向
for (int[] dir : dirs) {
int ni = i + dir[0], nj = j + dir[1];
if (ni >= 0 && ni < n && nj >= 0 && nj < n) {
dp[step][i][j] += dp[step - 1][ni][nj] / 8;
}
}
}
}
}
}
return dp[k][row][column];
}
}
个人题解:
动态规划。三维dp数组表示从(i,j)出发经过了step步之后还留在棋盘上的概率,动态规划方程就是某一步某一个位置的概率等于从8个方向走到这个位置的8个位置的概率的总和除以8。