编辑代码

// 设置标准输入接口
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

// 问题描述:接雨水问题的变体,找出可以接到最多水的区间
// 输入格式:一行空格分隔的数字,表示每个位置的高度
// 输出格式:区间的左右边界索引和可以接的水量,格式为 "left right:water"

void (async function () {
  // 读取输入数组并转换为数字数组
  const arr = (await readline()).split(" ").map(Number);
  let length = 0; // 记录当前最优区间的长度
  let ans = []; // 存储最优区间的左右边界索引

  // 记录最大蓄水量
  let val = -Infinity;
  // 使用双指针法,从数组两端向中间移动
  let left = 0,
    right = arr.length - 1;

  // 当左右指针未相遇时继续搜索
  while (left < right) {
    // 计算当前区间[left, right]能接的水量
    const res = helper(arr, left, right);

    // 如果找到更大的蓄水量,更新答案
    if (res > val) {
      val = res;
      ans = [left, right];
      length = right - left + 1;
    }
    // 如果蓄水量相同,选择长度更短的区间
    if (res == val) {
      const curLength = right - left + 1;
      if (curLength < length) {
        ans = [left, right];
        length = curLength;
      }
    }

    // 移动指针:
    // 如果左边高度大于等于右边,移动右指针
    // 否则移动左指针
    if (arr[left] >= arr[right]) right--;
    else left++;
  }

  // 输出结果
  console.log(`${ans[0]} ${ans[1]}:${val}`);
})();

// 辅助函数:计算给定区间内可以接的水量
const helper = (arr, left, right) => {
  let val = 0;
  // 获取左右边界中的较小值,这决定了水能达到的最大高度
  const min = Math.min(arr[left], arr[right]);

  // 遍历区间内的所有位置
  for (let i = left + 1; i < right; i++) {
    // 如果当前位置高度小于边界的最小值
    // 说明这个位置可以接水,累加接水量
    if (arr[i] < min) {
      val += min - arr[i];
    }
  }
  return val;
};

// 示例说明:
// 输入:2 1 2
// 输出:0 2:1
// 解释:
// - 在区间[0,2]之间,位置1的高度为1
// - 左右边界高度都为2,所以位置1可以接1单位的水
// - 这是所有可能区间中可以接最多水的情况