删数问题

探讨了如何通过删除指定数量的数字来构建一个给定高精度正整数的最小可能值,采用贪婪策略和详细步骤说明,包括处理高位零的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:输入高精度正整数 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值