问题:输入高精度正整数 n ,去掉其中任意 s 个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的 n 和 s,寻找一种方案使得剩下的数字组成的新数最小。输出去掉数字的位置和新的正整数。
贪婪原理:位数固定时,高位越小则值越小,尽可能删除较大的高位数字。
删除原则:将相邻两位比较,若高位比低位大,则删除高位。
被删除数的原位置= 它在新数中的位置 + 它向前移动的次数
删除字符(物理删除):
n |
n[1] |
n[2] |
n[3] |
n[4] |
n[5] |
n[6] |
n[7] |
n[8] |
n[9] |
n |
1 |
2 |
4 |
3 |
5 |
8 |
6 |
3 |
\0 |
n' |
1 |
2 |
3 |
5 |
8 |
6 |
3 |
\0 |
|
n'' |
1 |
2 |
3 |
5 |
6 |
3 |
\0 |
|
|
n''' |
1 |
2 |
3 |
5 |
3 |
\0 |
|
|
|
delete(char n[ ], int b, int k) { for (int i=b; i<=length(n)-k; i++) n[i]=n[i+k]; }
若删除位数不够s位
n |
n[1] |
n[2] |
n[3] |
n[4] |
n[5] |
n[6] |
n[7] |
n[8] |
n |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
\0 |
n' |
1 |
2 |
3 |
4 |
5 |
6 |
\0 |
|
n'' |
1 |
2 |
3 |
4 |
5 |
\0 |
|
|
n''' |
1 |
2 |
3 |
4 |
\0 |
|
|
|
for (i=count+1; i <=s; i++) { j=len-i; Delete(n, j, 1); } //count 记录已经被删掉的数字个数
删除s(如s=3)位数字后, 若高位存在0,怎么做?
n |
n[1] |
n[2] |
n[3] |
n[4] |
n[5] |
n[6] |
n[7] |
n |
1 |
2 |
0 |
0 |
8 |
3 |
\0 |
n' |
1 |
0 |
0 |
8 |
3 |
\0 |
|
n'' |
0 |
0 |
8 |
3 |
\0 |
|
|
n''' |
0 |
0 |
3 |
\0 |
|
|
|
n''' |
0 |
3 |
\0 |
|
|
|
|
n''' |
3 |
\0 |
|
|
|
|
|
while(n[0]=='0'&&strlen(n)>1) Delete(n, 0, 1);
int m[100]={0};
void Delete(char n[], int b, int k) //删除字符操作
{ int i;
for (i=b; i<=strlen(n)-k; i++)
{ n[i]=n[i+k]; m[i]=m[i+1]+1; } //数组m[i]中的值向前移动的位数
}
int main()
{ char n[100]; //数组n存储整数n
int s, i, j, j1=0, count=0, data[100], len; //数组data存储被删除数的原始位置
printf("Please input an integer: ");
gets(n);
len=strlen(n);
printf("Please input an integer s: ");
scanf("%d", &s);
if (s>len) { printf("data error!\n"); return -1; }
for (i =1; i <=s; i++) //删除操作
{ for (j = 0; j <strlen(n)-1; j++)
if(n[j]>n[j+1]) { count++; data[i-1]=j+m[j]; Delete(n, j, 1); break; } if (j>strlen(n)-1) break; }
for (i=count+1; i <=s; i++) { j=len-i; data[i-1]=j+m[j]; Delete(n, j, 1); } //删除不足s位的情况
while(n[0]=='0'&&strlen(n)>1) Delete(n, 0, 1); //删除后,最高位为零的情况
printf("\n**** Output the new integer: ");
puts(n);
}
方法二
void Delete(char n[], int b, int k)
{ int i;
for (i=b; i<=strlen(n)-k; i++)
n[i]=n[i+k];
}
int main()
{
char n[100];
int s, i, j, j1=0, count=0, data[100], len;
printf("Please input an integer: ");
gets(n);
len=strlen(n);
printf("Please input an integer s: ");
scanf("%d", &s);
if (s>len)
{ printf("data error!\n");
return -1;
}
for (i =1; i <=s; i++)
{ for (j = 0; j <strlen(n)-1; j++)
if(n[j]>n[j+1])
{ count++;
Delete(n, j, 1);
data[i-1]=j;
break;
}
if (j>strlen(n)-1)
break;
}
for (i=count+1; i <=s; i++)
{
j=len-i;
Delete(n, j, 1);
data[i-1]=j;
}
for (i=s-1; i>=0; i--) //恢复删除数在上一次删除时在数组中的位置 //与方法一不同的地方,节省空间(借鉴他人想法)
for (j=s-1; j>i; j--)//
if(data[i]<=data[j])
data[j]=data[j]+1;
printf("\n%^&* %d\n", strlen(n));
puts(n);
while(n[0]=='0'&&strlen(n)>1)
Delete(n, 0, 1);
printf("\n**** Output the new integer: ");
puts(n);
for (i=1; i<=s; i++)
printf("data[%d]=%d ", i-1, data[i-1]);
return 0;
}