题目描述:
给你一个字符数组 letters,该数组按非递减顺序排序,以及一个字符 target。letters 里至少有两个不同的字符。
返回 letters 中大于 target 的最小的字符。如果不存在这样的字符,则返回 letters 的第一个字符。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mrRPtX4W-1687850493924)(null)]
题目分析和代码:
(1).顺序暴力查找:
由于题目的字符数组已经是按非递减的顺序排序好了,我们可以直接选取数组的第一个元素作为基标,依次暴力的顺序遍历数组比较,找到第一个则跳出循环。
代码:
class Solution {
//Time Complexity:O(N)
//Space Complexity:O(1)
public char nextGreatestLetter(char[] letters, char target) {
char minMax = letters[0];
for (int i = 0;i < letters.length; ++i) {
if ((letters[i] - '0') > (target - '0')) {
minMax = letters[i];
break;
}
}
return minMax;
}
}
(2).二分查找法:
首先可以明确本题目是一个查找算法类的题目,加之我们知道二分查找的前提是被查找序列要按照一定的规律排列,而题目中正好是将字符数组按非递减的规律排列处。
1.定义左右指针分别指向字符数组的首位,循环退出条件为(left指针小于right指针);
2.执行二分操作,若中间值(中间位置假设为mid)大于target则将right指针移动到mid位置,若中间值小于等于target则将left指针移动到mid右侧一个位置(即mid+1位置处)
3.最后返回left指针指向位置处的值即可
代码:
class Solution {
//Time Complexity: O(lonN)
//Space Complexity: O(1)
public char nextGreatestLetter(char[] letters, char target) {
int left = 0;
int right = letters.length - 1;
//不存在的情况
if (letters[letters.length - 1] <= target) {
return letters[0];
}
while (left < right) {
int mid = left + (right - left) / 2;
if ((letters[mid] - '0') > (target - '0')) {
right = mid;
} else {
left = mid + 1;
}
}
return letters[left];
}
}
补充:本题目按上述二分查找代码的实现,其中left 移动到mid+1位置的原因右二
1.由于循环退出条件给的是left < right,若只是简答将left移动到mid位置处则可能发生死循环
2.由于我们在将left移动到mid+1的前提条件是当中间值小于等于target时,而此时mid+1处的位置开始就有可能是大于(或者刚好等于target),这也使得最后是直接返回字符数组中left指向位置的值。
综上我们还是可以体会处:二分查找算法终归只是一种思想没有固定的模板,虽然最基本的思想看起来比较简单,但是在循环退出条件,指针移动和其它根据题目实际需求的操作上都还是比较容易出错!!!