数字与字符串间转换——12、273、165、481

12. 整数转罗马数字

七个不同的符号代表罗马数字,其值如下:

符号
I1
V5
X10
L50
C100
D500
M1000

罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:

  • 如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
  • 如果该值以 4 或 9 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 4 是 5 (V) 减 1 (I): IV ,9 是 10 (X) 减 1 (I):IX。仅使用以下减法形式:4 (IV),9 (IX),40 (XL),90 (XC),400 (CD) 和 900 (CM)。
  • 只有 10 的次方(IXCM)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式

给定一个整数,将其转换为罗马数字。

解法一、遍历求值,分情况讨论

就是根据4|9/1-3/5-8的情况讨论,0不必输出任何

感觉很赘余 不够清晰,但是足够简单

class Solution {
    public static String intToRoman(int num) {
        String s = String.valueOf(num);
        StringBuffer sb = new StringBuffer();
        for(int i = 0 ; i<s.length();i++){
            sb.append(getValue(s.charAt(i) - '0',s.length() - i - 1));
        }
        return sb.toString();
    }
    private static String getValue(int num,int n){
        StringBuffer sb = new StringBuffer();
        if(num == 4 || num == 9){
            switch (n){
                case 2:
                    if(num == 4){
                        return "CD";
                    }else{
                        return "CM";
                    }
                case 1:
                    if(num == 4){
                        return "XL";
                    }else{
                        return "XC";
                    }
                case 0:
                    if(num == 4){
                        return "IV";
                    }else{
                        return "IX";
                    }
            }
        }else if(num >= 5){
            switch (n){
                case 2:
                    sb.append("D");
                    for(int i = 5;i < num;i++){
                        sb.append("C");
                    }
                    break;
                case 1:
                    sb.append("L");
                    for(int i = 5;i < num;i++){
                        sb.append("X");
                    }
                    break;
                case 0:
                    sb.append("V");
                    for(int i = 5;i < num;i++){
                        sb.append("I");
                    }
                    break;
            }
        }else{//1-3
            switch (n){
                case 3:
                    for(int i = 0;i < num;i++){
                        sb.append("M");
                    }
                    break;
                case 2:
                    for(int i = 0;i < num;i++){
                        sb.append("C");
                    }
                    break;
                case 1:
                    for(int i = 0;i < num;i++){
                        sb.append("X");
                    }
                    break;
                case 0:
                    for(int i = 0;i < num;i++){
                        sb.append("I");
                    }
                    break;
            }
        }
        return sb.toString();
    }
}

解法二、模拟(贪心)

本质上是换了一个计算形式。对于一个数字num,就是取出一个不超过它且最大的固定值,相减,重复这个过程。如3769,减三次1000, 减500,减两次200,以此类推。

此外,这里的数组+字符串组以下标联系、担任一个类似键值对的功能,我觉得非常出色,既可以遍历,又可以查找,接近Hashmap。非常出色的思路和功能。。

class Solution {
    int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
    String[] symbols = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};

    public String intToRoman(int num) {
        StringBuffer roman = new StringBuffer();
        for (int i = 0; i < values.length; ++i) {
            int value = values[i];
            String symbol = symbols[i];
            while (num >= value) {
                num -= value;
                roman.append(symbol);
            }
            if (num == 0) {
                break;
            }
        }
        return roman.toString();
    }
}

作者:力扣官方题解
链接:https://leetcode.cn/problems/integer-to-roman/solutions/774611/zheng-shu-zhuan-luo-ma-shu-zi-by-leetcod-75rs/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解法三、硬编码

对于位上,每个数字是固定的,因为是有限位(数据0-3999)可以直接硬查。这里应该使用了表驱动的思想

class Solution {
    String[] thousands = {"", "M", "MM", "MMM"};
    String[] hundreds  = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
    String[] tens      = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
    String[] ones      = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};

    public String intToRoman(int num) {
        StringBuffer roman = new StringBuffer();
        roman.append(thousands[num / 1000]);
        roman.append(hundreds[num % 1000 / 100]);
        roman.append(tens[num % 100 / 10]);
        roman.append(ones[num % 10]);
        return roman.toString();
    }
}

作者:力扣官方题解
链接:https://leetcode.cn/problems/integer-to-roman/solutions/774611/zheng-shu-zhuan-luo-ma-shu-zi-by-leetcod-75rs/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 
273. 整数转换英文表示

将非负整数 num 转换为其对应的英文表示。

示例 1:

输入:num = 123
输出:"One Hundred Twenty Three"

示例 2:

输入:num = 12345
输出:"Twelve Thousand Three Hundred Forty Five"

示例 3:

输入:num = 1234567
输出:"One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven"

提示:

  • 0 <= num <= 231 - 1

解法一、模拟递归 

对于0-100的部分,放在最下层处理。这里分三个字符串组,分别是0-9的,10-19的,20-99的,是三种处理逻辑。对于大于100的部分,其实是100的拆分+Billion/Million/Thousand/Hundred

能过困难题很惊喜。。

class Solution {
    static String [] single = {"Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine"};
    static String [] between = {"Ten","Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen","Seventeen","Eighteen","Nineteen"};
    static String [] tens = {"","","Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety"};
    public static String numberToWords(int num) {
        StringBuffer sb = new StringBuffer();
        if(num >= 1000000000){
            sb.append(numberToWords(num /1000000000));
            sb.append(" Billion ");
            if(num % 1000000000 != 0){
                sb.append(numberToWords(num % 1000000000));
            }
        }else if(num >= 1000000){
            sb.append(numberToWords(num /1000000));
            sb.append(" Million ");
            if(num % 1000000 != 0){
                sb.append(numberToWords(num % 1000000));
            }
        }else if(num >= 1000){
            sb.append(numberToWords(num /1000));
            sb.append(" Thousand ");
            if(num % 1000 != 0){
                sb.append(numberToWords(num % 1000));
            }
        }else if(num >= 100){
            sb.append(numberToWords(num /100));
            sb.append(" Hundred ");
            if(num % 100 != 0){
                sb.append(numberToWords(num % 100));
            }
        }else{//小于100
            if(num >= 20){
                sb.append(tens[num/10]);
                num = num % 10;
                if(num != 0){
                    sb.append(" ");
                    sb.append(single[num]);
                }
            }else if(num >= 10){
                sb.append(between[num % 10]);
            }else{
                sb.append(single[num]);
            }
        }
        return sb.toString().trim();
    }
}

165. 比较版本号

给你两个 版本号字符串 version1 和 version2 ,请你比较它们。版本号由被点 '.' 分开的修订号组成。修订号的值 是它 转换为整数 并忽略前导零。

比较版本号时,请按 从左到右的顺序 依次比较它们的修订号。如果其中一个版本字符串的修订号较少,则将缺失的修订号视为 0

返回规则如下:

  • 如果 version1 version2 返回 -1
  • 如果 version1 version2 返回 1
  • 除此之外返回 0

示例 1:

输入:version1 = "1.2", version2 = "1.10"

输出:-1

解释:

version1 的第二个修订号为 "2",version2 的第二个修订号为 "10":2 < 10,所以 version1 < version2。

示例 2:

输入:version1 = "1.01", version2 = "1.001"

输出:0

解释:

忽略前导零,"01" 和 "001" 都代表相同的整数 "1"。

示例 3:

输入:version1 = "1.0", version2 = "1.0.0.0"

输出:0

解释:

version1 有更少的修订号,每个缺失的修订号按 "0" 处理。

提示:

  • 1 <= version1.length, version2.length <= 500
  • version1 和 version2 仅包含数字和 '.'
  • version1 和 version2 都是 有效版本号
  • version1 和 version2 的所有修订号都可以存储在 32 位整数 中

解法一、分解,转换,按位比较

split分解,max确保全遍历,在i位于双字符串区间段里进行比较,若一个字符串结束、另一个没有,单独比较是不是0,若都结束未分长短,return 0

class Solution {
    public int compareVersion(String version1, String version2) {
        String[] a = version1.split("\\.");
        String[] b = version2.split("\\.");
        int len1 = a.length;
        int len2 = b.length;
        int max = Math.max(len1,len2);
        for(int i = 0;i < max;i++){
            if(i < len1 && i < len2) {
                int num1 = Integer.parseInt(a[i]);
                int num2 = Integer.parseInt(b[i]);
                if (num1 > num2) return 1;
                if (num1 < num2) return -1;
            }else if(i >= len1){//2比较长
                if(Integer.parseInt(b[i])!=0)return -1;
            }else{//1比较长
                if(Integer.parseInt(a[i])!=0)return 1;
            }
        }
        return 0;
    }
}

 

解法二、双指针

class Solution {
    public int compareVersion(String version1, String version2) {
        int n = version1.length(), m = version2.length();
        int i = 0, j = 0;
        while (i < n || j < m) {
            int x = 0;
            for (; i < n && version1.charAt(i) != '.'; ++i) {
                x = x * 10 + version1.charAt(i) - '0';
            }
            ++i; // 跳过点号
            int y = 0;
            for (; j < m && version2.charAt(j) != '.'; ++j) {
                y = y * 10 + version2.charAt(j) - '0';
            }
            ++j; // 跳过点号
            if (x != y) {
                return x > y ? 1 : -1;
            }
        }
        return 0;
    }
}

作者:力扣官方题解
链接:https://leetcode.cn/problems/compare-version-numbers/solutions/970416/bi-jiao-ban-ben-hao-by-leetcode-solution-k6wi/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 
481. 神奇字符串

 

神奇字符串 s 仅由 '1' 和 '2' 组成,并需要遵守下面的规则:

  • 神奇字符串 s 的神奇之处在于,串联字符串中 '1' 和 '2' 的连续出现次数可以生成该字符串。

s 的前几个元素是 s = "1221121221221121122……" 。如果将 s 中连续的若干 1和 2 进行分组,可以得到 "1 22 11 2 1 22 1 22 11 2 11 22 ......" 。每组中 1 或者 2 的出现次数分别是 "1 2 2 1 1 2 1 2 2 1 2 2 ......" 。上面的出现次数正是 s 自身。

给你一个整数 n ,返回在神奇字符串 s 的前 n 个数字中 1 的数目。

示例 1:

输入:n = 6
输出:3
解释:神奇字符串 s 的前 6 个元素是 “122112”,它包含三个 1,因此返回 3 。 

示例 2:

输入:n = 1
输出:1

提示:

  • 1 <= n <= 105

解法一、迭代

 挺白痴的解法,因为实在想不到其他办法了。。先造出一个长度够长的串,再遍历它数1。

class Solution {
    public static int magicalString(int n) {
        String a = "12";
        while(a.length() < n){
            a = makeString(a);
        }
        int sum = 0;
        for(int i = 0;i < n;i++){
            if(a.charAt(i) == '1'){
                sum++;
            }
        }
        return sum;
    }
    private static String makeString(String s){
        StringBuffer sb = new StringBuffer();
        char c = '1';
        for(int i = 0;i < s.length();i++){
            sb.append(c);
            if(s.charAt(i) == '2')sb.append(c);
            c = c == '1' ? '2':'1';
        }
        return sb.toString();
    }
}

 

解法二、双指针

一边延长一边统计

class Solution {
    public int magicalString(int n) {
        if (n < 4) {
            return 1;
        }
        char[] s = new char[n];
        s[0] = '1';
        s[1] = '2';
        s[2] = '2';
        int res = 1;
        int i = 2;
        int j = 3;
        while (j < n) {
            int size = s[i] - '0';
            int num = 3 - (s[j - 1] - '0');
            while (size > 0 && j < n) {
                s[j] = (char) ('0' + num);
                if (num == 1) {
                    ++res;
                }
                ++j;
                --size;
            }
            ++i;
        }
        return res;
    }
}

作者:力扣官方题解
链接:https://leetcode.cn/problems/magical-string/solutions/1936845/shen-qi-zi-fu-chuan-by-leetcode-solution-y5dg/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 解法三、打表

这个就不写了,字符串是固定的 提前写出来也没问题


 碎碎念

  • 12的数组+字符串组相当于依靠下标联系起来的键值对,现在还是感觉很神奇。。也学会了提前设一个String[]方便查阅和使用(273)
  • 增加了if else理解和边界严谨性
  • 双指针在字符串转换问题里真的很好用。。
  • 虽然273性价比、难度很低,但是做出了困难题,还是很开心
  • 20
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值