12. 整数转罗马数字
七个不同的符号代表罗马数字,其值如下:
符号 值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:
- 如果该值不是以 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 的次方(
I
,X
,C
,M
)最多可以连续附加 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性价比、难度很低,但是做出了困难题,还是很开心