当青训营遇上码上掘金
主题三 --- 寻友之旅
思路:
用dp来做,通过定义递归函数来暴力求解,然后将暴力求解过程转化为dp。这题是一道非常经典动态规划题目,也
非常的简单。我们定义一个process(cur, target)函数,代表当前在cur位置,需要移动到target位置,最少
的时间数是多少。递归出口就是当cur 等于 target时,我们返回0,代表现在已经到了目标位置了,需要0分钟就
能够到达目标位置。普通情况:我们可以选择步行,也可以选择坐公交。最终选择需要时间最少的那个方案作为我们最终的方案。
代码coding有很多细节需要注意,这里只给出暴力递归的版本,可以先将暴力递归版本转化为记忆化搜索版本,然后再将记忆化搜索版本转化为动态规划版本。
代码:
public static int method(int N, int K) {
return process(N, K);
}
public static int process(int cur, int target) {
if (cur == target) {
return 0;
}
// 步行
int condition_1 = process(cur - 1, target);
int condition_2 = process(cur + 1, target);
// 公交
int condition_3 = process(cur * 2, target);
return Math.min(Math.min(condition_1, condition_2), condition_3) + 1;
}
主题四 --- 攒青豆
思路:
利用单调栈结构来做,针对于数组中的每个位置,我们都计算它能够往上延申的最大高度,当我们把数组中的所有元素对应的结果都计算出来以后,就是最终的结果。
具体如何计算每个元素能够往上延申的最大高度,我们利用单调栈来做。通过单调栈来计算出距离当前元素最近的比它大的元素(注意:当前元素的左右两边都计算),然后就可以计算出当前元素能够往上延申的最大高度。
我们保证单调栈中的元素从栈底到栈顶是从大到小排列的,对于某一个元素,如果当前元素小于栈顶元素,直接入栈。如果当前元素大于栈顶元素,弹出栈顶元素直至可以入栈位置,弹出的元素我们计算最终结果。
有很多coding的细节需要注意,具体都在代码中解释了,可以看代码中的注解来进行理解。
代码:
public int trap(int[] height) {
// 得到每个数字左右两边的结果
int[][] maxArray = getMaxArray(height);
int result = 0;
// 开始计算总结果
for (int i = 0; i < height.length; i++) {
if (maxArray[i][0] != -1 && maxArray[i][1] != -1) {
System.out.println(Math.min(height[maxArray[i][0]], height[maxArray[i][1]]) - height[i]);
result += Math.min(height[maxArray[i][0]], height[maxArray[i][1]]) - height[i];
}
}
return result;
}
// 得到每个数字左右比它高的数字
public static int[][] getMaxArray(int[] height) {
// 单调栈
Stack<Integer> stack = new Stack<>();
int[][] result = new int[height.length][2];
stack.push(0);
for (int i = 1; i < height.length; i++) {
if (height[i] <= height[stack.peek()]) {
stack.push(i);
} else {
// 开始弹出栈顶元素
while (!stack.isEmpty() && height[stack.peek()] < height[i]) {
Integer integer = stack.pop();
List<Integer> list = new ArrayList<>();
list.add(integer);
while (!stack.isEmpty() && height[stack.peek()] == height[integer]) {
Integer integer1 = stack.pop();
list.add(integer1);
}
// 更新结果
for (int j = 0; j < list.size(); j++) {
result[list.get(j)][0] = stack.isEmpty() ? -1 : stack.peek();
result[list.get(j)][1] = i;
}
}
stack.push(i);
}
}
// 栈中还有元素
while (!stack.isEmpty()) {
Integer integer = stack.pop();
List<Integer> list = new ArrayList<>();
list.add(integer);
while (!stack.isEmpty() && height[stack.peek()] == height[integer]) {
Integer integer1 = stack.pop();
list.add(integer1);
}
// 更新结果
for (int j = 0; j < list.size(); j++) {
result[list.get(j)][0] = stack.isEmpty() ? -1 : stack.peek();
result[list.get(j)][1] = -1;
}
}
return result;
}