[JavaScript 刷题] 二分搜索 - 大于给定元素的最小元素,Leetcode 744

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JavaScript 刷题] 二分搜索 - 大于给定元素的最小元素,Leetcode 744相关的知识,希望对你有一定的参考价值。

[javascript 刷题] 二分搜索 - 大于给定元素的最小元素,Leetcode 744

题目地址:744. Find Smallest Letter Greater Than Target

题目

如下:

Given a characters array letters that is sorted in non-decreasing order and a character target, return the smallest character in the array that is larger than target.

Note that the letters wrap around.

  • For example, if target == 'z' and letters == ['a', 'b'], the answer is 'a'.

Constraints:

  • 2 <= letters.length <= 104
  • letters[i] is a lowercase English letter.
  • letters is sorted in non-decreasing order.
  • letters contains at least two different characters.
  • target is a lowercase English letter.

解题思路

依旧日常开始捋题,这道题不算长,不过需要注意的是,这道题属于是 二分查找 的变种,所以实现起来和普通的二分查找稍有不同。

  1. 如上面分析的那样,这道题依旧是用 二分查找 进行解题

    这属于 查找最小值 的变种,类似的还有 最大值第一个 最小值最后一个 最小值 等相关排列组合,但是基本思路都是 二分查找 的思路

  2. 数组是 非降序 的排序,也就是说 下一个字符一定是 ≥ \\geq 当前字符

  3. 返回值是 当前数组中大于 target 的最小值

    例:Input: letters = ["c","f","j"], target = "a",返回值是 "c",因为 "c" 是下一个大于 "a" 的值

    以题目中的例子来说,如果数组中不存在大于 target 的值,那么就返回数组中的最小值

  4. Constraints 中说了,数组和目标的值都是小写的英文字母,所以至少在这个题目中不用担心大小写的问题了

  5. Constraints 其实提供了一个挺好的边界条件的思路,例如说数组长度必须为 2 之类的

使用 JavaScript 解题

/**
 * @param {character[]} letters
 * @param {character} target
 * @return {character}
 */
var nextGreatestLetter = function (letters, target) {
  if (letters.length < 2)
    throw new Error('letters must contains at least two different characters.');
  let lo = 0,
    hi = letters.length - 1,
    mid;
  while (lo <= hi) {
    mid = Math.floor((lo + hi) / 2);

    // 当小于等于 target 的时候,都会往前推进一格
    // 也就是说,当跳出循环时,永远也不可能等到 letters[lo] === target 这个情况
    // 只会出现 letters[lo] > target 的情况
    // 题目要求返回的值必须要 > target,也就是说这一题返回的是 letters[lo]
    if (letters[mid] <= target) {
      lo = mid + 1;
    } else {
      hi = mid - 1;
    }
  }

  // 另外也存在一种情况,那就是当 target 永远 > 数组中的所有数字
  // 这种情况下,hi 会一直等于 letters.length,而当跳出循环时,lo === letters.length
  // 所以需要另外一个判断,当 lo === letters.length 时就代表数组中所有的值都比 target 小
  // 返回值就是 letters[0],如题目中所标注的那样
  return lo === letters.length ? letters[0] : letters[lo];
};

console.log(nextGreatestLetter((letters = ['a', 'b']), (target = 'z')));
console.log(nextGreatestLetter((letters = ['c', 'f', 'j']), (target = 'a')));
console.log(nextGreatestLetter((letters = ['c', 'f', 'j']), (target = 'c')));
console.log(nextGreatestLetter((letters = ['c', 'f', 'j']), (target = 'd')));
console.log(nextGreatestLetter((letters = ['c', 'f', 'j']), (target = 'g')));
console.log(nextGreatestLetter((letters = ['c', 'f', 'j']), (target = 'j')));

另外这一题的确是可以通过利用边界条件进行提速的:

这个想法来自于一个讨论:

我觉得很有道理,于是加了一个边界条件:

var nextGreatestLetter = function (letters, target) {
  if (letters[letters.length - 1] < target) return letters[0];
  // 后面的代码都是一样的
};

然后果然快了一些:

以上是关于[JavaScript 刷题] 二分搜索 - 大于给定元素的最小元素,Leetcode 744的主要内容,如果未能解决你的问题,请参考以下文章

[JavaScript 刷题] 二分搜索 - 搜索二维矩阵, leetcode 74

[JavaScript 刷题] 二分搜索 - 求开方,Leetcode 69

[JavaScript 刷题] 二分搜索 - 第一个错误的版本,Leetcode 278

[JavaScript 刷题] 二分搜索 - 有序数组的 Single Element,Leetcode 540

leetcode刷题记录——二分简单题

BZOJ4590[Shoi2015]自动刷题机 二分