美团2021届秋季校园招聘笔试真题解析:小美的仓库整理

问题

小美是美团仓库的管理员,她会根据单据的要求按顺序取出仓库中的货物,每取出一件货物后会把剩余货物重新堆放,使得自己方便查找。已知货物入库的时候是按顺序堆放在一起的。如果小美取出其中一件货物,则会把货物所在的一堆物品以取出的货物为界分成两堆,这样可以保证货物局部的顺序不变。
已知货物最初是按 1~n 的顺序堆放的,每件货物的重量为 w[i] ,小美会根据单据依次不放回的取出货物。请问根据上述操作,小美每取出一件货物之后,重量和最大的一堆货物重量是多少?

分析

首先有一个疑问,这样做真的能方便货物的查找吗?
我们换一种说法来帮助理解此题目。有一个整数数组,给出一个下标将数组分成2个子数组,分别求出各子数组元素和,找到元素和最大的子数组,重复上述操作,如下图:

  • 下标4,子数组最大元素和sum=9
    美团2021届秋季校园招聘笔试真题解析:小美的仓库整理_第1张图片
  • 下标2,子数组最大元素和sum=4
    美团2021届秋季校园招聘笔试真题解析:小美的仓库整理_第2张图片
  • 下标3,子数组最大元素和sum=3
    美团2021届秋季校园招聘笔试真题解析:小美的仓库整理_第3张图片
  • 下标1,子数组最大元素和sum=1
    美团2021届秋季校园招聘笔试真题解析:小美的仓库整理_第4张图片
  • 下标0,子数组最大元素和sum=0
    美团2021届秋季校园招聘笔试真题解析:小美的仓库整理_第5张图片

代码及解析

  public void manage(int[] weights, int[] nums) {
    int maxSum = Integer.MIN_VALUE;
    for (int i = 0; i < nums.length; i++) {
      // 判断是否需要计算"最大货堆重量和",减少计算量提升运行效率
      boolean needSum = needSum(weights, nums[i] - 1, maxSum);
      // 重量设置为0表示取出货物
      weights[nums[i] - 1] = 0;
      // 如果待取出货物的在"最大货堆"内,"最大货堆"将被分割,则需要重新计算"最大货堆重量和";
      // 否则"最大货堆重量和"不变,不需要计算
      maxSum = needSum ? maxSum(weights) : maxSum;
      System.out.println(maxSum);
    }
  }

  /**
   * 是否需要计算"最大货堆重量和"
   *
   * @param weights
   * @param index
   * @param maxSum
   * @return
   */
  private boolean needSum(int[] weights, int index, int maxSum) {
    // 初始需要计算"最大货堆重量和"
    if (maxSum == Integer.MIN_VALUE) return true;
    int left = index - 1, right = index + 1, currSum = weights[index];
    // 计算待取出货物的"货堆的重量和"currSum
    while (left >= 0 || right < weights.length) {
      if (left >= 0) {
        // 到了"货堆"的左边界,停止向左计算
        if (weights[left] == 0) left = -1;
        else currSum += weights[left--];
      }
      if (right < weights.length) {
        // 到了"货堆"的右边界,停止向右计算
        if (weights[right] == 0) right = weights.length;
        else currSum += weights[right++];
      }
    }
    // 如果待取出货物的在"最大货堆"内,"最大货堆"将被分割,则需要重新计算"最大货堆重量和"
    return currSum == maxSum;
  }

  /**
   * 计算"最大货堆重量和"
   *
   * @param weights
   * @return
   */
  private int maxSum(int[] weights) {
    int maxSum = 0, temp = 0;
    for (int j = 0; j < weights.length; j++) {
      // weights[j]==0表示到达了"货堆"边界,需要计算新"货堆重量和"
      temp = weights[j] == 0 ? 0 : temp + weights[j];
      maxSum = Math.max(maxSum, temp);
    }
    return maxSum;
  }

美团2021届秋季校园招聘笔试真题解析:小美的跑腿代购

题目来自力扣

你可能感兴趣的:(算法,面试,校招,美团2021秋季校招,美团笔试题,小美的仓库整理)