【LeetCode】Sama的个人记录_69

这篇博客介绍了如何利用前缀和与二分查找解决编程问题,包括粉笔补充问题、有效括号字符串验证以及寻找峰值元素。在粉笔问题中,通过前缀和和二分查找确定需要补充粉笔的学生;在括号字符串问题中,使用动态维护未匹配左括号的数量范围;在峰值元素问题中,借助二分查找在数组中找到峰值。这些算法都充分利用了数据结构和搜索策略,实现了高效解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

非常简单直观:前缀和+二分查找
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 需要 补充 粉笔。请你返回需要 补充 粉笔的学生 编号 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值