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;
}
}