• C/C++语言算法题——替换


    【问题】

    Description

    给定一个有限长度的非负整数序列。一次操作是指从第一个元素开始,依次把数列中的每个数替换为它右边比它小的数的个数。对该数列不断进行这个操作。总有一个时刻该数列将不再发生改变(即此时每个数都恰好等于它右边比它小的数的个数)。例如给定数列:
    5, 44, 19, 6, 49, 1, 27, 19, 50, 20
    连续进行五次操作后,依次得到新数列如下:

    1, 6, 2, 1, 4, 0, 2, 0, 1, 0
    3, 8, 5, 3, 5, 0, 3, 0, 1, 0
    4, 8, 6, 4, 5, 0, 3, 0, 1, 0
    5, 8, 7, 5, 5, 0, 3, 0, 1, 0
    5, 8, 7, 5, 5, 0, 3, 0, 1, 0

    其中,第四次操作后,数列不再发生改变。
    对给定数列,循环执行上述操作,直到其不再改变为止,输出最后得到的数列。

    Input

    第1行:一个整数T(1≤T≤10)为问题数。
    对于每组测试数据:
    第1行是一个正整数:数列长度N ( 2 < N≤30 );
    第2行有N个正整数:分别为该数列第1至第N个元素的值a1,a2,…,aN( a1,a2,…, aN均为1 - 1000的数),每两个整数之间用一个空格分开。

    Output

    对于每个问题,输出一行问题的编号(0开始编号,格式:case #0: 等)。
    然后在一行中依次输出最后数列的所有元素,每两个元素之间用一个空格分开,最后一个元素后面没有空格。

    Sample Input

    3
    10
    5 44 19 6 49 1 27 19 50 20
    10
    3 2 7 10 9 8 8 5 1 5
    10
    12 12 19 19 7 10 9 6 18 9

    Sample Output

    case #0:
    5 8 7 5 5 0 3 0 1 0
    case #1:
    9 2 3 6 5 3 3 2 0 0
    case #2:
    6 6 6 6 3 4 3 0 1 0

    【解题报告】

    算法本身很容易实现,但是问题是我不清楚应当如何判断算法何时结束,也就是如何判断“两次变换所得到的新数组相等”。如果有更好的算法请不吝赐教。

      1 #include <iostream>
      2 using namespace std;
      3 #define TRUE 1
      4 #define FALSE 0
      5 
      6 int isSame(const int*, const int*, const int);
      7 void setArray(int*, int);
      8 void outputArray(const int*, const int);
      9 void process(int*, int);
     10 int* clone(const int*, int);
     11 
     12 int main()
     13 {
     14     int T;
     15     cin>>T;
     16     for(int c = 0; c < T; c++)
     17     {
     18         int N;
     19         cin>>N;
     20         int* arr = new int[N];
     21         setArray(arr,N);
     22         for(;;)                            /* 这里我实在想不出该如何简便地判断参加变换的数组是否发生变化,因此 */
     23         {                                /* 只能通过备份前一次变换的结果和当次运算结果作比较 */
     24             int* temp = clone(arr,N);   
     25             process(arr,N);                /* 虽然能够AC,但是这肯定不是最优的算法 */
     26             if(isSame(arr,temp,N))      /* 因此如有更好的,时间复杂度更低的算法还望不吝赐教奥 */
     27             {
     28                 delete[] temp;
     29                 break;
     30             }
     31         }
     32         cout<<"case #"<<c<<":"<<endl;
     33         outputArray(arr,N);
     34         delete[] arr;
     35     }
     36     return 0;
     37 }
     38 
     39 /** 判断两个同等长度的数组是否相等
     40   @param arr1 数组1
     41   @param arr2 数组2
     42   @param N 数组1和2的长度
     43   @returns 相等返回1,否则返回0
     44 */
     45 int isSame(const int* arr1, const int* arr2, const int N)
     46 {
     47     for(int i = 0; i < N; i++)
     48     {
     49         if(arr1[i] != arr2[i])
     50             return FALSE;
     51     }
     52     return TRUE;
     53 }
     54 
     55 /**
     56  通过标准输入设置数组的各元素
     57  @param arr 待填充的数组
     58  @param n   数组长度
     59 */
     60 void setArray(int* arr, int n)
     61 {
     62     int t;
     63     for(int i = 0; i < n; i++)
     64     {
     65         cin>>t;
     66         arr[i] = t;
     67     }
     68 }
     69 
     70 /**
     71   输出数组
     72   @param arr 要输出的数组
     73   @param N 数组长度
     74 */
     75 void outputArray(const int* arr, const int N)
     76 {
     77     for(int i = 0; i < N; i++)
     78     {
     79         cout<<arr[i];
     80         if(i != N-1) cout<<' ';
     81         else cout<<'
    ';
     82     }
     83 }
     84 
     85 /**
     86   处理算法
     87   循环处理每一个元素,将其修改为它后面比它小的元素的个数
     88   @param arr 要处理的数组
     89   @param N 数组长度
     90 */
     91 void process(int* arr, int N)
     92 {
     93     for(int i = 0; i < N; i++)
     94     {
     95         int count = 0;
     96         for(int j = i+1; j < N; j++)
     97         {
     98             if(arr[j] < arr[i])
     99                 count++;
    100         }
    101         arr[i] = count;
    102     }
    103 }
    104 
    105 /**
    106   克隆数组,将一个数组克隆为另一个数组,
    107   使得两个数组中的各元素相同,但他们的首指针不同。
    108   @param arr 待克隆的源数组
    109   @param N   数组长度
    110   @returns   克隆出的新数组
    111 */
    112 int* clone(const int* arr, int N)
    113 {
    114     int* temp = new int[N];
    115     for(int i = 0; i < N; i++)
    116     {
    117         temp[i] = arr[i];
    118     }
    119     return temp;
    120 }解题代码
    解题代码

    【优化】

    根据hoodlum1980的建议。将process函数改为

    bool process(int* arr, int N)
    {
        bool changed = false;
        for(int i = 0; i < N; i++)
        {
            int count = 0;
            for(int j = i+1; j < N; j++)
            {
                if(arr[j] < arr[i])
                    count++;
            }
            if(arr[i] != count)
            {
                arr[i] = count;
                changed = true;
            }
        }
        return changed;
    }

    主函数相应部分改为

    while(process(arr,N));

    出处:http://acm.cs.ecnu.edu.cn/problem.php?problemid=2993

  • 相关阅读:
    Ubuntu14.0.4 64位 ADT 连接手机调试问题
    Ubuntu14.0.4 64位安装ADT问题
    Uubntu scrot 的简单使用
    Ubuntu14.0.4 64位安装Chrome浏览器
    Android DatePickerDialog 只选择年月
    Java 正则提取数字串
    客户端HttpClient处理 Servlet Gzip
    Ext常用Tool
    python使用 requirements.txt 管理所需的包
    PyQt5安装及ModuleNotFoundError: No module named 'PyQt5'问题解决
  • 原文地址:https://www.cnblogs.com/ryuasuka/p/3514632.html
Copyright © 2020-2023  润新知