12. 整数转罗马数字

题目

image-20240914135318729

题解

这道题目难点在堆三个条件的理解上,其余的就是常规的将一个int数按照位数拆开后对照

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {

//罗马数对照表
static constexpr string R[4][10] = {
{"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}, // 个位
{"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}, // 十位
{"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}, // 百位
{"", "M", "MM", "MMM"}, // 千位
};

public:
//常规按位拆分再对比
string intToRoman(int num) {
return R[3][num / 1000] + R[2][num / 100 % 10] + R[1][num / 10 % 10] + R[0][num % 10];
}
};

constexpr对比const

constexprconst 在 C++ 中都用于定义不可变的变量,但它们之间有几个关键的区别:

  1. 编译时常量与运行时常量

    • constexpr:指定的变量或函数在编译时就必须确定其值。这意味着,编译器可以在编译阶段就使用这个值进行优化和替换。constexpr 变量可以用于需要编译时常量的场合,比如模板参数或数组大小。
    • const:指定的变量在程序运行期间不可改变,但其值可以在运行时确定。const 变量通常用于确保数据在程序的生命周期内不被意外修改。
  2. 使用场景

    • constexpr:更适用于那些可以在编译时计算出结果的表达式,以及需要编译时常量的场合。
    • const:更通用,可以用于任何不希望被修改的变量,无论其值是在编译时还是运行时确定的。
  3. 类型要求

    • constexpr:只能用于字面量类型(如整型、浮点型、枚举等)或者具有constexpr构造函数的用户定义类型。
    • const:可以用于任何类型。
  4. 函数支持

    • constexpr:可以用于修饰函数,表示该函数在给定常量表达式作为参数时,会返回一个常量表达式。这使得函数可以在编译时被求值。
    • const:不能用于修饰函数,但可以用于函数参数和返回类型,表示参数或返回值在函数内部不可修改。
  5. 内存分配

    • 对于全局或静态存储持续时间的变量,constconstexpr 都可能导致编译器在程序的只读存储区分配内存。然而,对于局部变量,constexpr 变量可能根本不需要分配内存,因为编译器可以直接在其出现的地方使用它的值。
  6. 动态初始化

    • const 变量可以在运行时进行动态初始化。
    • constexpr 变量必须在编译时初始化,且其初始化表达式必须是常量表达式。
  7. 线程安全

    • 由于 constexpr 变量在编译时就已经确定其值,并且在多个线程之间共享时不需要同步,因此它们是线程安全的(假设编译器和链接器正确地处理了它们)。
    • const 变量如果是全局或静态的,并且在运行时初始化,那么在多线程环境中可能需要同步来确保线程安全。

综上所述,constexprconst 虽然都用于定义不可变的变量,但它们在编译时与运行时的行为、使用场景以及类型要求等方面存在显著差异。在可能的情况下,优先使用 constexpr 可以带来更好的编译时优化和运行时性能。