当青训营遇上码上掘金

78 阅读2分钟

前言

正文

当青训营遇上码上掘金

主题3:寻友之旅

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

  • 思路

首先很容易想到一些特殊情况:

  • 当 n >= k 时,由于公交不可以往后走,因此直接返回 n - k
  • 当 n < k 时,如果 n > 50000, 那么无法走公交(因为 2 * n > 100000,超过地点范围),此时直接返回 k - n;如果 n <= 50000,并且 2 * n <= k,那么选择公交移动一次,如果 2 * n > k,那么就取公交和步行两种方式中耗时最短的交通方式。
/**
* 支持 import Java 标准库 (JDK 1.8)
*/
import java.util.*;
/**
* 注意:目前 Java 代码的入口类名称必须为 Main(大小写敏感)
*/
public class Main {
    public static int shortestTime(int n, int k) {
        if (n >= k) {
            return n - k;
        } else {
            int time = 0;
            while (k > n) {
                if (n <= 50000) {
                    if (2 * n <= k) {
                        n *= 2;
                        time++;
                    } else {
                        time += Math.min(k - n, 1 + 2 * n - k);
                        break;
                    }
                } else {
                    time += k - n;
                    break;
                }
            }
            return time;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        System.out.println("shortestTime: " + shortestTime(n, k));
		// test();
    }

	public static void test() {
        int[][] arr = {
                {3, 9},
                {4, 9},
                {5, 9},
                {6, 9},
                {30000, 90000},
                {30000, 99999}
        };
        for (int[] a : arr) {
            System.out.println(String.format("n = %d, k = %d, shortestTime = %d", a[0], a[1], shortestTime(a[0], a[1])));
        }
    }
}

主题 4:攒青豆

现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

image.png

  • 思路

此题思路和 42. 接雨水 一致。

求每一列可以存放的青豆数,我们只需要关注当前柱子,以及左边最高的柱子,右边最高的柱子。 装青豆的多少,当然根据木桶效应,只需要取左边最高的柱子与右边最高的柱子中的较小值,然后用这个较小值减去当前柱子的高度,即可获得该列可以存放的青豆数。为了降低时间复杂度,我们可以预处理获得每列柱子的左右两边最高的柱子高度,分别用 leftMax 和 rightMax 数组来保存,即 leftMax[i] 表示第 i 列左边最高的柱子,rightMax[i] 表示第 i 列右边最高的柱子。

/**
* 支持 import Java 标准库 (JDK 1.8)
*/
import java.util.*;

/**
* 注意:目前 Java 代码的入口类名称必须为 Main(大小写敏感)
*/
public class Main {
	    public static int greenBeans(int[] height) {
        int n = height.length;
        int[] leftMax = new int[n];
        int[] rightMax = new int[n];
        leftMax[0] = height[0];
        rightMax[n - 1] = height[n - 1];

        for (int i = 1; i < n; i++) {
            leftMax[i] = Math.max(leftMax[i - 1], height[i]);
        }
        for (int i = n - 2; i >= 0; i--) {
            rightMax[i] = Math.max(rightMax[i + 1], height[i]);
        }

        int res = 0;
        for (int i = 0; i < n; i++) {
            res += Math.min(leftMax[i], rightMax[i]) - height[i];
        }
        return res;
    }
	
	public static void main(String[] args) {
        int[] heights = {5, 0, 2, 1, 4, 0, 1, 0, 3};
        System.out.println("green beans count: " + greenBeans(heights));
    }
}