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!
再去測通過率!
.........
我...無話可說
求大佬救救孩子啊!!