(笔试题)删除K位数字

题目:

现有一个 n 位数,你需要删除其中的 k 位,请问如何删除才能使得剩下的数最大?

比如当数为 2319274, k=1 时,删去 2 变成 319274 后是可能的最大值。

思路:

1、贪心算法

每次从高位向低位数,删除高位数字比低位数字小的那位数字。如2319274

第一次2<3,删除2,得到319274

第二次3>1,略过,1<9,删除1,得到39274

第三次3<9,删除3,得到9274

。。。。。。

// greedy method
string deleteKBits_1(string str,int k){
    int tlen=str.length();
    bool flag=true;
    int len;
    while(k && flag){
        len=str.length();
        for(int i=0;i<len-1;i++){
            if(str[i]<str[i+1]){
                str.erase(i,1);
                flag=true;
                break;
            }
        }
        k--;
    }
    return str.substr(0,tlen-k);
}

2、动态规划

分析:

假设str为长度为n的数字字符串,S[i][j]表示删除str[0...i-1]中j个数字后的最大字符数字。

如果删除第i个数,则S[i][j]等于删除前i-1个字符中的j-1位的最优解,即S[i][j]=S[i-1][j-1];

如果不删除第i个数,则S[i][j]等于删除前i-1个字符中j位的最优解+str[i],即S[i][j]=S[i-1][j]+str[i-1];

即S[i][j]=max(S[i-1][j-1],S[i-1][j]+str[i-1])

初始状态为当j=0时,不删除任何位的数字,即S[i][j]=str[0...i-1];

状态转移方程如下:

S[i][j]=

strsub(0,i); (if j==0)

max(S[i-1][j-1],S[i-1][j]+str[i-1]); (if 0<j<i;0<j<=k)

时间复杂度:O(n*k)

空间复杂度:O(n*k)

优化:

从上述的转移方程S[i][j]=max(S[i-1][j-1],S[i-1][j]+str[i-1]),可以看出在每一次i循环中,只与i-1相关,因此不需要用单独使用一个维度的数组来存储,只需要每次通过一个变量last保存上一次的结果。因此转移方程可以简化为S[j]=max(last,S[j]+str[i-1])

时间复杂度:O(n*k)

空间复杂度:O(k)

// dynamic programming
// time complexity: O(n*k)
// space complexity: O(n*k)
string deleteKBits_2(string str,int k){
    int tlen=str.length();
    vector<vector<string> > nums(tlen+1,vector<string>(k+1));
    string s1,s2;
    for(int i=1;i<=tlen;i++){
        for(int j=0;j<i && j<=k;j++){
            if(j==0){
                nums[i][j]=str.substr(0,i);
            }
            else{
                s1=nums[i-1][j-1];
                s2=nums[i-1][j]+str[i-1];
                if(s1.compare(s2)<=0)
                    nums[i][j]=s2;
                else
                    nums[i][j]=s1;
            }
        }
    }
    return nums[tlen][k];
}

// dynamic programming
// time complexity: O(n*k)
// space complexity: O(k)
string deleteKBits_3(string str,int k){
    int tlen=str.length();
    vector<string> nums(k+1);
    string s1,s2,last;
    for(int i=1;i<=tlen;i++){
        for(int j=0;j<i && j<=k;j++){
            if(j==0){
                last=nums[j];
                nums[j]=str.substr(0,i);
            }
            else{
                // s1=last
                s1=nums[j-1];
                s2=nums[j]+str[i-1];
                if(s1.compare(s2)<=0){
                    last=nums[j];
                    nums[j]=s2;
                }
                else{
                    last=nums[j];
                    nums[j]=s1;
                }
            }
        }
    }
    return nums[k];
}

// dynamic programming
// time complexity: O(n*k)
// space complexity: O(k)
string deleteKBits_4(string str,int k){
    int tlen=str.length();
    vector<string> nums(k+1);
    string tmp,s2,last;
    for(int i=1;i<=tlen;i++){
        for(int j=0;j<i && j<=k;j++){
            if(j==0){
                last=nums[j];
                nums[j]=str.substr(0,i);
            }
            else{
                // s1=last
                // s1=nums[j-1];
                s2=nums[j]+str[i-1];
                if(last.compare(s2)<=0){
                    last=nums[j];
                    nums[j]=s2;
                }
                else{
                    tmp=nums[j];
                    nums[j]=last;
                    last=tmp;
                }
            }
        }
    }
    return nums[k];
}

运行结果:

int main()
{
    string str="2319274";
    int k=3;
    cout <<deleteKBits_1(str,k)<< endl;
    cout <<deleteKBits_2(str,k)<< endl;
    cout <<deleteKBits_3(str,k)<< endl;
    cout <<deleteKBits_4(str,k)<< endl;
    return 0;
}

 

原文地址:https://www.cnblogs.com/AndyJee/p/4527382.html