【贪心算法】(经典实战应用解析(三):K次取反后最⼤化的数组和、按⾝⾼排序、优势洗牌、最⻓回⽂串、增减字符串匹配)


🔥承渊政道: 个人主页
❄️个人专栏: 《C语言基础语法知识》 《数据结构与算法》 《C++知识内容》 《Linux系统知识》 《算法刷题指南》 《测评文章活动推广》 《大模型语言路线学习》
✨逆境不吐心中苦,顺境不忘来时路!✨ 🎬 博主简介:

在算法学习中,贪心算法一直是一个既"直观"又"容易踩坑"的专题.它的核心思想看似简单:每一步都选择当前看来最优的方案,最终希望得到全局最优解.但真正落到题目中,难点往往不在于"会不会贪",而在于如何找到正确的贪心策略,以及如何证明这个策略不会出错 .本篇文章将继续围绕贪心算法的经典实战应用展开,通过几个非常具有代表性的题目,进一步体会贪心思想在不同场景下的灵活运用.我们会依次分析:K 次取反后最大化的数组和、根据身高重建队列、优势洗牌、最长回文串、增减字符串匹配等问题.这些题目表面上涉及数组、排序、字符串、双指针等不同知识点,但背后都隐藏着一个共同思路:在合适的时机做出局部最优选择,并让这些选择逐步逼近整体最优.通过本篇内容,希望你不仅能够掌握这些题目的解法,更能理解每道题中贪心策略的设计逻辑,为后续解决更复杂的贪心问题打下基础.废话不多说,下面跟着小编的节奏🎵一起去疯狂的学习吧!

目录

1.K次取反后最⼤化的数组和(OJ题)


解法(贪心):
贪心策略 :分情况讨论,设整个数组中负数的个数为 m 个:

a. m > k:把前 k 小负数,全部变成正数;

b. m == k:把所有的负数全部转化成正数;

c. m < k

i. 先把所有的负数变成正数;

ii. 然后根据 k - m 的奇偶分情况讨论:

  1. 如果是偶数,直接忽略;

  2. 如果是奇数,挑选当前数组中最小的数,变成负数.






核心代码

cpp 复制代码
class Solution
{
public:
    //函数功能:对数组进行k次取反操作,返回能得到的最大数组和
    //参数:nums-目标数组;k-取反次数
    int largestSumAfterKNegations(vector<int>& nums, int k)
    {
        //m:统计数组中**负数的个数**
        //minElem:记录数组中**绝对值最小的元素**(初始为int最大值)
        //n:数组的长度
        int m = 0, minElem = INT_MAX, n = nums.size();
        
        //第一次遍历数组:统计负数数量 + 找绝对值最小的数
        for(auto x : nums)
        {
            //如果当前数字是负数,负数计数+1
            if(x < 0) 
                m++;
            //更新绝对值最小的元素
            minElem = min(minElem, abs(x)); 
        }

        //最终结果:最大数组和
        int ret = 0;
        
        //情况1:负数的数量 大于 取反次数k
        if(m > k)
        {
            //对数组升序排序(最小的负数排在最前面)
            sort(nums.begin(), nums.end());
            
            //把前k个最小的负数取反为正数,累加到结果
            for(int i = 0; i < k; i++) 
            {
                ret += -nums[i];
            }
            
            //剩余数字直接累加(保持原值)
            for(int i = k; i < n; i++) 
            {
                ret += nums[i];
            }
        }
        //情况2:负数的数量 小于等于 取反次数k
        else
        {
            //第一步:把所有负数都取反为正数,累加总和
            for(auto x : nums) 
                ret += abs(x);

            //剩余取反次数:k - m(所有负数转正后,还剩的取反次数)
            //如果剩余次数是**奇数**:需要对绝对值最小的数再取反一次(总和 -= 2*minElem)
            //如果剩余次数是**偶数**:取反两次抵消,无需操作
            if((k - m) % 2) 
            {
                ret -= minElem * 2;
            }
        }
        //返回最终最大和
        return ret;
    }
};

完整测试代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Solution
{
public:
    // 函数功能:对数组进行 k 次取反操作,返回能得到的最大数组和
    // 参数:nums - 目标数组;k - 取反次数
    int largestSumAfterKNegations(vector<int>& nums, int k)
    {
        // m:统计数组中负数的个数
        // minElem:记录数组中绝对值最小的元素
        // n:数组的长度
        int m = 0, minElem = INT_MAX, n = nums.size();

        // 第一次遍历数组:统计负数数量 + 找绝对值最小的数
        for (auto x : nums)
        {
            if (x < 0)
                m++;

            minElem = min(minElem, abs(x));
        }

        // 最终结果:最大数组和
        int ret = 0;

        // 情况1:负数的数量大于取反次数 k
        if (m > k)
        {
            // 对数组升序排序,最小的负数排在最前面
            sort(nums.begin(), nums.end());

            // 把前 k 个最小的负数取反为正数,累加到结果
            for (int i = 0; i < k; i++)
            {
                ret += -nums[i];
            }

            // 剩余数字直接累加
            for (int i = k; i < n; i++)
            {
                ret += nums[i];
            }
        }
            // 情况2:负数的数量小于等于取反次数 k
        else
        {
            // 把所有负数都取反为正数,累加总和
            for (auto x : nums)
                ret += abs(x);

            // 如果剩余次数是奇数,需要对绝对值最小的数再取反一次
            if ((k - m) % 2)
            {
                ret -= minElem * 2;
            }
        }

        return ret;
    }
};

void printVector(const vector<int>& nums)
{
    cout << "[";

    for (size_t i = 0; i < nums.size(); i++)
    {
        cout << nums[i];

        if (i != nums.size() - 1)
            cout << ", ";
    }

    cout << "]";
}

int main()
{
    Solution sol;

    vector<pair<vector<int>, int>> testCases = {
            {{4, 2, 3}, 1},              // 取反 2:[-2] -> 2,结果 5
            {{3, -1, 0, 2}, 3},          // 有 0,剩余取反次数可作用在 0 上,结果 6
            {{2, -3, -1, 5, -4}, 2},     // 取反 -4 和 -3,结果 13
            {{-8, 3, -5, -3, -5, -2}, 6},// 负数数量 <= k,剩余次数为奇数
            {{-1, -2, -3, -4}, 2},       // 负数数量 > k,只取反最小的两个负数
            {{-1, -2, -3, -4}, 4},       // 所有负数都取反
            {{-1, -2, -3, -4}, 5},       // 所有负数取反后,剩余奇数次
            {{1, 2, 3, 4}, 2},           // 全是正数,偶数次取反,结果不变
            {{1, 2, 3, 4}, 1},           // 全是正数,奇数次取反,取反最小值 1
            {{0, 1, 2, 3}, 5},           // 有 0,剩余取反次数不影响结果
            {{-5}, 1},                   // 单个负数,取反后为 5
            {{5}, 1},                    // 单个正数,取反后为 -5
            {{5}, 2},                    // 单个正数,取反两次仍为 5
            {{-2, 9, 9, 8, 4}, 5}        // 剩余奇数次,取反绝对值最小的 2
    };

    for (int i = 0; i < testCases.size(); i++)
    {
        vector<int> nums = testCases[i].first;
        int k = testCases[i].second;

        cout << "测试用例 " << i + 1 << ":";
        printVector(nums);
        cout << ",k = " << k << endl;

        cout << "最大数组和:";
        cout << sol.largestSumAfterKNegations(nums, k) << endl;

        cout << "------------------------" << endl;
    }

    return 0;
}

2.按身高排序(OJ题)


解法(通过排序"索引"的方式):
算法思路 :我们不能直接按照 i 位置对应的 heights 来排序,因为排序过程是会移动元素的,但是 names 内的元素是不会移动的.由题意可知,names 数组和 heights 数组的下标是一一对应的,因此我们可以重新创建出来一个下标数组,将这个下标数组按照 heights[i] 的大小排序.

那么,当下标数组排完序之后,里面的顺序就相当于 heights 这个数组排完序之后的下标.之后通过排序后的下标,依次找到原来的 name,完成对名字的排序.






核心代码

cpp 复制代码
class Solution
{
public:
    //参数:names-姓名数组;heights-身高数组(一一对应)
    //返回值:按身高降序排列后的姓名数组
    vector<string> sortPeople(vector<string>& names, vector<int>& heights)
    {
        //获取数组长度(姓名和身高长度一致)
        int n = names.size();
        //1.创建下标数组 index:存储 0,1,2...n-1 原始下标
        //作用:不修改原数组,通过排序下标来关联姓名和身高,保证一一对应
        vector<int> index(n);
        for(int i = 0; i < n; i++) 
            index[i] = i;

        //2.对下标数组进行自定义排序
        //使用sort + lambda匿名函数:自定义排序规则
        //规则:按照身高 降序 排列(heights[i] > heights[j])
        sort(index.begin(), index.end(), [&](int i, int j)
        {
            //身高大的下标排在前面
            return heights[i] > heights[j];
        });

        //3.根据排序后的下标,提取对应的姓名,生成结果数组
        vector<string> ret;
        //遍历排序后的下标数组
        for(int i : index)
        {
            //按下标取出姓名,添加到结果中
            ret.push_back(names[i]);
        }
        //返回最终排序后的姓名数组
        return ret;
    }
};

完整测试代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

class Solution
{
public:
    // 参数:names - 姓名数组;heights - 身高数组(一一对应)
    // 返回值:按身高降序排列后的姓名数组
    vector<string> sortPeople(vector<string>& names, vector<int>& heights)
    {
        // 获取数组长度(姓名和身高长度一致)
        int n = names.size();

        // 1. 创建下标数组 index:存储 0,1,2...n-1 原始下标
        // 作用:不修改原数组,通过排序下标来关联姓名和身高,保证一一对应
        vector<int> index(n);
        for (int i = 0; i < n; i++)
            index[i] = i;

        // 2. 对下标数组进行自定义排序
        // 规则:按照身高降序排列
        sort(index.begin(), index.end(), [&](int i, int j)
        {
            return heights[i] > heights[j];
        });

        // 3. 根据排序后的下标,提取对应的姓名,生成结果数组
        vector<string> ret;

        for (int i : index)
        {
            ret.push_back(names[i]);
        }

        return ret;
    }
};

void printStringVector(const vector<string>& arr)
{
    cout << "[";

    for (size_t i = 0; i < arr.size(); i++)
    {
        cout << "\"" << arr[i] << "\"";

        if (i != arr.size() - 1)
            cout << ", ";
    }

    cout << "]";
}

void printIntVector(const vector<int>& arr)
{
    cout << "[";

    for (size_t i = 0; i < arr.size(); i++)
    {
        cout << arr[i];

        if (i != arr.size() - 1)
            cout << ", ";
    }

    cout << "]";
}

int main()
{
    Solution sol;

    vector<pair<vector<string>, vector<int>>> testCases = {
            {{"Mary", "John", "Emma"}, {180, 165, 170}},
            {{"Alice", "Bob", "Bob"}, {155, 185, 150}},
            {{"Tom"}, {175}},
            {{}, {}},
            {{"A", "B", "C", "D"}, {160, 170, 180, 190}},
            {{"A", "B", "C", "D"}, {190, 180, 170, 160}},
            {{"Zhang", "Li", "Wang", "Zhao"}, {172, 172, 180, 165}},
            {{"小明", "小红", "小刚"}, {168, 172, 165}}
    };

    for (int i = 0; i < testCases.size(); i++)
    {
        vector<string> names = testCases[i].first;
        vector<int> heights = testCases[i].second;

        cout << "测试用例 " << i + 1 << ":" << endl;

        cout << "姓名数组:";
        printStringVector(names);
        cout << endl;

        cout << "身高数组:";
        printIntVector(heights);
        cout << endl;

        vector<string> result = sol.sortPeople(names, heights);

        cout << "按身高降序排列后的姓名数组:";
        printStringVector(result);
        cout << endl;

        cout << "------------------------" << endl;
    }

    return 0;
}

3.优势洗牌(田忌赛马)(OJ题)


解法(贪心):

讲一下田忌赛马背后包含的博弈论和贪心策略:

田忌赛马没听过的自行百度,这里讲一下田忌赛马背后的博弈决策,从三匹马拓展到 n 匹马之间博弈的最优策略.

田忌:下等马 中等马 上等马

齐王:下等马 中等马 上等马

a. 田忌的下等马 pk 不过齐王的下等马,因此把这匹马丢去消耗一个齐王的最强战马!

b. 接下来选择中等马 pk 齐王的下等马,勉强获胜;

c. 最后用上等马 pk 齐王的中等马,勉强获胜.

由此,我们可以得出一个最优的决策方式:

a. 当己方此时最差的比不过对面最差的时候,让我方最差的去处理掉对面最好的(反正要输,不如去拖掉对面一个最强的);

b. 当己方此时

c. 最差的能比得上对面最差的时候,就让两者比对下去(最差的都能获胜,为什么要输呢).

每次决策,都会使我方处于优势.






核心代码

cpp 复制代码
class Solution
{
public:
    vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2)
    {
        //获取数组长度(两个数组长度相同)
        int n = nums1.size();

        //第一步:预处理排序
        //对 nums1 进行升序排序(从小到大,方便田忌赛马策略匹配)
        sort(nums1.begin(), nums1.end());
        
        //创建 nums2 的下标数组 index2:存储 0,1,2...n-1 原始下标
        vector<int> index2(n);
        for(int i = 0; i < n; i++) 
            index2[i] = i;
        
        //对下标数组 index2 排序:按照 nums2 对应的值**升序**排列
        //作用:记录 nums2 从小到大的原始位置,保证排序后不丢失原位置信息
        sort(index2.begin(), index2.end(), [&](int i, int j)
        {
            return nums2[i] < nums2[j];
        });

        //第二步:田忌赛马贪心策略
        //结果数组 ret:存储最终的优势排列
        vector<int> ret(n);
        //双指针:
        //left 指向 nums2 中**最小元素**的原始下标
        //right 指向 nums2 中**最大元素**的原始下标
        int left = 0, right = n - 1;

        //遍历**升序排序后的 nums1**(从小到大拿元素)
        for(auto x : nums1)
        {
            //核心策略:
            //如果当前 nums1 的最小元素 > nums2 的最小元素 → 用它赢下 nums2 的最小元素(对位)
            if(x > nums2[index2[left]]) 
            {
                ret[index2[left++]] = x;
            }
            //否则 → 用它去对抗 nums2 的最大元素(送人头,牺牲最小元素保大的)
            else 
            {
                ret[index2[right--]] = x;
            }
        }

        //返回最终的优势最大化排列
        return ret;
    }
};

完整测试代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Solution
{
public:
    vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2)
    {
        // 获取数组长度(两个数组长度相同)
        int n = nums1.size();

        // 第一步:预处理排序
        // 对 nums1 进行升序排序
        sort(nums1.begin(), nums1.end());

        // 创建 nums2 的下标数组 index2
        vector<int> index2(n);
        for (int i = 0; i < n; i++)
            index2[i] = i;

        // 对 index2 排序:按照 nums2 对应的值升序排列
        sort(index2.begin(), index2.end(), [&](int i, int j)
        {
            return nums2[i] < nums2[j];
        });

        // 第二步:田忌赛马贪心策略
        vector<int> ret(n);

        int left = 0, right = n - 1;

        // 遍历升序排序后的 nums1
        for (auto x : nums1)
        {
            // 如果当前 x 能赢 nums2 中最小的元素,就用它去赢
            if (x > nums2[index2[left]])
            {
                ret[index2[left++]] = x;
            }
                // 否则用它去对抗 nums2 中最大的元素
            else
            {
                ret[index2[right--]] = x;
            }
        }

        return ret;
    }
};

void printVector(const vector<int>& nums)
{
    cout << "[";

    for (size_t i = 0; i < nums.size(); i++)
    {
        cout << nums[i];

        if (i != nums.size() - 1)
            cout << ", ";
    }

    cout << "]";
}

// 计算优势数量:result[i] > nums2[i] 的个数
int countAdvantage(const vector<int>& result, const vector<int>& nums2)
{
    int count = 0;

    for (size_t i = 0; i < result.size(); i++)
    {
        if (result[i] > nums2[i])
            count++;
    }

    return count;
}

int main()
{
    Solution sol;

    vector<pair<vector<int>, vector<int>>> testCases = {
            {{2, 7, 11, 15}, {1, 10, 4, 11}},       // 示例:可获得 4 个优势
            {{12, 24, 8, 32}, {13, 25, 32, 11}},    // 示例:可获得 3 个优势
            {{1, 2, 3, 4}, {1, 2, 3, 4}},           // 相同数组,可获得 3 个优势
            {{4, 3, 2, 1}, {1, 2, 3, 4}},           // nums1 逆序输入
            {{1, 1, 1, 1}, {2, 2, 2, 2}},           // 全部无法取胜
            {{5, 5, 5, 5}, {1, 2, 3, 4}},           // 全部可以取胜
            {{2, 2, 2, 3}, {1, 2, 2, 2}},           // 包含重复元素
            {{8, 12, 24, 32}, {13, 25, 32, 11}},    // 接近示例,但 nums1 已升序
            {{10}, {5}},                            // 单个元素,能取胜
            {{3}, {5}},                             // 单个元素,不能取胜
            {{}, {}}                                // 空数组
    };

    for (int i = 0; i < testCases.size(); i++)
    {
        vector<int> nums1 = testCases[i].first;
        vector<int> nums2 = testCases[i].second;

        cout << "测试用例 " << i + 1 << ":" << endl;

        cout << "nums1:";
        printVector(nums1);
        cout << endl;

        cout << "nums2:";
        printVector(nums2);
        cout << endl;

        vector<int> result = sol.advantageCount(nums1, nums2);

        cout << "优势洗牌结果:";
        printVector(result);
        cout << endl;

        cout << "优势数量:";
        cout << countAdvantage(result, nums2) << endl;

        cout << "------------------------" << endl;
    }

    return 0;
}

4.最长回文串(OJ题)


解法(贪心):
贪心策略 :用尽可能多的字符去构造回文串:

a. 如果字符出现偶数个,那么全部都可以用来构造回文串;

b. 如果字符出现奇数个,减去一个之后,剩下的字符能够全部用来构造回文串;

c. 最后再判断一下,如果有字符出现奇数个,就把它单独拿出来放在中间.







核心代码

cpp 复制代码
class Solution
{
public:
    int longestPalindrome(string s)
    {
        //1.字符计数:用数组模拟哈希表
        //ASCII码共127个字符,创建数组hash统计每个字符出现的次数,初始化为0
        int hash[127] = { 0 };
        //遍历字符串,统计每个字符的出现次数
        for(char ch : s) 
            hash[ch]++;

        //2.计算最长回文串的基础长度(仅统计偶数次字符)
        int ret = 0;
        //遍历所有字符的计数
        for(int x : hash)
        {
            //回文串中,每个字符最多使用【偶数个】
            //x/2*2:向下取偶,比如3→2,5→4,2→2
            ret += x / 2 * 2;
        }

        //3.最终判断:
        //如果基础长度 < 原字符串长度 → 说明存在出现奇数次的字符
        //可以选1个奇数字符作为回文中心,总长度+1
        //如果相等 → 所有字符都是偶数次,直接返回
        return ret < s.size() ? ret + 1 : ret;
    }
};

完整测试代码

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

class Solution
{
public:
    int longestPalindrome(string s)
    {
        // 1.字符计数:用数组模拟哈希表
        // ASCII 码共 127 个字符,创建数组 hash 统计每个字符出现的次数
        int hash[127] = { 0 };

        // 遍历字符串,统计每个字符的出现次数
        for (char ch : s)
            hash[ch]++;

        // 2.计算最长回文串的基础长度(仅统计偶数次字符)
        int ret = 0;

        // 遍历所有字符的计数
        for (int x : hash)
        {
            // 回文串中,每个字符最多使用偶数个
            ret += x / 2 * 2;
        }

        // 3.如果存在奇数次字符,可以选 1 个作为回文中心
        return ret < s.size() ? ret + 1 : ret;
    }
};

int main()
{
    Solution sol;

    string testCases[] = {
            "abccccdd",     // dccaccd,长度 7
            "a",            // 单个字符,长度 1
            "bb",           // 两个相同字符,长度 2
            "abc",          // 只能选一个字符作为中心,长度 1
            "Aa",           // 区分大小写,长度 1
            "ccc",          // 可以使用 3 个 c,长度 3
            "bananas",      // a:3, n:2,最长长度 5
            "",             // 空字符串,长度 0
            "aabbcc",       // 全是偶数次,长度 6
            "aabbccd",      // 偶数字符 + 一个中心字符,长度 7
            "aabbccdde",    // 偶数字符 + 一个中心字符,长度 9
            "aaaabbbbcccd"  // a:4,b:4,c:3,d:1,最长长度 11
    };

    int n = sizeof(testCases) / sizeof(testCases[0]);

    for (int i = 0; i < n; i++)
    {
        cout << "测试用例 " << i + 1 << ":" << endl;
        cout << "字符串:\"" << testCases[i] << "\"" << endl;

        cout << "最长回文串长度:";
        cout << sol.longestPalindrome(testCases[i]) << endl;

        cout << "------------------------" << endl;
    }

    return 0;
}

5.增减字符串匹配(OJ题)


解法(贪心):
贪心策略

a. 当遇到 'I' 的时候,为了让下一个上升的数可选择的范围更多,当前选择最小的那个数;

b. 当遇到 'D' 的时候,为了让下一个下降的数可选择的范围更多,选择当前最大的那个数.






核心代码

cpp 复制代码
class Solution
{
public:
    vector<int> diStringMatch(string s)
    {
        //双指针贪心策略:
        //left 初始为 0(当前可用的最小值)
        //right 初始为 s.size()(当前可用的最大值,因为结果数组长度是 n+1,数值范围 0~n)
        int left = 0, right = s.size(); 
        //存储最终结果的数组
        vector<int> ret;

        //遍历字符串中的每一个字符(I/D)
        for(auto ch : s)
        {
            //遇到 'I' (Increase 递增):放入当前最小值,然后最小值+1
            if(ch == 'I') 
                ret.push_back(left++);
            //遇到 'D' (Decrease 递减):放入当前最大值,然后最大值-1
            else 
                ret.push_back(right--);
        }

        //遍历结束后,left 和 right 指向同一个数字,将最后这个剩余数字加入结果
        ret.push_back(left); 
        
        //返回满足条件的数组
        return ret;
    }
};

完整测试代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Solution
{
public:
    vector<int> diStringMatch(string s)
    {
        // 双指针贪心策略:
        // left 初始为 0,表示当前可用的最小值
        // right 初始为 s.size(),表示当前可用的最大值
        int left = 0, right = s.size();

        // 存储最终结果的数组
        vector<int> ret;

        // 遍历字符串中的每一个字符
        for (auto ch : s)
        {
            // 遇到 'I':放入当前最小值,然后最小值 +1
            if (ch == 'I')
                ret.push_back(left++);

                // 遇到 'D':放入当前最大值,然后最大值 -1
            else
                ret.push_back(right--);
        }

        // 最后 left 和 right 指向同一个剩余数字
        ret.push_back(left);

        return ret;
    }
};

void printVector(const vector<int>& nums)
{
    cout << "[";

    for (size_t i = 0; i < nums.size(); i++)
    {
        cout << nums[i];

        if (i != nums.size() - 1)
            cout << ", ";
    }

    cout << "]";
}

// 验证结果是否满足 I / D 条件
bool checkResult(const string& s, const vector<int>& result)
{
    if (result.size() != s.size() + 1)
        return false;

    for (int i = 0; i < s.size(); i++)
    {
        if (s[i] == 'I' && result[i] >= result[i + 1])
            return false;

        if (s[i] == 'D' && result[i] <= result[i + 1])
            return false;
    }

    return true;
}

int main()
{
    Solution sol;

    vector<string> testCases = {
            "IDID",     // 交替出现
            "III",      // 全部递增
            "DDI",      // 先降后升
            "DDD",      // 全部递减
            "I",        // 单个 I
            "D",        // 单个 D
            "",         // 空字符串
            "IIDDD",    // 前升后降
            "DDIII",    // 前降后升
            "IDDDI"     // 混合情况
    };

    for (int i = 0; i < testCases.size(); i++)
    {
        string s = testCases[i];

        cout << "测试用例 " << i + 1 << ":" << endl;
        cout << "字符串:\"" << s << "\"" << endl;

        vector<int> result = sol.diStringMatch(s);

        cout << "匹配结果:";
        printVector(result);
        cout << endl;

        cout << "是否满足条件:";
        cout << (checkResult(s, result) ? "true" : "false") << endl;

        cout << "------------------------" << endl;
    }

    return 0;
}

🚀真正的勇者不是流泪的人,而是含泪奔跑的人!


敬请期待下一篇文章内容的更新【贪心算法】(经典实战应用解析(四):分发饼干、最优除法、跳跃游戏、跳跃游戏Ⅱ、加油站)


每日心灵鸡汤: 人生就是这样,做着做着就有出路了!

余华老师说:抛弃旧的东西是很难的,但是往往旧的东西都会阻碍你们往前走.人生也是一样,如何让自己往前走,有时候你真的不得不,把自己最喜爱,最熟练的东西放下来.我所说的放弃不是完全得抛弃,因为很可能过几年之后你又把它找回来了.只要是属于你的东西,它会永远跟随你,它不会离开你,只是你要知道,你在不同的时间点,需要的是不同的东西.当你不得不去完成某个让你倍感压力的任务时,最好的对策就是马上去做,勇敢地去尝试.在看似余额充足的青春里,我们应该踏实地耐心地去做点什么,以后的日子多长本事,多看世界,多读书,把英语学好,保证自己随时都有走出去的能力.

相关推荐
三品吉他手会点灯1 小时前
C语言学习笔记 - 34.数据类型 - 编程规范与高效学习方法
c语言·开发语言·笔记·学习
Lucky_ldy1 小时前
C语言学习:动态内存管理(数据结构关键)
c语言·数据结构·学习
凌波粒1 小时前
LeetCode--100.相同的树(二叉树)
算法·leetcode·职场和发展
alexwang2111 小时前
P16473 [GKS 2013 #B] Sudoku Checker题解
c++·算法·题解·洛谷
咸甜适中1 小时前
rust语言学习笔记Trait之 AsRef 和 AsMut(引用转换)
笔记·学习·rust
一条鱼头1 小时前
c++11语法点
开发语言·c++
leon_teacher1 小时前
HarmonyOS 6 古诗学习宝实战:基于 Preferences 实现错题本自动派生与题级去重系统
学习·华为·harmonyos
Peter·Pan爱编程1 小时前
C++中的 const 与 volatile:比C强大十倍
c++·const·volatile·c++基础
lihao lihao1 小时前
MFC知识点
c++·mfc