数据结构与算法之贪心算法

贪心算法是一种常用的算法思想,它在每个阶段选择局部最优解,最终得到全局最优解。其原理可以概括为以下三点:

1.贪心选择性质:当我们决定做出一个选择时,我们只考虑当前所面临的局部最优解,而不考虑该选择可能导致的未来后果。

2.无后效性:一旦做出了某个选择,我们就不能更改它,也就是说,我们并不关心在这个选择之后可能出现的新局面。

3.子问题最优解:当我们将原问题分解成若干个子问题时,贪心算法能够保证每个子问题的最优解能够组合成原问题的最优解。

在这里插入图片描述



一、C 贪心算法 源码实现及详解

贪心算法是一种求解最优化问题的算法,它在每一步选择中都采取当前状态下最优的选择,从而导致最终结果是全局最优的。贪心算法通常需要证明其正确性,否则会出现不正确的结果。

以下是贪心算法的一般步骤:

  1. 构造可行解空间:首先需要思考如何构造可行解空间,并且需要保证可行解空间的构造方式具有贪心选择性质,即每次选择都是最优的选择。

  2. 选择最优解:在可行解空间中选择最优解,需要证明该选择具有贪心选择性质。

  3. 约束条件检验:对选择的最优解进行约束条件检验,确保选择的最优解是可行的。

  4. 终止条件检验:判断是否满足终止条件,如果满足则结束算法,否则继续执行第二步。

下面以一个例子来说明贪心算法的实现过程。

问题描述:

给定一个长度为n的字符串s,将其划分成若干个回文子串,使得每个子串都是回文串,并且划分的子串数量最少。例如,对于字符串“abacdc”,可以将其划分为“aba”、“cdc”两个回文子串,划分的数量是最少的。

解法:

以字符串“abacdc”为例,我们可以按照以下步骤进行划分:

  1. 从字符串的第一个字符开始,尝试找到以该字符为起点的最长回文子串,即找到字符串s中第i个字符到第j个字符之间的最长回文子串。

  2. 将该回文子串作为一个子串划分出来。

  3. 将剩余的字符串s[j+1:n]作为一个新的字符串s’,重复步骤1,直到s’为空。

实现代码如下:

#include <stdio.h>
#include <string.h>

#define MAXN 1005

int f[MAXN];  // f[i]表示前i个字符的最小划分数
int dp[MAXN][MAXN];  // dp[i][j]表示s[i...j]是否为回文子串

int main() {
    char s[MAXN];
    scanf("%s", s+1);
    int n = strlen(s+1);
    
    // 初始化dp数组
    for (int i = 1; i <= n; i++) dp[i][i] = 1;
    for (int i = 1; i < n; i++) {
        if (s[i] == s[i+1]) dp[i][i+1] = 1;
    }
    for (int k = 3; k <= n; k++) {
        for (int i = 1; i <= n-k+1; i++) {
            int j = i + k - 1;
            if (s[i] == s[j] && dp[i+1][j-1]) dp[i][j] = 1;
        }
    }
    
    // 计算f数组
    for (int i = 1; i <= n; i++) {
        f[i] = MAXN;  // 初始化为最大值
        if (dp[1][i]) f[i] = 1;  // 本身就是回文子串
        else {
            for (int j = 1; j < i; j++) {
                if (dp[j+1][i]) f[i] = f[i] < f[j]+1 ? f[i] : f[j]+1;
            }
        }
    }
    printf("%d\n", f[n]);
    return 0;
}

时间复杂度为 O ( n 2 ) O(n^2) O(n2),可以通过本题。

在这里插入图片描述



二、C++ 贪心算法 源码实现及详解

贪心算法是指在求解问题的过程中,总是选择当前最优的决策,而不考虑其对以后可能造成的影响,从而得到整体最优解的算法。在 C++ 中,贪心算法可以通过代码实现来解决一些问题。

例如,我们有一些活动,每个活动有开始时间和结束时间,现在我们需要安排这些活动,使得尽可能多的活动都能够被安排。我们可以使用贪心算法来解决。

具体实现步骤如下:

1.将所有活动按照结束时间从小到大排序。
2.选择第一个活动,并将它的结束时间记录为当前时间。
3.从剩下的活动中,选择开始时间大于等于当前时间,且结束时间最早的活动,并将它的结束时间记录为当前时间,重复该步骤直到所有活动都被选择完为止。

以下是具体的 C++ 代码实现:

#include <iostream>
#include <algorithm>
using namespace std;

const int MAX_N = 1000;

struct Activity {
    int start;
    int end;
} activities[MAX_N];

bool cmp(const Activity &a, const Activity &b) {
    return a.end < b.end;
}

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> activities[i].start >> activities[i].end;
    }
    sort(activities, activities + n, cmp);
    int cnt = 0, cur_end = -1;
    for (int i = 0; i < n; ++i) {
        if (activities[i].start >= cur_end) {
            cnt++;
            cur_end = activities[i].end;
        }
    }
    cout << cnt << endl;
    return 0;
}

上述代码定义了一个结构体 Activity ,表示活动的开始时间和结束时间。在主函数中,首先读入活动的数量和每个活动的开始时间和结束时间,然后将所有活动按照结束时间从小到大排序。

接着,我们依次遍历每个活动,如果它的开始时间大于等于当前时间,则将计数器 cnt 加 1 ,并将当前时间更新为该活动的结束时间。最后输出 cnt 的值即为答案。

以上就是使用 C++ 实现贪心算法的详细过程。在实际应用中,我们需要根据不同的问题特点,选择合适的贪心策略来解决问题。

在这里插入图片描述



三、java 贪心算法 源码实现及详解

贪心算法是指在求解问题的过程中,总是选择当前最优的决策,而不考虑其对以后可能造成的影响,从而得到整体最优解的算法。在 C++ 中,贪心算法可以通过代码实现来解决一些问题。

例如,我们有一些活动,每个活动有开始时间和结束时间,现在我们需要安排这些活动,使得尽可能多的活动都能够被安排。我们可以使用贪心算法来解决。

具体实现步骤如下:

1.将所有活动按照结束时间从小到大排序。
2.选择第一个活动,并将它的结束时间记录为当前时间。
3.从剩下的活动中,选择开始时间大于等于当前时间,且结束时间最早的活动,并将它的结束时间记录为当前时间,重复该步骤直到所有活动都被选择完为止。

以下是具体的 C++ 代码实现:

#include <iostream>
#include <algorithm>
using namespace std;

const int MAX_N = 1000;

struct Activity {
    int start;
    int end;
} activities[MAX_N];

bool cmp(const Activity &a, const Activity &b) {
    return a.end < b.end;
}

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> activities[i].start >> activities[i].end;
    }
    sort(activities, activities + n, cmp);
    int cnt = 0, cur_end = -1;
    for (int i = 0; i < n; ++i) {
        if (activities[i].start >= cur_end) {
            cnt++;
            cur_end = activities[i].end;
        }
    }
    cout << cnt << endl;
    return 0;
}

上述代码定义了一个结构体 Activity ,表示活动的开始时间和结束时间。在主函数中,首先读入活动的数量和每个活动的开始时间和结束时间,然后将所有活动按照结束时间从小到大排序。

接着,我们依次遍历每个活动,如果它的开始时间大于等于当前时间,则将计数器 cnt 加 1 ,并将当前时间更新为该活动的结束时间。最后输出 cnt 的值即为答案。

以上就是使用 C++ 实现贪心算法的详细过程。在实际应用中,我们需要根据不同的问题特点,选择合适的贪心策略来解决问题。

在这里插入图片描述






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值