LeetCode 273. 整数转换英文表示 / 29. 两数相除 / 412. Fizz Buzz

273. 整数转换英文表示

2021.10.11 每日一题

题目描述

将非负整数 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”

示例 4:

输入:num = 1234567891
输出:“One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety One”

提示:

0 <= num <= 2^31 - 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/integer-to-english-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

其实就是一个模拟
需要知道英文数字的这些表示怎么写
因为英文数字表示是三位一组的,所以这里三位三位的进行处理
另外,英文的表示中没有几百零几这种说法,直接拼接就行了,这样方便很多
还有就是英文中十几有特殊的写法,所以每次判断三位中的中间位的时候需要判断是否为1,如果是1需要特殊处理
然后注意从高位到低位就行处理
最后将多余的空格去掉

class Solution {
    static String[] level = {"", "Thousand", "Million", "Billion"};
    static String[] single = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
    static String[] teen = {"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
    static String[] ten = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};

    public String numberToWords(int num) {
        //有点烦
        //想想,首先是三个一组,如果是十几的话就有直接对应的表示形式,而且还得是三个一组的后两位
        //其他的话都是0 2 3 ... 都是直接用几十的这种形式表示
        //现在的问题是,用map存这些数字对应的英文吗
        if(num == 0)
            return "Zero";
        int idx = 3;
        StringBuilder sb = new StringBuilder();
        for(int i = (int)1e9; i >= 1; i /= 1000){
            //当前三位数
            int temp = num / i;
            num = num % i;

            //当前三位数
            int ge = temp % 10;
            temp /= 10;
            int shi = temp % 10;
            temp /= 10;
            int bai = temp % 10;
            //如果三个数都是0,那么不用跳过
            if(ge == 0 && shi == 0 && bai == 0){
                idx--;
                continue;
            }
                
            //然后处理百位,十位,个位,百位正常处理
            if(bai != 0){
                sb.append(single[bai] + " " + "Hundred" + " ");
            }
            //十位需要判断是否为1
            if(shi != 0){
                if(shi > 1){
                    sb.append(ten[shi] + " ");
                }
                else if(shi == 1){
                    sb.append(teen[ge] + " ");
                }
            }
            //个位
            if(ge != 0 && shi != 1){
                sb.append(single[ge] + " ");
            }
            if(idx != 0)
                sb.append(level[idx] + " ");
            idx--;
        }

        return sb.toString().trim();
    }
}

29. 两数相除

2021.10.12 每日一题

题目描述

给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。

返回被除数 dividend 除以除数 divisor 得到的商。

整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2

示例 1:

输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = truncate(3.33333…) = truncate(3) = 3

示例 2:

输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = truncate(-2.33333…) = -2

提示:

被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−2^31, 2^31 − 1]。本题中,如果除法结果溢出,则返回 2^31 − 1。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/divide-two-integers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

思路就是二分找第一个商和除数的乘积小于被除数的商,然后乘法用位运算来表示
本身题不难,难的是处理整数的范围
首先,因为负数范围比正数要大,所以先都变成负数,方便处理
其次,因为二分查找的left和right是正数,所以不能处理结果为最小值的情况,所以做特殊处理
如果除数为最小值,也不能处理
因为采用的是left < right 的二分,所以商为0的情况,需要特殊处理,也就是被除数大于除数的情况

另外,在做乘法的过程中,采用的是快速幂
但是有可能乘积或者乘数可能溢出,所以需要特殊处理,溢出就返回0

class Solution {
    public int divide(int dividend, int divisor) {
        if(dividend == Integer.MIN_VALUE && divisor == -1)
            return Integer.MAX_VALUE;
        if(dividend == Integer.MIN_VALUE && divisor == 1)
            return dividend;
        //如果除数为最小值
        if(divisor == Integer.MIN_VALUE)
            return dividend == Integer.MIN_VALUE ? 1 : 0;

        //首先处理正负数
        //因为负数范围大,所以先都变成负数
        boolean isfu = false;
        if((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)){
            isfu = true;
        }
        if(dividend > 0)
            dividend = -dividend;
        if(divisor > 0)
            divisor = -divisor;
        
        if(dividend > divisor)
            return 0;
        //然后就是二分找点了
        int left = 1;
        int right = dividend == Integer.MIN_VALUE ? Integer.MAX_VALUE : -dividend;
        while(left < right){
            int mid = ((right - left + 1) >> 1) + left;
            int res = mutiply(divisor, mid);
            //如果res越界了,说明太大了
            if(res == 0 || res < dividend)
                right = mid - 1;
            else
                left = mid;
        }
        return isfu ? -left : left;
    }

    public int mutiply(int a, int b){
        int res = 0;
        while(b != 0){
            //如果当前位为1,那么加当前位
            if((b & 1) == 1){
                //如果溢出了,那么就返回0
                if(Integer.MIN_VALUE - res > a)
                    return 0;
                res += a;
            }
            //如果基数溢出了,那么也返回0
            if(Integer.MIN_VALUE - a > a && b != 1)
                return 0;
            b >>= 1;
            a += a;
        }
        return res;
    }
}

看到的另一个思路,就是先将除数的倍数放在一个集合中,然后看哪些位是1

class Solution {
    public int divide(int dividend, int divisor) {
        // 考虑被除数为最小值的情况
        if (dividend == Integer.MIN_VALUE) {
            if (divisor == 1) {
                return Integer.MIN_VALUE;
            }
            if (divisor == -1) {
                return Integer.MAX_VALUE;
            }
        }
        // 考虑除数为最小值的情况
        if (divisor == Integer.MIN_VALUE) {
            return dividend == Integer.MIN_VALUE ? 1 : 0;
        }
        // 考虑被除数为 0 的情况
        if (dividend == 0) {
            return 0;
        }
        
        // 一般情况,使用类二分查找
        // 将所有的正数取相反数,这样就只需要考虑一种情况
        boolean rev = false;
        if (dividend > 0) {
            dividend = -dividend;
            rev = !rev;
        }
        if (divisor > 0) {
            divisor = -divisor;
            rev = !rev;
        }

        //将divisor的倍数放在这个集合中
        List<Integer> candidates = new ArrayList<Integer>();
        candidates.add(divisor);
        int index = 0;
        // 注意溢出
        //因为是负数,所以这里是大于等于
        while (candidates.get(index) >= dividend - candidates.get(index)) {
            candidates.add(candidates.get(index) + candidates.get(index));
            ++index;
        }
        int ans = 0;
        //然后从大到小,将集合中的数加到结果中
        for (int i = candidates.size() - 1; i >= 0; --i) {
            if (candidates.get(i) >= dividend) {
                ans += 1 << i;
                dividend -= candidates.get(i);
            }
        }

        return rev ? -ans : ans;
    }
}

412. Fizz Buzz

2021.10.13 每日一题

题目描述

给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:

answer[i] == “FizzBuzz” 如果 i 同时是 3 和 5 的倍数。
answer[i] == “Fizz” 如果 i 是 3 的倍数。
answer[i] == “Buzz” 如果 i 是 5 的倍数。
answer[i] == i 如果上述条件全不满足。

示例 1:

输入:n = 3
输出:[“1”,“2”,“Fizz”]

示例 2:

输入:n = 5
输出:[“1”,“2”,“Fizz”,“4”,“Buzz”]

示例 3:

输入:n = 15
输出:[“1”,“2”,“Fizz”,“4”,“Buzz”,“Fizz”,“7”,“8”,“Fizz”,“Buzz”,“11”,“Fizz”,“13”,“14”,“FizzBuzz”]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/fizz-buzz
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

class Solution {
    public List<String> fizzBuzz(int n) {
        List<String> res = new ArrayList<>();
        int idx = 1;
        while(idx <= n){
            if(idx % 3 == 0 && idx % 5 == 0)
                res.add("FizzBuzz");
            else if(idx % 3 == 0)
                res.add("Fizz");
            else if(idx % 5 == 0)
                res.add("Buzz");
            else
                res.add(String.valueOf(idx));
            idx++;
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值