保留最大的数(C++)

题目描述

给定一个十进制的正整数number,选择从里面去掉一部分数字,希望保留下来的数字组成的正整数最大。

输入描述:

输入为两行内容,第一行是正整数number,1 ≤ length(number) ≤ 50000。第二行是希望去掉的数字数量cnt 1 ≤ cnt < length(number)。

输出描述:

输出保留下来的结果。

示例1

输入

325  1

输出

35

看到这个题之后,作为一个刚学了一个月C++的菜鸡,我最初的想法非常简单粗暴,就是想办法找到最小的那个数,然后把它删除,这样就能保留最大的数。

#include <bits/stdc++.h>
using namespace std;
//第一代
int main()
{
    string number;
    int cnt;
    cin >> number >> cnt;
    while(cnt--)
    {
        //找最小的数字所在位置
        int len = number.length();
        int minIndex = 0;
        for(int i=0;i<len;i++)
        {
            if(number[i] < number[minIndex])
            {
                minIndex = i;
            }
        }
        //删除数组中的元素
        for(int i=0;i<len;i++)
        {
            if(i==minIndex)
            {
               number.erase(i,1);
            }
        }
    }
    cout << number << endl;
    return 0;
}

这个算法只能通过牛客网上30%的测试用例。比如当输入"123450  1"时,我们预期的答案应该是23450,但是算法是通过找出最小的数字所在位置,再把它删除来获取最大值的。算法得出结果是12345,显然算法还存在缺陷。

这就有点尴尬了,问了下学姐,她说试试从最高位开始把相邻的两个数字作比较,如果前一位比后一位小就删掉前一位,因为要使一个数大的话 尽量让最高位大就行了。于是我在第一代的基础上修改之后,写出了这道题第二代算法。

#include <bits/stdc++.h>
using namespace std;
//第二代
int main()
{
    string number;
    int cnt;
    cin >> number >> cnt;
    while(cnt--)
    {
        //找最高位且大于次位的数字所在位置
        int len = number.length();
        int Index = 0;
        for(int i=0;i<len-1;i++)
        {
            if(number[i] < number[i+1])
            {
                Index = i;
                break;
            }
        }
        //删除数组中的元素
        for(int i=0;i<len;i++)
        {
            if(i==Index)
            {
               number.erase(i,1);
            }
        }
    }
    cout << number << endl;
    return 0;
}

第二代不愧是第二代,它能通过牛客网上80%的测试用例。好尴尬啊,问题出在哪呢? 经过多次调试可以发现,当Index没有发生改变时,这个算法就会出错。比如当输入"543210  1"时,Index一直等于零,所以在删除元素的时候,最高位会被直接删除,从而得到结果43210,这与我们预期的结果54321不同。

这可咋办呢? 在思考片刻之后,case通过率30%+80%会不会等于100%呢?然后我把第一代算法和第二代算法结合在一起,写出来了这题的第三代算法,果然全部AC。

#include <bits/stdc++.h>
using namespace std;
//第三代
int main()
{
    string number;
    int cnt;
    cin >> number >> cnt;
    while(cnt--)
    {
        //找最高位且大于次位的数字所在位置
        int len = number.length();
        int Index = 0;
        bool flag = true;    //flag为真,说明Index没有变过
        for(int i=0;i<len-1;i++)
        {
            if(number[i] < number[i+1])
            {
                Index = i;
                flag = false;
                break;
            }
        }
        //如果Index从没变过
        if(flag)
        {
            //找最小的数字所在位置
            int len = number.length();
            Index = 0;
            for(int i=0;i<len;i++)
            {
                if(number[i] < number[Index])
                {
                    Index = i;
                }
            }
        }
        //删除数组中的元素
        for(int i=0;i<len;i++)
        {
            if(i==Index)
            {
               number.erase(i,1);
            }
        }
    }
    cout << number << endl;
    return 0;
}

额 顺便简述一下string.erase()函数的使用,如下: 

erase函数的原型 erase函数的用法 erase函数的文字解释
(1)string& erase ( size_t pos = 0, size_t n = npos ); erase(pos,n); 删除从pos开始的n个字符
(2)iterator erase ( iterator position ); erase(position); 删除迭代器位置处的单个字符, 并返回下个元素的迭代器
(3)iterator erase ( iterator first, iterator last ); erase(first,last); 删除迭代器[first, last)区间的所有字符,返回一个指向被删除的最后一个元素的下一个字符的迭代器

直到这篇博文写完,我还是不敢相信这居然是2017校招真题。。。。。

膜拜某大佬简洁明了C++的代码,20行真的牛批。。。可能是因为我还没真正地理解erase()这个函数的精髓。

。

扫描二维码关注公众号,回复: 3716720 查看本文章

好了,时候不早了,大家晚安。

。

猜你喜欢

转载自blog.csdn.net/weixin_42449444/article/details/82951487
今日推荐