一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
一、题目
leetcode 寻找比目标字母大的最小字母
给你一个排序后的字符列表 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 是一个小写字母
二、题解
方法一
简单的可以直接遍历一次字符数组letters查询比目标字母target大的一个字母,因为原数组已然递增有序,所以当找到第一个大于目标字母target的即可,由于字母都是小写所以又不用区分大小写。具体的循环遍历数组元素,判断当前元素是否大于目标字母,如果大于目标字母,那当前字母就是比目标字母大的最小字母;否则继续往下遍历,如果遍历结束都找不到比目标字母大的一个字母,说明不存在这个字母,但是因为字母循环出现,所以直接返回数组第一个字母即可。
方法二
根据题目提取出关键字,有序数组,查找目标值,因此可以考虑使用二分查找优化时间复杂度。根据前面的方法可以知道,如果目标字母target大于或者等于数组letters的最后一个字母时,数组中是找不到比目标字母大的字母的,所以可以直接返回数组第一个字母。然后开始二分查找,初始的l、r指针指向数组两端,取l、r指针的中间值mid,获取mid下的字母和目标字母target比较,如果大于目标字母,说明比目标值大的第一个字母在左边范围,否则小于目标值,说明第一个大于目标值的字母是在右边范围。最后直到找到这个大于目标值的字母返回即可。
三、代码
方法一 Java代码
class Solution {
public char nextGreatestLetter(char[] letters, char target) {
for (char letter : letters) {
if (letter > target) return letter;
}
return letters[0];
}
}
时间复杂度:O(n),一次循环遍历数组元素。
空间复杂度:O(1),只需常数个空间变量。
方法二 Java代码
class Solution {
public char nextGreatestLetter(char[] letters, char target) {
int len = letters.length;
if (target >= letters[len - 1]) {
return letters[0];
}
int l = 0, r = len - 1;
while (l < r) {
int mid = (r - l) / 2 + l;
if (letters[mid] > target) {
r = mid;
} else {
l = mid + 1;
}
}
return letters[l];
}
}
时间复杂度:O(logn),二分查找法的时间复杂度即可。
空间复杂度:O(1),只需常数个空间变量。