Skip to content

Commit c19a90b

Browse files
committed
add notes
1 parent 84b244c commit c19a90b

11 files changed

Lines changed: 1052 additions & 0 deletions
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
17.罗马数字转整数
2+
===
3+
4+
5+
### 题目
6+
7+
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
8+
9+
```
10+
字符 数值
11+
I 1
12+
V 5
13+
X 10
14+
L 50
15+
C 100
16+
D 500
17+
M 1000
18+
```
19+
例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
20+
21+
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
22+
23+
- I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
24+
- X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
25+
- C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
26+
- 给定一个罗马数字,将其转换成整数。
27+
28+
29+
30+
示例 1:
31+
32+
- 输入: s = "III"
33+
- 输出: 3
34+
35+
示例 2:
36+
37+
- 输入: s = "IV"
38+
- 输出: 4
39+
40+
示例 3:
41+
42+
- 输入: s = "IX"
43+
- 输出: 9
44+
45+
示例 4:
46+
47+
- 输入: s = "LVIII"
48+
- 输出: 58
49+
- 解释: L = 50, V= 5, III = 3.
50+
51+
示例 5:
52+
53+
- 输入: s = "MCMXCIV"
54+
- 输出: 1994
55+
- 解释: M = 1000, CM = 900, XC = 90, IV = 4.
56+
57+
58+
提示:
59+
60+
- 1 <= s.length <= 15
61+
- s 仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')
62+
- 题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999]
63+
- 题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
64+
- IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
65+
66+
### 思路
67+
68+
通常情况下,罗马数字中小的数字在大的数字的右边。若输入的字符串满足该情况,那么可以将每个字符视作一个单独的值,累加每个字符对应的数值即可。
69+
70+
例如 XXVII 可视作 X+X+V+I+I=10+10+5+1+1=27。
71+
72+
若存在小的数字在大的数字的左边的情况,根据规则需要减去小的数字。对于这种情况,我们也可以将每个字符视作一个单独的值,若一个数字右侧的数字比它大,则将该数字的符号取反。
73+
74+
例如 XIV 可视作 X−I+V=10−1+5=14。
75+
76+
所以我们可以从左遍历,如果一个字符右边的比当前的大,那这个就要减去该值,否则就加。
77+
78+
```java
79+
class Solution {
80+
Map<Character, Integer> symbolValues = new HashMap<Character, Integer>() {{
81+
put('I', 1);
82+
put('V', 5);
83+
put('X', 10);
84+
put('L', 50);
85+
put('C', 100);
86+
put('D', 500);
87+
put('M', 1000);
88+
}};
89+
90+
public int romanToInt(String s) {
91+
int ans = 0;
92+
int n = s.length();
93+
for (int i = 0; i < n; ++i) {
94+
int value = symbolValues.get(s.charAt(i));
95+
if (i < n - 1 && value < symbolValues.get(s.charAt(i + 1))) {
96+
ans -= value;
97+
} else {
98+
ans += value;
99+
}
100+
}
101+
return ans;
102+
}
103+
}
104+
```
105+
106+
复杂度分析:
107+
108+
- 时间复杂度:O(n),其中 n 是字符串 s 的长度。
109+
110+
- 空间复杂度:O(1)。
111+
112+
---
113+
- 邮箱 :charon.chui@gmail.com
114+
- Good Luck!
115+
116+
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
18.整数转罗马数字
2+
===
3+
4+
5+
### 题目
6+
7+
七个不同的符号代表罗马数字,其值如下:
8+
```
9+
符号 值
10+
I 1
11+
V 5
12+
X 10
13+
L 50
14+
C 100
15+
D 500
16+
M 1000
17+
```
18+
罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:
19+
20+
- 如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
21+
- 如果该值以 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)。
22+
- 只有 10 的次方(I, X, C, M)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式。
23+
- 给定一个整数,将其转换为罗马数字。
24+
25+
26+
27+
示例 1:
28+
29+
- 输入:num = 3749
30+
31+
- 输出: "MMMDCCXLIX"
32+
33+
- 解释:
34+
35+
- 3000 = MMM 由于 1000 (M) + 1000 (M) + 1000 (M)
36+
- 700 = DCC 由于 500 (D) + 100 (C) + 100 (C)
37+
- 40 = XL 由于 50 (L) 减 10 (X)
38+
- 9 = IX 由于 10 (X) 减 1 (I)
39+
注意:49 不是 50 (L) 减 1 (I) 因为转换是基于小数位
40+
41+
示例 2:
42+
43+
- 输入:num = 58
44+
45+
- 输出:"LVIII"
46+
47+
解释:
48+
49+
- 50 = L
50+
- 8 = VIII
51+
52+
示例 3:
53+
54+
- 输入:num = 1994
55+
56+
- 输出:"MCMXCIV"
57+
58+
- 解释:
59+
60+
- 1000 = M
61+
- 900 = CM
62+
- 90 = XC
63+
- 4 = IV
64+
65+
66+
提示:
67+
68+
- 1 <= num <= 3999
69+
70+
### 思路
71+
72+
题目中说了num <= 3999
73+
74+
所以:
75+
76+
- 千位数只能由M表示,分别为 M,MM,MMM
77+
- 百位数只能由C、CC、CCC、CD、D、DC、DCC、DCCC、CM表示
78+
- 十位数只能由X、XX、XXX、XL、L、LX、LXX、LXXX、XC表示
79+
- 个位数只能由I、II、III、IV、V、VI、VII、VIII、IV表示
80+
81+
82+
所以可以利用模运算和除法运算,得到num每个位上的数字,然后去取对应的罗马数字就可以了。
83+
84+
```java
85+
86+
class Solution {
87+
String[] thousands = {"", "M", "MM", "MMM"};
88+
String[] hundreds = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
89+
String[] tens = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
90+
String[] ones = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
91+
92+
public String intToRoman(int num) {
93+
StringBuffer roman = new StringBuffer();
94+
roman.append(thousands[num / 1000]);
95+
roman.append(hundreds[num % 1000 / 100]);
96+
roman.append(tens[num % 100 / 10]);
97+
roman.append(ones[num % 10]);
98+
return roman.toString();
99+
}
100+
}
101+
```
102+
103+
复杂度分析:
104+
105+
- 时间复杂度:O(1)。计算量与输入数字的大小无关。
106+
107+
- 空间复杂度:O(1)。
108+
109+
110+
---
111+
- 邮箱 :charon.chui@gmail.com
112+
- Good Luck!
113+
114+
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
19.最后一个单词的长度
2+
===
3+
4+
5+
### 题目
6+
7+
给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。
8+
9+
单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。
10+
11+
12+
13+
示例 1:
14+
15+
- 输入:s = "Hello World"
16+
- 输出:5
17+
- 解释:最后一个单词是“World”,长度为 5。
18+
19+
示例 2:
20+
21+
- 输入:s = " fly me to the moon "
22+
- 输出:4
23+
- 解释:最后一个单词是“moon”,长度为 4。
24+
25+
示例 3:
26+
27+
- 输入:s = "luffy is still joyboy"
28+
- 输出:6
29+
- 解释:最后一个单词是长度为 6 的“joyboy”。
30+
31+
32+
提示:
33+
34+
- 1 <= s.length <= 104
35+
- s 仅有英文字母和空格 ' ' 组成
36+
- s 中至少存在一个单词
37+
38+
### 思路
39+
40+
从最后一个字母开始往前遍历,并开始计数,找到第一个空格的时候停止。要注意没有空格的情况,例如"ab",应该返回2。
41+
42+
```java
43+
class Solution {
44+
public int lengthOfLastWord(String s) {
45+
int end = s.length() - 1;
46+
while(end >= 0 && s.charAt(end) == ' ') end--;
47+
if(end < 0) return 0;
48+
int start = end;
49+
while(start >= 0 && s.charAt(start) != ' ') start--;
50+
return end - start;
51+
}
52+
}
53+
```
54+
55+
56+
```python
57+
class Solution:
58+
def lengthOfLastWord(self, s: str) -> int:
59+
length = 0
60+
for i in reversed(range(len(s.rstrip()))):
61+
if s.rstrip()[i] == " ":
62+
return length
63+
else:
64+
length += 1
65+
return length
66+
```
67+
68+
复杂度分析:
69+
70+
- 时间复杂度:O(n),其中 n 是字符串的长度。最多需要反向遍历字符串一次。
71+
72+
- 空间复杂度:O(1)。
73+
74+
---
75+
- 邮箱 :charon.chui@gmail.com
76+
- Good Luck!
77+
78+

Algorithm/20.最长公共前缀.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
20.最长公共前缀
2+
===
3+
4+
5+
### 题目
6+
7+
编写一个函数来查找字符串数组中的最长公共前缀。
8+
9+
如果不存在公共前缀,返回空字符串 ""。
10+
11+
12+
13+
示例 1:
14+
15+
- 输入:strs = ["flower","flow","flight"]
16+
- 输出:"fl"
17+
18+
示例 2:
19+
20+
- 输入:strs = ["dog","racecar","car"]
21+
- 输出:""
22+
- 解释:输入不存在公共前缀。
23+
24+
25+
提示:
26+
27+
- 1 <= strs.length <= 200
28+
- 0 <= strs[i].length <= 200
29+
- strs[i] 如果非空,则仅由小写英文字母组成
30+
31+
### 思路
32+
33+
34+
###### 遍历每次找重合的前缀部分
35+
36+
横向扫描,依次遍历每个字符串,更新最长公共前缀
37+
38+
```python
39+
class Solution:
40+
def longestCommonPrefix(self, strs: List[str]) -> str:
41+
ans = strs[0]
42+
def compare(s1, s2) -> str:
43+
result = ""
44+
for i in range(min(len(s1), len(s2))):
45+
if s1[i] == s2[i]:
46+
result += s1[i]
47+
else:
48+
break
49+
return result
50+
51+
for i in range(1, len(strs)):
52+
ans = compare(ans, strs[i])
53+
return ans
54+
```
55+
56+
57+
复杂度分析:
58+
59+
- 时间复杂度:O(mn),其中 m 是字符串数组中的字符串的平均长度,n 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。
60+
61+
- 空间复杂度:O(1)。使用的额外空间复杂度为常数。
62+
63+
64+
---
65+
- 邮箱 :charon.chui@gmail.com
66+
- Good Luck!
67+
68+

0 commit comments

Comments
 (0)