力扣第744题 二分查找 线性查找

题目

744. 寻找比目标字母大的最小字母

简单

给你一个字符数组 letters,该数组按非递减顺序排序,以及一个字符 targetletters 里至少有两个不同的字符。

返回 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 <= 104
  • letters[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(log⁡n),其中 n 是列表 letters的长度。二分查找的时间复杂度是 O(log⁡n)。

        空间复杂度

                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];
    }
}

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

posted @ 2023-09-18 08:00  lenyan~  阅读(35)  评论(0)    收藏  举报  来源