• 算法试题:从一串数字中构造出能被15整除的最大整数


    上周末布置的算法试题:

    给定一行只包含数字的字符串(1到1000个数字),求使用字符串中的某些字符,构造一个能被15整除的最大整数,要求字符串中的每个字符最多只能使用一次。

    该试题需要考虑什么数能被3整除和被5整除,涉及排序,当不能被3整除时需要考虑如何舍去某些数字。

     

    我今天用C++编程实现了,估计应该能对。

     

    一、首先编写测试用例,每对值中给出待测试的数字串和预期的结果:

     

    bool AssertPair(const char* instr, const char* check);

    bool Test()
    {
        return AssertPair("0", "")
            && AssertPair("5", "")
            && AssertPair("1", "")
            && AssertPair("12", "")
            && AssertPair("50", "")
            && AssertPair("125", "15")
            && AssertPair("120", "210")
            && AssertPair("102", "210")
            && AssertPair("012", "210")
            && AssertPair("102", "210")
            && AssertPair("051", "510")
            && AssertPair("12310", "3210")
            && AssertPair("12320", "3210")
            && AssertPair("0223", "30")
            && AssertPair("123110", "31110")
            && AssertPair("123220", "32220");
    }

     

    二、编码实现代码:

     

    #include <iostream>
    #include <string>
    using namespace std;

    // 按从大到小顺序插入排序
    void Sort(char* buf)
    {
        for (int i = 0; buf[i]; i++)            // 对每一个输入的数字
        {
            for (int j = 0; j < i; j++)         // 按从大到小顺序插入
            {
                if (buf[i] > buf[j])            // 将 buf[i] 插入到 j 位置
                {
                    char c = buf[i];
                    for (int k = i; k > j; k--)
                    {
                        buf[k] = buf[k - 1];
                    }
                    buf[j] = c;
                    break;
                }
            }
        }
    }

    // 找到5,放到末尾
    bool Move5ToEnd(string& str)
    {
        size_t pos = str.find('5');

        if (pos == string::npos)
        {
            return false;
        }
        str += str[pos];
        str.erase(pos, 1);

        return true;
    }

    // 从倒数第二个开始往前找一个数字移除,该数字除以3的余数为指定数
    bool RemoveOneChar(string& str, int rem)
    {
        for (int i = (int)str.size() - 2; i >= 0; i--)
        {
            if ((str[i] - '0') % 3 == rem)
            {
                str.erase(i, 1);
                return str != "0";
            }
        }

        return false;
    }

    // 从倒数第二个开始往前找两个数字移除,该数字之和除以3的余数为指定数
    bool RemoveTwoChars(string& str, int rem)
    {
        for (int i = (int)str.size() - 2; i >= 0; i--)
        {
            for (int j = i - 1; j >= 0; j--)
            {
                if ((str[i] - '0' + str[j] - '0') % 3 == rem)
                {
                    str.erase(i, 1);
                    str.erase(j, 1);
                    return str != "0";
                }
            }
        }

        return false;
    }

    // 将一行中各个数字组成能被15整除的最大整数
    bool GetMaxInt(string& str)
    {
        // 去掉不是数字的字符
        for (int t = (int)str.size() - 1; t >= 0; t--)
        {
            if (!isdigit(str[t]))
            {
                str.erase(t, 1);
            }
        }

        // 从大到小排序
        Sort(&str[0]);

        // 如果末位不是0,则找到5,放到末尾,这样就能被5整除
        if (*str.rbegin() != '0' && !Move5ToEnd(str))
        {
            return false;
        }

        // 求所有数字之和
        int sum = 0;
        for (size_t i = 0; i < str.size(); i++)
        {
            sum += str[i] - '0';
        }

        // 根据除以3的余数,从倒数第二个开始往前找数字移除
        return sum > 0 &&                       // 0不能被整除
            (sum % 3 == 0                       // 正好被3整除
            || RemoveOneChar(str, sum % 3)      // 移除一个数字,该数字除3余指定数
            || RemoveTwoChars(str, sum % 3));   // 移除两个数字,其和除3余指定数
    }

    int main()
    {
        printf(Test() ? "Test OK.\n" : "Test fail.\n");
        string str;

        cout << "请输入多行数字,将输出每行中各数字组成的能被15整除的最大整数。\n";

        for (;;)
        {
            cin >> str;
            if (str.empty() || str[0] == 'q')
            {
                break;
            }

            if (GetMaxInt(str))
            {
                printf("%s\n\n", str.c_str());
            }
            else
            {
                printf("Imporssible.\n\n");
            }
        }

        return 0;
    }

    bool AssertPair(const char* instr, const char* check)
    {
        string str(instr);
        bool ret = GetMaxInt(str)
            ? strcmp(check, str.c_str()) == 0
            : strcmp(check, "") == 0;

        printf("%s\tinput: %s\toutput: %s\tcheck: %s\n",
            ret ? "OK." : "Fail.",
            instr, str.c_str(),
            *check ? check : "Imporssible");

        return ret;
    }

  • 相关阅读:
    System.Runtime.InteropServices.COMException (0x800706BA) 解决方法
    Win7 不能安装 msi 解决办法
    note 1 对象和数据类型
    note 0 Python介绍及Python IDE环境安装 Spyder with Anaconda
    无法获得锁 /var/lib/dpkg/lock
    keil5 MDK 链接报错 Error: L6410W 解决
    手动卸载CAD 删除残留文件 清理遗留的文件
    keil5 MDK warning:registered ARM compiler version not found in path
    干掉hao123劫持浏览器主页
    Win7 无法访问Installer服务
  • 原文地址:https://www.cnblogs.com/rhcad/p/1982441.html
Copyright © 2020-2023  润新知