贪心算法——删数问题

116 阅读1分钟

问题:输入正整数 n ,去掉其中任意 s 个数字后剩下的数字按原左右次序将组成一个新的正整数,使得到的正整数最小。



算法思想:

从高位向低位进行搜索:

  • 如果A[i…j]是一条非递减序列,那么就删除最后一个数;
  • 如果A[i…j]是严格递减子序列,那么就删除该序列的第一个数。

注意:删除是物理删除,即某个元素删除后后面的元素会前移补齐。另外,删除后各个元素之间的相对位置是不变的。




代码

#include <iostream>
using namespace std;

int main()
{

    int i = 0, n, count = 0;
    string str;

    cin >> str;
    cin >> n;
    int len = str.length();

    while (i < len && count < n)
    {
        i = 0;                       // 每次都回到整个序列的首位,从当前序列的最高位开始往后找
        while (str[i] <= str[i + 1]) // 寻找非递减序列的末位;寻找递减序列的首位不用遍历
            i++;
        cout << "第" << count + 1 << "次删除的元素:" << str[i] << endl;
        str.erase(i, 1); // 物理删除,即删除后后面元素依次自动前移
        count++;
    }
    cout << endl;

    
    /// 处理0的问题,即省略新正整数前面高位的0
    i = 0;
    len = str.length();  // 因为是新的str,所以要重新计算长度
    while (str[i] == '0' && i < len)
        i++;    // 统计一下从左到右0的个数
    if (i == len)     // 如果是全0,则直接输出0
        cout << "0" << endl;  
    else              // 从不为0的地方开始输出
        cout << str.substr(i, len) << endl;    // param1:开始截取的坐标 param2:截取的长度(若越界则视为到最后一位)

    return 0;
}

/*

999654 3
949596 4
30000 3
300004 3
141915
178543 4
908070605040302010
4236549134602476000415780145127514651014356713451437854733046235543680154682474181058435618576942381501235901569012564083175658103514832760
60
6

*/




运行结果