字节跳动青训营 --- 主题创作

88 阅读2分钟

当青训营遇上码上掘金

主题三 --- 寻友之旅

思路:

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