当前位置: 首页 > news >正文

C++刷题 - 7.27

贪心算法的详细逻辑

这个问题的最优解可以用 贪心算法 在 O(N) 时间 内解决。它的核心思想是:

每次操作尽可能覆盖最长的连续非零区间,并通过数学分析发现:最小操作次数等于所有“上升台阶”的高度差之和


1. 直观理解

假设 steps = [1, 2, 3, 2, 1],我们可以这样操作:

  1. 第一次操作:覆盖整个数组 [1,2,3,2,1] → [0,1,2,1,0]
    (操作次数 +=1)

  2. 第二次操作:覆盖 [1,2,1] → [0,0,1,0,0]
    (操作次数 +=1)

  3. 第三次操作:覆盖 [1] → [0,0,0,0,0]
    (操作次数 +=1)

总操作次数 = 3,正好等于 1 (初始) + (2-1) + (3-2) = 3


2. 贪心策略的数学证明

  • 关键观察

    • 如果当前数字 steps[i] 比前一个数字 steps[i-1] 大,说明需要 新增 steps[i] - steps[i-1] 次操作

    • 如果 steps[i] <= steps[i-1],说明它可以被之前的操作覆盖,无需新增操作次数。

  • 数学表达

    text

    总操作次数 = steps[0] + Σ max(steps[i] - steps[i-1], 0)  (i = 1 to N-1)

3. 代码实现

cpp

#include <vector>
#include <iostream>
using namespace std;int GetMinStep(const vector<int>& steps) {if (steps.empty()) return 0;int res = steps[0]; // 初始必须有 steps[0] 次操作for (int i = 1; i < steps.size(); i++) {if (steps[i] > steps[i-1]) {res += steps[i] - steps[i-1]; // 增加新的操作}}return res;
}int main() {vector<int> steps1 = {1, 2, 3, 2, 1};cout << GetMinStep(steps1) << endl; // 输出 3vector<int> steps2 = {3, 2, 1, 2, 3};cout << GetMinStep(steps2) << endl; // 输出 5vector<int> steps3 = {4, 1, 2, 3, 1};cout << GetMinStep(steps3) << endl; // 输出 6 (4 + 0 + 1 + 1 + 0)return 0;
}

4. 为什么贪心算法是正确的?

反证法

假设贪心算法不是最优的,那么存在某个 steps[i] 没有被正确覆盖:

  • 情况 1steps[i] > steps[i-1]
    如果少操作,会导致 steps[i] 无法归零,矛盾。

  • 情况 2steps[i] <= steps[i-1]
    它已经被之前的操作覆盖,无需额外操作。

因此,贪心策略的正确性得证。


5. 对比原始模拟方法

方法时间复杂度适用场景
原始模拟(每次找最长区间减1)O(N²)直观但较慢
贪心算法(数学优化)O(N)最优解

6. 实际应用示例

示例 1steps = [3, 2, 1, 2, 3]
  • 计算过程

    • res = 3(初始)

    • i=12 <= 3 → 不增加

    • i=21 <= 2 → 不增加

    • i=32 > 1 → res += 1 → res=4

    • i=43 > 2 → res += 1 → res=5

  • 总操作次数 = 5

示例 2steps = [4, 1, 2, 3, 1]
  • 计算过程

    • res = 4(初始)

    • i=11 <= 4 → 不增加

    • i=22 > 1 → res += 1 → res=5

    • i=33 > 2 → res += 1 → res=6

    • i=41 <= 3 → 不增加

  • 总操作次数 = 6


7. 总结

  • 贪心策略:利用高度差直接计算最小操作次数。

  • 优势:O(N) 时间,无需模拟每次操作。

  • 适用场景:题目允许数学分析时,优先使用贪心算法。

这种方法高效且优雅,能完美解决问题! 🎯


资源 

#include <iostream>
#include <vector>
#include <climits>
#include <queue>
#include <list>
#include <unordered_set>
using namespace std;
void PrintList(list<pair<int,int>> lists)
{for(auto l:lists){cout<<"<"<<l.first<<" "<<l.second<<">"<<"   ";}cout<<endl;
}int Solution(const int frameNum, const int windowSize, const vector<int> pages) 
{int ret = 0;// 记录访问次数,访问时间,// <51 1> <52 1> <53 1>// <52 1> <53 1> <54 1>// 要么遍历一遍时间,要么遍历一遍page,要么加空间// 链表比较合适,list<pair<int,int>> pagesList;for(auto& page:pages){auto it = pagesList.begin();bool flagFind = false;while(it!=pagesList.end()){if(it->first == page){flagFind = true;it->second++;break;}it++;}if(flagFind == false){if(pagesList.size()<frameNum){pagesList.push_back(make_pair(page,1));}else // 触发置换{//从头节点开始取windowSize个//遍历得到最小值auto left = pagesList.begin();int nums = windowSize;int minof = INT_MAX;while (nums>0){minof = min(minof,left->second);left++;nums--;}nums = windowSize;left = pagesList.begin();while (nums>0){if(left->second==minof){pagesList.erase(left);pagesList.push_back(make_pair(page,1));break;}left++;nums--;}ret++;}}//PrintList(pagesList);//cout<<ret<<endl;}return ret;
}

单词统计

int Solution(const vector<string> lines) 
{// 需要特殊处理的 " " . ,    -string allLines;int ret = 0;for(int l=0;l<lines.size();l++){int i =0;if(lines[l] == "-"){  }    else{  while (i<lines[l].size()){while(i<lines[l].size()&&(lines[l][i]==','||lines[l][i]=='.'||lines[l][i]==' ')){i++;}if(i<lines[l].size()){ret++;while((i<lines[l].size())&&(lines[l][i]<='z'&&lines[l][i]>='a')){i++;} }if((i==lines[l].size()-1 )&& lines[l][i]=='-') {i++;if(l+1<lines.size()&&lines[l+1][0]>='a'&&lines[l+1][0]<='z')   { ret--;}if(l+1<lines.size()&&lines[l+1]=="-"){ret--;}}}}}return ret;
}

http://www.lryc.cn/news/608202.html

相关文章:

  • Rust: 工具链版本更新
  • Kubernetes Service 全面详解:从概念到实践
  • 具身智能VLA困于“数据泥潭”,人类活动视频数据是否是“破局之钥”?
  • 北京-4年功能测试2年空窗-报培训班学测开-今天来聊聊我的痛苦
  • 对于考研数学的理解
  • Linux 系统管理-15-OpenSSH 服务管理
  • 【Pytorch✨】LSTM 入门
  • Next.js 怎么使用 Chakra UI
  • 洛谷做题4:P5713 【深基3.例5】洛谷团队系统
  • OAuth 2.0 详解:现代授权的核心协议
  • 知识随记-----Qt 实战教程:使用 QNetworkAccessManager 发送 HTTP POST
  • Web前端实现银河粒子流动特效的3种技术方案对比与实践
  • C#中的除法
  • 【Web】CCF智能汽车大赛-CTF遴选赛 wp
  • LVGL代码框架简介
  • 苹果MAC 安卓模拟器
  • 计算机网络:任播和负载均衡的区别
  • 【QT】Qt信号与槽机制详解信号和槽的本质自定义信号和槽带参数的信号和槽
  • 【Python修仙编程】(二) Python3灵源初探(11)
  • linux中pthread_t 的值与top -Hp中线程id值的区别
  • 知识随记-----用 Qt 打造优雅的密码输入框:添加右侧眼睛图标切换显示
  • Autosar Nm-网管报文PNC停发后无法休眠问题排查
  • Antlr4在Windows环境下的配置
  • 涉水救援机器人cad【12张】三维图+设计书明说
  • Vue 服务端渲染 Nuxt 使用详解
  • AI Agent开发学习系列 - LangGraph(6): 有多个节点的Sequential Graph(练习解答)
  • 深入理解C++中的Lazy Evaluation:延迟计算的艺术
  • LangGraph认知篇-Command函数
  • UDP通信中BIND端口号的作用解析,LOCALPORT的关系解析
  • 搜索与图论(最小生成树 二分图)