终于到家了!开始好好学习算法及数据结构〜
这是一道两天前就在写的题,算法是想出来了,但是读入的时候总是出现问题!
分享下我的解题历程吧〜
题目如下:
题目描述
给定一个十进制的正整数数目,选择从里面去掉一部分数字,希望保留下来的数字组成的正整数最大。
输入描述:
输入为两行内容,第一行是正整数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!
再去测通过率!
.........
我...无话可说
求大佬救救孩子啊!!