数据结构算法系列----贪心算法

目录

一、什么是贪心

1、定义:

2、举例:

二、例题

完整代码:


一、什么是贪心

1、定义:

      贪心算法是一种在每一步选择中都采取当前状态下最优决策的算法。在贪心算法中,通过 局部最优 解来达到全局最优解。贪心算法通常用于解决最优化问题,每一步都采取当前状态下最优的选择,而不考虑之后的结果会如何。

   大家如果有学过数据结构这门课肯定会知道下面这个例子,通过这个例子能更好的理解贪心:

2、举例:

假设题目为:给定一个整数数组,找出数组中连续子数组的最大和。

题目描述: 给定一个整数数组,编写一个程序来找到数组中连续子数组(至少包含一个元素)的最大和,并返回这个最大和。

示例: 输入:[1, 3, 5, -4, 5, 2, 1] 输出:12 解释:连续子数组[1, 3, 5, -4, 5, 2, 1]的最大和为12。

这个问题可以用一个简单的贪心算法来解决。我们可以遍历整个数组,同时维护两个变量:`current_sum`表示当前位置的最大子段和,`max_sum`表示全局最大子段和。

   如果不会贪心,我们很容易想到用暴力的方法解决,双重循环第一层固定子段的头,第二层固定子段的尾。但是这样时间复杂度就为o(n²)了。所以这个时候我们就要引入贪心算法。

具体步骤如下:
1. 初始化`current_sum`和`max_sum`为数组的第一个元素。
2. 从第二个元素开始遍历数组:
   - 更新`current_sum`为当前元素值与`current_sum + 当前元素值`中的较大值。
   - 更新`max_sum`为`max(max_sum, current_sum)`,即全局最大子段和为当前位置的最大子段和和之前的全局最大子段和中的较大值。
3. 遍历完整个数组后,`max_sum`即为最大子段和。

这种方法的时间复杂度为O(n),其中n是数组的长度。

#include <iostream>
#include <vector>

using namespace std;

int maxSubArray(vector<int>& nums) {
    int current_sum = nums[0];
    int max_sum = nums[0];

    for (int i = 1; i < nums.size(); i++) {
        current_sum = max(nums[i], current_sum + nums[i]);
        max_sum = max(max_sum, current_sum);
    }

    return max_sum;
}

int main() {
    vector<int> nums = {1, 3, 5, -4, 5, 2, 1};
    int result = maxSubArray(nums);
    cout << "Maximum sum of subarray: " << result << endl;

    return 0;
}

二、例题

【牛客】-道路铺设

https://ac.nowcoder.com/acm/problem/21222

   因为这个题目可以选择区间去减少深度,所以我们很容易想到要得出答案观察连续的区间即可,我们从头开始,如果是一段连续递减序列那么其实这个序列需要减掉的就是最大值,比如说5 3 3 1

先【1,4】减一次,再【1,3】两次,再【1,1】一次,一共就是五次。但是当这个不是一个连续递减序列是比如5 3 3 1 5的手这个区间【1,5】的时候就变为4 2 2 0 4不能一起减了,因为被0隔开了,所以我们要先像上面那样处理完前一个区间,再来处理这个4,所以能得到如果不递减的时候答案要加上这个不递减的值减去前面的值。

完整代码:

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n, ans;
    cin >> n; // 输入数组长度
    vector<int> a(n); // 定义大小为n的整数数组
    cin >> a[0]; // 输入第一个元素
    ans = a[0]; // 初始化最大子段和为第一个元素

    // 遍历数组
    for(int i = 1; i < n; i++){
        cin >> a[i]; // 输入当前元素
        if(a[i] >= a[i-1]){
            ans += a[i] - a[i-1]; // 如果当前元素大于等于前一个元素,将其加入最大子段和
        } 
    }

    cout << ans << endl; // 输出最大子段和
    return 0;
}

  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值