二分猜答案

lc2167

前后缀分解 -> 线性dp

前缀数组记录从左侧处理违禁车厢的最小时间、后缀数组记录从右侧处理的最小时间

遍历每个位置时合并两侧时间,取最小值得到移除所有违禁车厢的最少时间

class Solution {

public:

int minimumTime(string s) {

int n = s.length();

vector<int> suf(n + 1);

for (int i = n - 1; i >= 0; --i)

sufi = si == '0' ? sufi + 1 : ++min(sufi + 1 + 2, n - i); //suf预处理 记录选择++

int ans = suf0, pre = 0;

for (int i = 0; i < n; ++i)

if (si == '1') {

++***pre = min(pre + 2, i + 1);
ans = min(ans, pre + sufi +***++ 1);

}

return ans;

}

};

lc286

前后缀分解

class Solution {

public:

vector<int> productExceptSelf(vector<int>& nums)

{

int n=nums.size();

vector<int> f(n),g(n);

f0=1;

gn-1=1;//init

//空间换时间

//预处理

for(int i=1;i<=n-1;i++)

fi=fi-1*numsi-1;

for(int j=n-2;j>=0;j--)

gj=gj+1*numsj+1;

//cal

vector<int> ret(n);

for(int i=0;i<n;i++)

++reti=fi*gi;++

return ret;

}

};

lc786

二分查找分数值范围,统计小于等于中间值的分数个数,定位第k小的素数分数并返回

#include <vector>

using namespace std;

class Solution {

private:

vector<int> arr;

int n, a, b;

public:

vector<int> kthSmallestPrimeFraction(vector<int>& _arr, int k) {

arr = _arr;

n = arr.size();

double l = 0, r = 1;

while (true) {

double mid = (l + r) / 2;

int cnt = check(mid);

if (cnt > k) r = mid;

else if (cnt < k) l = mid;

else break;

}

return {a, b};

}

private:

int check(double x) {

int ans = 0;

double large = 0;

for (int i = 0, j = 1; j < n; j++) {

while (arri + 1 * 1.0 / arrj <= x)

i++;

if (arri * 1.0 / arrj <= x) {

ans += i + 1;

if (arri * 1.0 / arrj > large) {

a = arri;

b = arrj;

large = arri * 1.0 / arrj;

}

}

}

return ans;

}

};

核心逻辑:用二分查找定位"第k小的素数分数",不用暴力枚举所有分数,效率更高

  1. 前提:输入数组是从小到大排序的素数,要找的是"两个素数相除(分子在前、分母在后,分子<分母)"中第k小的那个分数(比如数组2,3,5,分数有2/3、2/5、3/5,第2小是2/5)

  2. 二分查找的是什么?

不直接找分数,而是找"分数的数值大小"。因为所有可能的分数都在 0~1 之间(分子<分母),所以在 0,1 区间里二分:

  • 每次取中间值 mid ,++统计"所有小于等于 mid 的分数有多少个"(用 check 函数算)++。

  • 如果统计数 >k:说明第k小的分数比 mid 小,缩小右边界;

  • 如果统计数 <k:说明第k小的分数比 mid 大,扩大左边界;

  • 统计数 ==k:说明 mid 刚好"卡"在第k小的分数上,找到目标。

  1. check函数怎么统计?

用"双指针"高效计数(不用两两枚举,避免超时):

  • 固定分母 j ,找最大的分子 i 使得 arri/arrj ≤ mid (因为数组有序, i 越大,分数越大);

  • 此时, i+1 就是以 arrj 为分母、满足条件的分数个数(分子可以是 arr0~arri );

  • 同时记录这些分数中最大的那个(因为统计数==k时,这个最大分数就是第k小的目标)

lc1300

对数组排序后,通过二分查找确定"将数组中大于该值的元素替换为该值后总和最接近目标值"的数,用二分+迭代器定位_计算总和

using namespace std;

class Solution

{

public:

int findBestValue(vector<int>& arr, int target)

{

sort(arr.begin(),arr.end());

int l=0, r=arr.back();

int n=arr.size();

auto check=\&(int x)->int

{

int ret=0;

auto it=lower_bound(arr.begin(),arr.end(),x);

int idx=it-arr.begin();

for(int i=0;i<idx;i++)

ret+=arri;

return ret+(n-idx)*x;

};

while(l<=r)

{

int m=l+(r-l)/2;

if(check(m)<target)

l=m+1;

else

r=m-1;

}

int sum1=check(l), sum2=check(l-1);

return abs(sum1-target) < abs(sum2-target) ? l : l-1;

}

};

相关推荐
happymaker062633 分钟前
LeetCodeHot100——42.接雨水
算法
阿正的梦工坊1 小时前
【Rust】07-错误处理:Option、Result 与 ? 运算符
开发语言·算法·rust
八解毒剂3 小时前
数据结构-平衡二叉树——对二叉搜索树的优化
数据结构·c++·算法
运行时记录3 小时前
别再手动写提示词了 — SkillOpt 让技能文档自己进化
算法
啦啦啦啦啦zzzz3 小时前
算法总结(二分查找、双指针)
c++·算法
qq_8573058194 小时前
python语法
开发语言·python·算法
DXM05214 小时前
第9期|从机器学习到深度学习:AI遥感解译的进化逻辑
人工智能·算法·计算机视觉
小蒋学算法4 小时前
算法-阶乘函数后K个零
算法
weixin_307779134 小时前
智能模拟数据生成平台:生成式AI合成数据技术重塑开发测试效能
人工智能·测试工具·算法·测试用例
羊羊小栈5 小时前
Uplift营销供应链协同决策系统(基于Uplift因果推断与运筹优化算法)
前端·人工智能·算法·毕业设计·大作业