1. 程式人生 > >c++程式設計題 保留最大的數

c++程式設計題 保留最大的數

終於到家了!開始好好學習演算法及資料結構〜

這是一道兩天前就在寫的題,演算法是想出來了,但是讀入的時候總是出現問題!

分享下我的解題歷程吧〜

題目如下:

題目描述

給定一個十進位制的正整數數目,選擇從裡面去掉一部分數字,希望保留下來的數字組成的正整數最大。

輸入描述:

輸入為兩行內容,第一行是正整數number,1 ≤ length(number) ≤ 50000。第二行是希望去掉的數字數量cnt 1 ≤ cnt < length(number)。

輸出描述:

輸出保留下來的結果。

示例1

輸入

325 1

輸出

35

以下是我最開始的程式碼:

#include<iostream>
#include<math.h>
#include<string>

using namespace std;

int main(void){
    int number=0; //讀入的資料
    int cnt=0;    //讀入資料要減去的位數

    cin>>number>>cnt;

    int a[50000];
   
    int count=0;    //讀入資料的位數

    for(int i=0;i<50000;i++){
        a[i]=number % 10;     //按位數儲存每位數(通過取餘)
        number/=10;
        if(a[i]!=0) count++;
        else break;
    }

    if(a[0]==0) count++;

    int index=0;        //減去對應位數後剩下數字的位數
    index=count-cnt;

    int jindex=0;    //找到起始的最大一位數的下標

    int max=a[index];
    for(int j=index-1;j<count;j++){    //因為一共有index位,所以最大的第一位數肯定在a[index-1]~a[count-1]之間(其後面應有足夠的位數使得數字減去後仍有index位)
        if(a[j]>=max) {        //找到最大的第一位數,存在max裡,下標為jindex
            max=a[j];
            jindex=j;
        }
    }

    int kmax[5000];    //儲存剩下最大的index-1位數

    for(int k=jindex-1;k>=0;k--){    //從之前的jindex-1開始尋找
        kmax[k]=a[k];
        for (int h=k;h>=(index-1+(k-jindex));h--){          //同理,其後面應有足夠的位數使得數字減去後仍有(index-1+(k-jindex)位
            if(a[h]>kmax[k]){
                kmax[k]=a[h];
                a[h]=0;
            }
        }
    }
    string s;
    for(int x = jindex-1;x>=(jindex-index+1);x--){    //整數轉字串並依次拼接
        string p=std::to_string(kmax[x]);
        s+=p;
    }
    string t=std::to_string(max);
    t+=s;
    cout<<t;
}

用到的知識點:

1、數字轉字串

string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);

例子:

// to_string example
#include <iostream>   // std::cout
#include <string>     // std::string, std::to_string
 
int main ()
{
  std::string pi = "pi is " + std::to_string(3.1415926);
  std::string perfect = std::to_string(1+2+4+7+14) + " is a perfect number";
  std::cout << pi << '\n';
  std::cout << perfect << '\n';
  return 0;
}

---------------

最開始自己想的資料測的,得到的結果都是對的,所以雄心壯志的點了“儲存程式碼並測試”,結果告訴我通過率只有20%,好吧..一下打趴。

於是開始多換幾個資料,還是沒問題啊?怎麼回事呢?

胡亂輸入了一個很長的資料,發現程式根本沒等待我輸入第二個資料,就自己跳出來一個結果(而且當然是不對的)。

然後才反應過來 - 啊,INT溢位了!

改成double = 0呢?

----

這-8是什麼鬼!還是讀入有問題啊!

一拍腦門,嘿,這傻子,雙型別是浮點數,不能取餘啊!想啥呢!

改成long long int number = 0!

嘿嘿〜成功!

再去測!

ok...

又去試了更長的數,果然還是讀入的問題..而且似乎這個網站大多數的測試用例都是長資料..

我完全懵比不知道咋個辦了......

只好看看通過的大佬的程式碼,學習下吧..

#include <bits/stdc++.h>
   
using namespace std;
const int maxn = 5e4 + 20;
char str[maxn], s[maxn];
int k, top = 0, num = 0;
   
int main() {
    scanf("%s%d", str, &k);
    int len = strlen(str);
    for (int i = 0; i < len; i++) {
        while (top > 0 && s[top - 1] < str[i] && num < k) {
            num++;
            top--;
        }
        s[top++] = str[i];
    }
    top = min(top, len - k);
    s[top] = '\0';
    puts(s);
    return 0;
}

......我承認我被秀到了。

原來讀入按字串就可以了啊!摔!

-----------------

讀入程式碼改為:

long int count=number.length();        //注意str.length()返回的資料型別是size_t,故前面用long int,否則會報警告
    for(int i=0;i<count;i++){
        a[count-1-i]=int(number[i])-48;    //這裡也需要修改,之前程式碼是a[0]存的個位數,如果不改就是a[0]存最高位數了(字串的第一個字元)。而且轉換為int後得到的是ASCII的號碼,如‘1’對應49,故應該減去48.
    }

最終程式碼如下:

#include<iostream>
#include<math.h>
#include<string>


using namespace std;

int main(void){
    string number;    //這裡最開始初始化只改了型別,忘了把=0刪掉,一直報越界錯誤,我還一直以為是下面讀取的問題。。。
    int cnt=0;
    cin>>number>>cnt;
    int a[50000];
    long int count=number.length();
    for(int i=0;i<count;i++){
        a[count-1-i]=int(number[i])-48;
    }

    long int index=0;
    index=count-cnt;
    long int jindex=0;
    int max=a[index];
    for(long int j=index-1;j<count;j++){
        if(a[j]>=max) {
            max=a[j];
            jindex=j;
        }
    }

    int kmax[5000];
    for(long int k=jindex-1;k>=0;k--){
        kmax[k]=a[k];
        for (long int h=k;h>=(index-1+(k-jindex));h--){
            if(a[h]>kmax[k]){
                kmax[k]=a[h];
                a[h]=0;
            }
        }
    }
    string s;
    for(long int x = jindex-1;x>=(jindex-index+1);x--){
        string p=std::to_string(kmax[x]);
        s+=p;
    }
    string t=std::to_string(max);
    t+=s;
    cout<<t;
}

測試長資料:

完全OK!

再去測通過率!

.........

我...無話可說

求大佬救救孩子啊!!