Leetcode刷题 2021.01.20
Leetcode1218 最长定差子序列
给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序列中相邻元素之间的差等于 difference 。
今天leetcode不知道怎么回事,明明做了三道新题,不给加积分。只能又做了一道。
这题还是比较基础的动态规划题的,其实也没有特意用动态规划做,可能题做多了真的有点感觉了。其实动态规划也就是记忆化搜索而已。对于这题,从后往前遍历,用一个map记录最长的等差数列。遍历的时候,找一下map里有没有可能的等差数列就行了。看了下其他做法,用一个大的数组模拟map的,差不多的做法,也算是空间换时间吧。
class Solution {
public int longestSubsequence(int[] arr, int difference) {
int n = arr.length;
//用一个map记录
Map<Integer, Integer> memo = new HashMap<>();
int res = 0;
//从后往前遍历
for(int i = n - 1; i >= 0; i--){
int count = 1;
//如果map里有,说明在这个元素之后存在一个可行的等差数列
if (memo.containsKey(arr[i] + difference)){
count += memo.get(arr[i] + difference);
}
//把自己加进去,同时记录当前自己最长的长度
memo.put(arr[i], count);
//更新全局
res = Math.max(res, count);
}
return res;
}
}
Leetcode1219 黄金矿工
你要开发一座金矿,地质勘测学家已经探明了这座金矿中的资源分布,并用大小为 m * n 的网格 grid 进行了标注。每个单元格中的整数就表示这一单元格中的黄金数量;如果该单元格是空的,那么就是 0。
为了使收益最大化,矿工需要按以下规则来开采黄金:
每当矿工进入一个单元,就会收集该单元格中的所有黄金。
矿工每次可以从当前位置向上下左右四个方向走。
每个单元格只能被开采(进入)一次。
不得开采(进入)黄金数目为 0 的单元格。
矿工可以从网格中 任意一个 有黄金的单元格出发或者是停止。
非常正常的DFS回溯题,基本都不需要怎么改,因为矩阵不大,所以也没去优化了。比较基础。
class Solution {
public int getMaximumGold(int[][] grid) {
int m = grid.length, n = grid[0].length;
int res = 0;
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
res = Math.max(res, helper(grid, i, j));
}
}
return res;
}
private int helper(int[][] grid, int i, int j){
if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == 0){
return 0;
}
int temp = grid[i][j];
grid[i][j] = 0;
int u = helper(grid, i + 1, j);
int d = helper(grid, i - 1, j);
int l = helper(grid, i, j - 1);
int r = helper(grid, i, j + 1);
int max = Math.max(Math.max(u, d), Math.max(l, r));
grid[i][j] = temp;
return max + grid[i][j];
}
}
Leetcode1190 反转每对括号间的子串
给出一个字符串 s(仅含有小写英文字母和括号)。
请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。
注意,您的结果中 不应 包含任何括号。
对这种递归题有点不熟悉,调试了半天没调出来,还是想复杂了。其他题解有用栈做的,其实都是一回事。递归也就是用了虚拟机栈嘛。
思路就是递归,维护全局的索引,遇到左括号就递归,右括号退出,否则加到StringBuilder里面。
class Solution {
int index = 0;
public String reverseParentheses(String s) {
//字符串题用StringBuilder节约空间
StringBuilder sb = new StringBuilder();
while (index < s.length()){
char c = s.charAt(index++);
//左括号递归,注意要翻转
if (c == '('){
sb.append((new StringBuilder(reverseParentheses(s))).reverse());
//右括号退出
}else if (c == ')'){
break;
//否则加到StringBuilder里面
}else{
sb.append(c);
}
}
return sb.toString();
}
}