一起养成写作习惯!这是我参与「掘金日新计划 · 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 <= 104letters[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)。