非常简单直观:前缀和+二分查找
class Solution {
public int chalkReplacer(int[] chalk, int k) {
int len = chalk.length;
// step1:前缀和
if (chalk[0] > k) {
return 0;
}
for (int i = 1; i < len; i++) {
chalk[i] += chalk[i - 1];
// 如果当前需要粉笔数已经超过k,则立即补充粉笔,算法结束
// 这解决了前缀和超过int的溢出问题
if (chalk[i] > k) {
return i;
}
}
// step2:二分查找
int target = k % chalk[len - 1];
int left = 0;
int right = len - 1;
int mid;
while (left < right) {
mid = left + (right - left) / 2;
// 等于目标值的话,要到下一个人才补充粉笔
// 所以这里和"收缩模板"有一点点不同
if (chalk[mid] <= target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}
如果使用经典的"栈"的话,遇到'('则入栈,遇到')'则出栈
简化一下,直接用一个变量表示"未被匹配的左括号的数量",遇到'('则加1,遇到')'则减1
而本题中,'*'的出现使得该变量成为了一个"范围"
class Solution {
public boolean checkValidString(String s) {
// [lo,hi]表示未匹配的左括号的数量范围,一个右括号可匹配抵消一个左括号
int lo = 0;
int hi = 0;
for (char c : s.toCharArray()) {
if (c == '*') {
lo--;
hi++;
} else if (c == '(') {
lo++;
hi++;
} else if (c == ')') {
lo--;
hi--;
}
// lo为负数没有意义,可以用"****"来理解
if (lo < 0) {
lo = 0;
}
// hi为负数说明右括号过多,括号匹配失败
if (hi < 0) {
return false;
}
}
// 最少未匹配左括号的数量为0
return lo == 0;
}
}
为什么可以使用"二分"?
因为题目有以下限制条件:
1.找出一个峰值即可
2.数组两侧可看成悬崖(负无穷)
3.相邻的值必不相同
class Solution {
public int findPeakElement(int[] nums) {
int left = 0;
int right = nums.length - 1;
int mid;
while (left < right) {
mid = left + (right - left) / 2;
if (nums[mid] < nums[mid + 1]) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}
检索标记:162. 寻找峰值峰值元素是指其值严格大于左右相邻值的元素。给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。你可以假设 nums[-1] = nums[n] = -∞ 。你必须实现时间复杂度为 O(log n) 的算法来解决此问题。1 <= nums.length <= 1000-231 <= nums[i] <= 231 - 1对于所有有效的 i 都有 nums[i] != nums[i + 1]678. 有效的括号字符串给定一个只包含三种字符的字符串:( ,) 和 ,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:任何左括号 ( 必须有相应的右括号 )。任何右括号 ) 必须有相应的左括号 ( 。左括号 ( 必须在对应的右括号之前 )。 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。一个空字符串也被视为有效字符串。1894. 找到需要补充粉笔的学生编号一个班级里有 n 个学生,编号为 0 到 n - 1 。每个学生会依次回答问题,编号为 0 的学生先回答,然后是编号为 1 的学生,以此类推,直到编号为 n - 1 的学生,然后老师会重复这个过程,重新从编号为 0 的学生开始回答问题。给你一个长度为 n 且下标从 0 开始的整数数组 chalk 和一个整数 k 。一开始粉笔盒里总共有 k 支粉笔。当编号为 i 的学生回答问题时,他会消耗 chalk[i] 支粉笔。如果剩余粉笔数量 严格小于 chalk[i] ,那么学生 i 需要 补充 粉笔。请你返回需要 补充 粉笔的学生 编号 。