nc112. 进制转换

题意

给你一个十进制数,求他的进制数对应的字符串。

1. 递归做法

首先看一下进制的定义:N进制就是逢N进一。
任何一个N进制数M都可以表示为如下形式:

其中,就是, 求出a0之后,我们可以继续对上式变形:

再套用上面的逻辑,对左边的数再对N取模即可得到. 以此类推可以设计递归解法,设原问题为f(M, N), 则有:

, 其中=M % N.

class Solution {
public:
    string F(int M, int N, int dep = 1) {
        // 本题数据略弱,没有考虑M为0的情况,如果不加辅助参数depth也能AC
        // 但是这里要特判一下,如果是第一层传进来就为0,那要返回0
        // 如果是递归过程中遇到了终点,要返回空字符串,否则答案中会出现前导0
        if (!M) return dep == 1 ? "0" : "";

        // 负数转化为正数
        if (M < 0) return "-" + F(-M, N);
        int a0 = M % N;
        string s0 = to_string(a0);
        if (a0 > 10) {
            s0 = 'A' + a0 - 10;
        }
        return F((M - a0) / N, N, dep+1) + s0;

    }
    string solve(int M, int N) {
        return F(M, N); // 默认为第一层,据上述公式实现
    }
};
  • 时间复杂度:, 因为每次不断把M除以N,总的复杂度是对数级别。
  • 空间复杂度:, 算法递归次,每次常数级别空间。

2. 非递归做法

非递归做法就是模拟我们小学奥数课的手算方法:(以4567转16进制为例,实际上也是上面的数学公式不断迭代求N的幂的系数的过程):

图片说明

因此,

用代码模拟上述过程即可。

class Solution {
public:
    /**
     * 进制转换
     * @param M int整型 给定整数
     * @param N int整型 转换到的进制
     * @return string字符串
     */
    string solve(int M, int N) {
        // 特判,本题没有的数据,但是要更加严谨
        if (!M) return "0";

        // 负数转化为正数
        if (M < 0) return "-" + solve(-M, N);
        string res;
        // 迭代出口为M=0
        while(M) {
            int a = M%N; // 求余数
            string s = to_string(a);
            if (a > 10) {
                s = 'A' + a - 10;
            }
            // 向前拼接
            res = s + res;
            // 求商,进行下一轮迭代
            M /= N;
        }
        return res;
    }
};
  • 时间复杂度:, 因为每次不断把M除以N,总的复杂度是对数级别。
  • 空间复杂度:, 变量res的长度是M的对数级别。