LeetCode 第二天 9.回文数 &13.罗马数字转整数

LeetCode百日筑基系列主要是为了练习基础的数据结构与算法,题库全为LeetCode简单题(后面会在其他系列更新中等题和困难题),主要使用C语言和Java编写,前期的题目以完成功能为目的,后续会使用更优的算法以及优化代码块。

9.回文数
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-number
C语言:

bool isPalindrome(int x){
    unsigned int  i = 0,j = x;
    if(x < 0){
        return false;
    }
    while (x != 0){
        i = i * 10 + x % 10;
        x = x / 10;
    }
        return i == j;
}

主体思路:首先负数一定不是回文数,-121首位为-,不可能与1相等。设置一个变量i存储最后的回文数,设置一个变量j存储最初的输入x。由于i*10的过程中可能超出int的范围,所以可以用unsigned(回文不为负)或long类型。
进行数字反转:对于数字 12321,如果执行 12321 % 10,将得到最后一位数字 1,再除以 10 把最后一位数字从 12321 中移除,12321 / 10 = 1232,再求出上一步结果除以 10 的余数,1232 % 10 = 2,就可以得到倒数第二位数字。如果我们把最后一位数字乘以 10,再加上倒数第二位数字,1 * 10 + 2 = 12,就得到了我们想要的反转后的数字。
最后将得到的反转后的数字与最初输入数字比较。
Java:

class Solution {
    public boolean isPalindrome(int x) {
        if(x < 0 || (x % 10 == 0 && x != 0)){
            return false;
        }
        int i = 0;
        while(x > i){
            i = i * 10 + x % 10;
            x /= 10;
        }
        return x == i || x == i / 10;
    }
}

新思路:在上述数字反转基础上加以优化,当 x < 0 时,x 不是回文数。同样的,如果数字的最后一位是 0,它也不是回文数,如10 数字反转后为01。当然0除外。
上面C的代码将所有数字都反转,但回文数前半部分数字和后半部分的反转数字应是相同的,所以只需反转一半数字即可。
反转一半数字:
奇数个数字如12321,反转三位才过半,i为123,x为12(奇数个数字中间的数不影响判断是否回文)
偶数个数字如1221,反转两位就过半,此时i为12,x为12
所以当x<=i即可停止反转下一位数字。
最后输出时,奇数个数字,判断i/10==x, 偶数个数字判断i == x。
由于判断时前面的成立即可立即输出结果,建议使用||短路运算。
复杂度分析
时间复杂度:O(log n),对于每次迭代,我们会将输入除以 10,因此时间复杂度为 O(\log n)。
空间复杂度:O(1)。我们只需要常数空间存放若干变量。


13.罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/roman-to-integer
C语言

int romanToInt(char * s){
    int num = 0;
    while(*s){
        if(*s == 'V'){ 
            num += 5;
        }else if(*s == 'L'){ 
            num += 50;
        }else if(*s == 'D'){ 
            num += 500;
        }else if(*s == 'M'){ 
            num += 1000;
        }else if(*s == 'I'){
            num = (*(s+1) == 'X' || *(s+1) == 'V') ? (num - 1) : (num + 1);
        } else if(*s == 'X'){
            num = (*(s+1) == 'L' || *(s+1) == 'C') ? (num - 10) : (num + 10); 
        }else if (*s == 'C'){
            num = (*(s+1) == 'D' || *(s+1) == 'M') ? (num - 100) : (num + 100); 
        }
        s++;
     }
     return num;
}

当小值在大值的左边,则减小值,如 IV=5-1=4;当小值在大值的右边,则加小值,如 VI=5+1=6;

Java

class Solution {
    public int romanToInt(String s) {
        int sum = 0;
        int leftNum = getNum(s.charAt(0));   //左边第一位数
        for(int i = 1; i < s.length(); i++){   // 循环s里的所有数
            int num = getNum(s.charAt(i));   //找到右边下一位的值
            if(leftNum < num){              //若左边的值小于右边的值,减去左边的数
                sum = sum - leftNum;
            }else{                           //若左边的值大于或等于右边的值,加上左边的值
                sum = sum + leftNum;
            }
            leftNum = num;        //将最后一个数通过leftNum传出
        }
        return sum = sum + leftNum;
    }
    public int getNum(char ch){
        switch(ch){
            case'I' : return 1;
            case'V' : return 5;
            case'X' : return 10;
            case'L' : return 50;
            case'C' : return 100;
            case'D' : return 500;
            case'M' : return 1000;
            default : return 0;
        } 
    }
}

java.lang.String.charAt() 方法返回指定索引处的char值。索引范围是从0到length() - 1。对于数组索引,序列的第一个char值是在索引为0
例如:str.charAt(0)检索str中的第一个字符,str.charAt(str.length()-1)检索最后一个字符

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rpk712

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值