zoukankan      html  css  js  c++  java
  • 高精度整数去位取最小问题

    Description

    键盘输入一个高精度的正整数N,去掉其中任意M个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的N和M寻找一种方案使得剩下的数字组成的新数最小。输出组成的新的正整数。(不超过240位) 

    输入数据均不需判错。 

    如果去掉了某几个位后得到的新整数开头为0,保留0。

    Input

     

    本题有多组测试数据,每组测试数据占一行。 

    一个高精度正整数N(N不超过240位)一个正整数M。(M为不大于N的长度的正整数) 

    N,M由一个空格分开。

    Output

     

    新的正整数,每组数据的输出占一行。不要多余的空白.

    Sample Input

     

    456547 1 456547 2 456547 3 7773359 2 103 1

     Sample Output

     45547 4547 447 73359 03

    本题可以贪心算法快速解决。

    数据结构设计: 对于高精度整数,可以将其存储为字符串格式。

    问题分析: 在位数固定前提下,让高位的数字尽量小。其值就较小。依据贪心策略可以解决这个问题。

    如何根据贪心来删除数字呢?总目标是删除高位较大的数字,具体地相邻两位比较,若高位比地位大则删除高位.

    但是看下面的特殊情况:

    n3="1 2 3 4 5 6 7" s=3

    经过对n3相邻位进行比较,一个数字也没删除,这就要将后3位删除。当然还有可以在相邻比较的过程中删除的位数小于s,也要进行相似的操作。

    算法设计:

      根据以上分析,算法注意由4部分组成:初始化,相邻数字比较(必要时删除),处理比较过程中删除位数不够s位情况和结果输出。

    其中删除字符的实现方法很多:如

    1.物理的进行字符删除,就是用后面的字符覆盖已删除的字符,字符串的长度改变,这样可能会有较多的字符移动操作,算法效率不高。

    2.可以利用数字记录字符的存在状态,元素值为“1”表示对应的数值存在,0表示不存在。 但这样做前后数字的比较过程和最后的输出过程相对复杂些。

    3,利用一个数组,来记录为删除字符的下标。删除值时对应数组的下标删除。

     

     

    用C++的string类型很简单。代码如下:

     

    #include<iostream>
    #include<string>
    using namespace std;
    
    string greedy(string &str,int n)
    {
         bool del;
         
         for(int i=n;i>0;i--) //这里为什么从n范围是从n到1,而不是从1到n,是为后面代码简化.
         {
             del=false;
             for(string::iterator it=str.begin();it!=str.end()-1;it++)
             {
                 if(*it>*(it+1))
                 {
                     str.erase(it);
                     del=true;
                     break; //为什么要跳出
                 }
    
             }//end for
             //如果所有数字递增,则删除最后几个数字直接返回
    
                  if(!del)
             {
                 str.erase(str.end()-i,str.end());
                 break;
            
             }
             
         }
             
         return str;
    }
    int main()
    {
        string str;
        int n;
        cin>>str;
        cin>>n;
        cout<<greedy(str,n)<<endl;
        return 0;
    }
             

     以1 2 4 3 为例,S=3;

    最开始i=3; 进入里面的for循环后删除了4,退出for,变成了123

     i=2; del=false;for循环没有元素删除,!del为真,表示此时是按照从小到大排列的,从后面删除i个元素.2 ,3变成1.

    结果为1.

     

    删除数组中第i个字符:

    /*删除数组a【】的第k个字符  数组名不能用delete,c++的关键字*/

    void
    del(char *a,int k) { while(a[k]!='\0') { a[k]=a[k+1]; k++; } } /*删除数组a【】从b起的k个字符 */ void del(char *a,int b,int k) { int i; for(i=b;i<=strlen(a)-k;i++) a[i]=a[i+k]; }

     较简单的c算法:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    void find()
    {
        char N[200];
        int s;
        int i=0,j;
        printf("input the number:");
        scanf("%s",N);
        printf("\ninput times:");
        scanf("%d",&s);
        while(s>0) /*循环减s次*/
        {
    
          i=0;/*每次删除后重头开始*/
          while(i<strlen(N) && N[i]<=N[i+1])
    i++;/*算法核心*/ for(j=i;j<strlen(N);j++)N[j]=N[j+1];/*移位将删除的覆盖*/ s--; } printf("%s",N); } int main() { find(); system("pause"); }

     参考这里

     

     

  • 相关阅读:
    读书思维导图
    19/12/19 最近计划
    搭建自己的终极框架
    Win10下安装erl和RabbitMQ踩坑【版本不兼容】
    这里的博客不再更新了,有兴趣的可以转移到我的新博客地址 https://spacesec.github.io/
    最新最全的sqlmap命令中文详解以及插件功能详解[最全]
    Listary:放弃笨拙且丑陋的文件查找系统吧
    自己写一个破解zip加密文件的脚本
    分享一下第一次和别人开发项目的心得
    如何进行git 的push操作
  • 原文地址:https://www.cnblogs.com/youxin/p/2445513.html
Copyright © 2011-2022 走看看