贪心
一般解题步骤
- 将问题分解为若干个子问题
- 找出合适的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解堆叠成全局最优解
例题
1、leetcode - 53. 最大子数组和(代码随想录、剑指 Offer 42. 连续子数组的最大和、NC19 连续子数组的最大和)
题目:https://leetcode-cn.com/problems/maximum-subarray/
方法一、贪心
- 时间复杂度:O(n)
- 空间复杂度:O(1)
- 题解:计算起点一定为正数,负数只会拉低综合。参考代码随想录
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int maxn = nums[0], sum = nums[0];
int ind = 0;
for(int i=1; i<nums.size(); i++){
if(sum < 0){
ind = i;
sum = nums[i];
}else{
sum += nums[i];
}
maxn = max(maxn, sum);
}
return maxn;
}
};
方法二、DP
解题思路:
- 确定dp数据以及下标的含义
dp[i]:包括下标i之前的最大连续子序列和。 - 确定递推公式
dp[i] = max(dp[i-1] + nums[i], nums[i])
参考代码随想录
- 时间复杂度:O(n)
- 空间复杂度:O(n)
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
vector<int> dp(array.size(), 0);
dp[0] = array[0];
int maxn = array[0];
for(int i=1; i<array.size(); i++){
dp[i] = max(dp[i-1]+array[i], array[i]); // 状态转移公式
if(maxn < dp[i]){
maxn = dp[i]; // maxn保存dp[i]的最大值
}
}
return maxn;
}
};
2、广联达2022.5.25笔试
第一行输入一个整数n,代表面试的人员数
第二行和第三行代表面试官发起面试的时间Ai和结束面试的时间Bi;
要求输出面试官的最多能完成的有效面试个数 面试官开始下一轮面试的时刻最少为Bi+1;
示例:
输入:
4
1 3 1 4
3 5 4 5
输出:2
解释:【1,3】和【4,5】才是有效的
题解:贪心。
- 将所有面试者的时间段按结束时间从小到大排序,结束时间一样的话按开始时间从小到大排。排序完之后就遍历,贪心的选择下一个可行的时间段。
#include<bits/stdc++.h>
using namespace std;
int n;
int main(){
scanf("%d", &n);
if(n == 0) return 0;
vector<vector<int>> times(n, vector<int>(2, 0));
for(int i=0; i<n; i++){
scanf("%d", ×[i][0]);
}
for(int i=0; i<n; i++){
scanf("%d", ×[i][1]);
}
sort(times.begin(), times.end(), [](vector<int> &a, vector<int> &b){
if(a[1] == b[1]) return a[0] < b[0];
return a[1] < b[1];
});
int res = 1;
int k = 0;
for(int i=1; i<n; i++){
if(times[k][1]+1 <= times[i][0]){
res++;
k = i;
}
}
printf("%d", res);
return 0;
}