力扣第744题 二分查找 线性查找
题目
简单
给你一个字符数组 letters,该数组按非递减顺序排序,以及一个字符 target。letters 里至少有两个不同的字符。
返回 letters 中大于 target 的最小的字符。如果不存在这样的字符,则返回 letters 的第一个字符。
示例 1:
输入: letters = ["c", "f", "j"],target = "a" 输出: "c" 解释:letters 中字典上比 'a' 大的最小字符是 'c'。
示例 2:
输入: letters = ["c","f","j"], target = "c" 输出: "f" 解释:letters 中字典顺序上大于 'c' 的最小字符是 'f'。
示例 3:
输入: letters = ["x","x","y","y"], target = "z" 输出: "x" 解释:letters 中没有一个字符在字典上大于 'z',所以我们返回 letters[0]。
提示:
2 <= letters.length <= 104letters[i]是一个小写字母letters按非递减顺序排序letters最少包含两个不同的字母target是一个小写字母
思路和解题方法 一
- 由于给定的列表已经按照递增顺序排序,因此可以从左到右遍历列表,找到第一个比目标字母大的字母,即为比目标字母大的最小字母。
- 如果目标字母小于列表中的最后一个字母,则一定可以在列表中找到比目标字母大的最小字母。如果目标字母大于或等于列表中的最后一个字母,则列表中不存在比目标字母大的字母,根据循环出现的顺序,列表的首个字母是比目标字母大的最小字母。
复杂度
时间复杂度:
O(n)
时间复杂度:O(n),其中 n 是列表 letters 的长度。需要遍历列表一次寻找比目标字母大的最小字母。
空间复杂度
O(1)
空间复杂度:O(1)。
c++ 代码一
class Solution {
public:
char nextGreatestLetter(vector<char>& letters, char target) {
for (char letter : letters) { // 遍历给定的字符数组
if (letter > target) { // 如果当前字符大于目标字符
return letter; // 返回当前字符作为结果
}
}
return letters[0]; // 如果没有找到更大的字符,则返回数组的第一个字符作为结果
}
};
思路和解题方法 二
- 利用列表有序的特点,可以使用二分查找降低时间复杂度。
- 首先比较目标字母和列表中的最后一个字母,当目标字母大于或等于列表中的最后一个字母时,答案是列表的首个字母。当目标字母小于列表中的最后一个字母时,列表中一定存在比目标字母大的字母,可以使用二分查找得到比目标字母大的最小字母。
- 初始时,二分查找的范围是整个列表的下标范围。每次比较当前下标处的字母和目标字母,如果当前下标处的字母大于目标字母,则在当前下标以及当前下标的左侧继续查找,否则在当前下标的右侧继续查找。
复杂度
时间复杂度:
O(log n)
时间复杂度:O(logn),其中 n 是列表 letters的长度。二分查找的时间复杂度是 O(logn)。
空间复杂度
O(1)
空间复杂度:O(1)。
c++ 代码
class Solution {
public:
char nextGreatestLetter(vector<char>& letters, char target) {
int left = 0; // 搜索范围的左边界,初始值为数组起始位置
int right = letters.size() - 1; // 搜索范围的右边界,初始值为数组末尾位置
while (left <= right) { // 循环直到搜索范围为空
int mid = left + (right - left) / 2; // 计算中间索引
if (letters[mid] <= target) { // 如果中间字符小于或等于目标字符
left = mid + 1; // 将搜索范围缩小为右半部分
} else { // 否则,中间字符大于目标字符
right = mid - 1; // 将搜索范围缩小为左半部分
}
}
// 当 left 超出数组范围时,取模运算确保结果在合法范围内
return letters[left % letters.size()];
}
};
class Solution {
public:
char nextGreatestLetter(vector<char>& letters, char target) {
// 如果目标字符小于数组中的最后一个字符
if (target < letters.back()) {
// 使用 upper_bound 函数在数组中查找第一个大于目标字符的位置,并返回其指针
// 注意这里使用 letters.end() - 1 来排除数组最后一个字符
return *upper_bound(letters.begin(), letters.end() - 1, target);
} else {
// 目标字符大于等于数组中的最后一个字符,直接返回数组的第一个字符
return letters[0];
}
}
};
简单版
class Solution {
public:
char nextGreatestLetter(vector<char> &letters, char target) {
return target < letters.back() ? *upper_bound(letters.begin(), letters.end() - 1, target) : letters[0];
}
}
觉得有用的话可以点点赞,支持一下。
如果愿意的话关注一下。会对你有更多的帮助。
每天都会不定时更新哦 >人< 。
浙公网安备 33010602011771号