1.加油站

暴力解法:两层for循环,(先写一下,优化版本就是根据暴力解法写出来的)
优化:当从a位置出发到f位置的时候发现油变成负数了,那就说明从a位置到f位置这个区间内,所有的点都无法到达 ,所以我们直接从f的下一个位置开始出发寻找,这样时间复杂度就变低了(贪心 )
这里的diff表示gas[i]-cost[i]
cpp
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int n=gas.size();
for(int i=0;i<n;i++)
{
int total=0,step=0;
for(step=0;step<n;step++)
{
int index=(i+step)%n;
total=total+gas[index]-cost[index];
if(total<0) break;
}
if(total>=0) return i;
i+=step;
}
return -1;
}
};
2.单调递增的数字

暴力:同样用两层for循环即可
优化:
我们只需要把数字成变小趋势的前一个数字-1,后面的数据全改成9即可;
但是要注意,当成变小趋势的前一个数字不止一个的时候,就要把最前面的数字-1,
cpp
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string num=to_string(n);
int size=num.size();
int i=0;
//找到第一个变化的数字
while(i+1<size() && num[i]<=num[i+1])
i++;
if(i+1==size) return n;//说明这个数就是递增的
//找到第一位
while(i-1>=0 &7 num[i]==num[i-1])
i--;
//该数值
s[i]--;
for(int j=i+1;j<n;j++)
{
s[j]='9';
}
return stoi(num);
}
};
3.坏了的计算器

cpp
> 正向求解:贪心:如果小于目标值就*2,大于目标值就--; 举个例子5->8
> 先*2变成10,在--两次变成8需要三次操作,但是最优操作只需要两次,所以这个贪心是错误的。
> 根据正难则反,我们可以去反推,用target->startValue;那操作条件就变成了只能 进行÷2和++;
> 因为整数的除法是向下取整的,所以碰到奇数的只能进行++操作; 分类讨论 当target>startValue 奇数偶数都是++
> 当target<startValue 奇数++ 偶数/2
cpp
class Solution {
public:
int brokenCalc(int startValue, int target) {
int ret=0;
while(target>startValue)
{
if(target%2==0) target/=2;
else target+=1;
ret++;
}
return ret+startValue-target;
}
};
4.合并区间

合并区间: 把第一个位置的数设为left和right 要比较的数字左右两边设为a和b
如果有重叠部分:right>=a,那就把区间变成[left,max(right,b)]
如果没有重叠部分,直接把当前的数组加入到数组中,然后把left和right设置位置从a和b开始向后出发
cpp
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
//1.排序
sort(intervals.begin(),intervals.end());
//合并
int left=intervals[0][0],right=intervals[0][1];
vector<vector<int>> ret;
for(int i=1;i<intervals.size();i++)
{
int a=intervals[i][0],b=intervals[i][1];
if(right>=a)//有重叠部分
{
//求并集
right=max(right,b);
}
else
{
ret.push_back({left,right});
left=a;
right=b;
}
}
//把最后一次也添加到里面
ret.push_back({left,right});
return ret;
}
};
5.无重叠区间

和上题类似,但是这题的left我们不需要关注 如果有重叠right>a,就把右端点较大的值移除 如果没有重叠,right=b,继续向后出发
cpp
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
//1.排序
sort(intervals.begin(),intervals.end());
int left=intervals[0][0],right=intervals[0][1];
int ret=0;
//删除区间
for(int i=1;i<intervals.size();i++)
{
int a=intervals[i][0],b=intervals[i][1];
if(right>a)//有重复区间
{
//贪心:删除右端点大的区间
right=min(right,b);
ret++;
}
else
{
left=a;
right=b;
}
}
return ret;
}
};