[Algorithm][贪心][跳跃游戏][加油站][单调递增的数字][坏了的计算器]详细讲解


1.跳跃游戏

1.题目链接


2.算法思路详解

  • 贪心:类似层序遍历的过程
    请添加图片描述

3.代码实现

bool canJump(vector<int>& nums) 
{
    int left = 0, right = 0, maxPos = 0, n = nums.size();
    while(left <= right)
    {
        if(maxPos >= n - 1)
        {
            return true;
        }

        for(int i = left; i <= right; i++)
        {
            maxPos = max(maxPos, nums[i] + i);
        }
        left = right + 1;
        right = maxPos;
    }

    return false;
}

2.加油站

1.题目链接


2.算法原理详解

  • 思路一:暴力解 —> 枚举 —> 会超时:P
    • 依次枚举所有的起点
    • 从起点开始,模拟一遍加油的流程即可
  • 思路二:优化暴力解法 —> 找规律(贪心)
    请添加图片描述

3.代码实现

// v1.0 暴力解
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) 
{
    int n = gas.size();
    for(int i = 0; i < n; i++) // 枚举起点
    {
        int rest = 0;
        for(int step = 0; step < n; step++) // 枚举向后走的步数
        {
            int index = (i + step) % n; // 求出走step步之后的下标
            rest = rest + gas[index] - cost[index];

            if(rest < 0)
            {
                break;
            }
        }

        if(rest >= 0)
        {
            return i;
        }
    }

    return -1;
}
--------------------------------------------------------------------
// v2.0 贪心
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) 
{
    int n = gas.size();
    for(int i = 0; i < n; i++) // 枚举起点
    {
        int rest = 0, step = 0;
        for(; step < n; step++) // 枚举向后走的步数
        {
            int index = (i + step) % n; // 求出走step步之后的下标
            rest = rest + gas[index] - cost[index];

            if(rest < 0)
            {
                break;
            }
        }

        if(rest >= 0)
        {
            return i;
        }

        i = i + step; // 优化
    }

    return -1;
}

3.单调递增的数字

1.题目链接


2.算法原理详解

  • 思路一:暴力枚举
    • 从大到小的顺序,枚举[n, 0]区间内的数字
    • 判断数字是否是“单调递增的”
  • 思路二:贪心
    • 如果高位单调递增,就不去修改
      • 因为高位如果修改了,那么该数大小会小非常多,影响较大
    • 从左往右,找到第一个递减的位置
      • 从这个位置向前推,推到相同区域的最左端
      • 使其减1,后面的数全部修改成9
        请添加图片描述

3.代码实现

int monotoneIncreasingDigits(int n) 
{
    string str = to_string(n); // 把数字转化为字符串,以便逐位操作

    int i = 0, m = str.size();

    // 找到第一个递减的位置
    while(i + 1 < m && str[i] <= str[i + 1])
    {
        i++;
    }

    // 特判
    if(i == m - 1)
    {
        return n;
    }

    // 回推
    while(i - 1 >= 0 && str[i] == str[i - 1])
    {
        i--;
    }

    // 操作
    str[i]--;
    for(int j = i + 1; j < m; j++)
    {
        str[j] = '9';
    }

    return stoi(str);
}

4.坏了的计算器

1.代码实现


2.算法原理详解

  • 思路一:正向推导,可用DFS解决
    请添加图片描述

  • 思路二:贪心 --> 正难则反

    • 从目标出发,执行/2+1操作
      请添加图片描述

3.代码实现

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;
}
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当谈到动态规划算法、回溯算法和贪心算法时,它们都是解决优化问题的经典算法。下面我会对每个算法进行详细讲解: 1. 动态规划算法(Dynamic Programming): 动态规划算法通常用于解决具有重叠子问题和最优子结构性质的问题。它通过将问题分解为子问题,并利用子问题的解来构建更大规模的问题的解。动态规划算法通常使用一个表格或数组来存储中间结果,避免重复计算。其基本思想是通过保存并重复使用子问题的解来减少计算量。 2. 回溯算法(Backtracking): 回溯算法是一种通过试错的搜索方法,用于求解满足一定条件的所有可能的解。回溯算法通过尝试每一种可能的选择并在达到不可行解时进行回溯,即返回上一层并尝试其他选择。回溯算法通常使用递归来实现,它能够穷尽所有可能的解空间,并找到满足条件的解。 3. 贪心算法(Greedy Algorithm): 贪心算法是一种通过每一步的局部最优选择来构建整体最优解的算法。贪心算法在每个步骤上都选择当前最优的解,而不考虑整体未来的结果。它通常不会回溯或重新评估之前的选择。贪心算法适用于一些特定类型的问题,如最小生成树、最短路径等,但并不适用于所有问题。 这三种算法各有优势和局限性,选择哪种算法取决于问题的性质和要求。动态规划算法通常适用于具有重叠子问题和最优子结构的问题,回溯算法适用于穷尽搜索所有可能解的问题,而贪心算法适用于局部最优解构成整体最优解的问题。在选择算法时,需要根据问题的特点和约束进行综合考虑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DieSnowK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值