LeetCode探索(46):744-寻找比目标字母大的最小字母

584 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

题目

给你一个排序后的字符列表 letters ,列表中只包含小写英文字母。另给出一个目标字母 target,请你寻找在这一有序列表里比目标字母大的最小字母。

在比较时,字母是依序循环出现的。举个例子:

如果目标字母 target = 'z' 并且字符列表为 letters = ['a', 'b'],则答案返回 'a'

示例 1:

输入: letters = ["c", "f", "j"],target = "a"
输出: "c"

示例 2:

输入: letters = ["c","f","j"], target = "c"
输出: "f"

示例 3:

输入: letters = ["c","f","j"], target = "d"
输出: "f"

提示:

  • 2 <= letters.length <= 104
  • letters[i] 是一个小写字母
  • letters 按非递减顺序排序
  • letters 最少包含两个不同的字母
  • target 是一个小写字母

思考

本地难度简单,是LeetCode每日一题的题目。

首先是阅读题意。题目给出的字符列表letters是有序的,且只包含小写英文字母,我们需要找出列表中比目标字母target大的最小字母。很简单的题意!

不过,我们注意到题目中有一个隐含条件:如果 target 比所有字母都大则返回第一个字母... 也就是,假如目标字母 target = 'z' 并且字符列表为 letters = ['a', 'b'],则答案返回 'a',这是一个隐藏的坑。

我们可以对非递减列表的每一项进行遍历,当元素>target时,即为答案,此时时间复杂度是O(n)。考虑到给出的是有序列表,我们可以借助二分查找的方法优化我们的答案,此时时间复杂度是O(logn)

解答

方法一: 二分查找

var nextGreatestLetter = function(letters, target) {
  let len = letters.length
  // 题目中的隐含条件:如果 target 比所有字母都大则返回第一个字母
  if (target >= letters[len - 1]) {
    return letters[0]
  }
  let low = 0, high = len - 1
  while (low < high) {
    let mid = Math.floor((high - low) / 2) + low
    if (letters[mid] > target) {
      high = mid
    } else {
      low = mid + 1
    }
  }
  return letters[low]
}

复杂度分析:

  • 时间复杂度:O(logn),其中 n 是列表 letters 的长度。二分查找的时间复杂度是 O(logn)。
  • 空间复杂度:O(1)

参考