Skip to content

Commit d77d7af

Browse files
committed
新增3题,累积45题
1 parent ac4714b commit d77d7af

File tree

3 files changed

+197
-0
lines changed

3 files changed

+197
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.cjl.leetcode;
2+
3+
/*
4+
10. 正则表达式匹配
5+
问题描述:
6+
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
7+
'.' 匹配任意单个字符
8+
'*' 匹配零个或多个前面的那一个元素
9+
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
10+
示例 1:
11+
输入:s = "aa", p = "a"
12+
输出:false
13+
解释:"a" 无法匹配 "aa" 整个字符串。
14+
示例 2:
15+
输入:s = "aa", p = "a*"
16+
输出:true
17+
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
18+
示例 3:
19+
输入:s = "ab", p = ".*"
20+
输出:true
21+
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。
22+
提示:
23+
1 <= s.length <= 20
24+
1 <= p.length <= 30
25+
s 只包含从 a-z 的小写字母。
26+
p 只包含从 a-z 的小写字母,以及字符 . 和 *。
27+
保证每次出现字符 * 时,前面都匹配到有效的字符
28+
*/
29+
public class Question_10 {
30+
31+
// 时间复杂度是O(MN),空间复杂度是O(MN)
32+
public boolean solution1(String s, String p) {
33+
char[] cs = s.toCharArray();
34+
char[] cp = p.toCharArray();
35+
36+
// dp[i][j]:表示s的前i个字符,p的前j个字符是否能够匹配
37+
boolean[][] dp = new boolean[cs.length + 1][cp.length + 1];
38+
39+
// 初期值
40+
// s为空,p为空,能匹配上
41+
dp[0][0] = true;
42+
// p为空,s不为空,必为false(boolean数组默认值为false,无需处理)
43+
44+
// s为空,p不为空,由于*可以匹配0个字符,所以有可能为true
45+
for (int j = 1; j <= cp.length; j++) {
46+
if (cp[j - 1] == '*') {
47+
// 因为题目条件(保证每次出现字符 * 时,前面都匹配到有效的字符)
48+
// 所以*必然不会出现在cp[0]的位置,即进入这里的j必然会大于1
49+
dp[0][j] = dp[0][j - 2];
50+
}
51+
}
52+
53+
// 填格子
54+
for (int i = 1; i <= cs.length; i++) {
55+
for (int j = 1; j <= cp.length; j++) {
56+
// 文本串和模式串,末尾字符串能匹配得上
57+
if (cs[i - 1] == cp[j - 1] || cp[j - 1] == '.') {
58+
dp[i][j] = dp[i - 1][j - 1];
59+
} else if (cp[j - 1] == '*') {
60+
// 如果模式串的末尾是*,那么模式串*前的那个字符,可分为以下两种情况
61+
// 第一种,能够跟文本串匹配上,那能匹配0到多次
62+
// 第二种,跟文本串匹配不上,那只能匹配0次,把这个字符抹除掉
63+
if (cs[i - 1] == cp[j - 2] || cp[j - 2] == '.') {
64+
dp[i][j] = dp[i][j - 2] // 匹配0次的情况
65+
|| dp[i - 1][j]; // 匹配1次或多次的情况
66+
} else {
67+
dp[i][j] = dp[i][j - 2];// 匹配0次
68+
}
69+
}
70+
}
71+
}
72+
return dp[cs.length][cp.length];
73+
}
74+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.cjl.leetcode;
2+
3+
/*
4+
13. 罗马数字转整数
5+
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
6+
字符 数值
7+
I 1
8+
V 5
9+
X 10
10+
L 50
11+
C 100
12+
D 500
13+
M 1000
14+
例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
15+
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。
16+
同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
17+
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
18+
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
19+
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
20+
给定一个罗马数字,将其转换成整数。
21+
示例 1:
22+
输入: s = "III"
23+
输出: 3
24+
示例 2:
25+
输入: s = "IV"
26+
输出: 4
27+
示例 3:
28+
输入: s = "IX"
29+
输出: 9
30+
示例 4:
31+
输入: s = "LVIII"
32+
输出: 58
33+
解释: L = 50, V= 5, III = 3.
34+
示例 5:
35+
输入: s = "MCMXCIV"
36+
输出: 1994
37+
解释: M = 1000, CM = 900, XC = 90, IV = 4.
38+
提示:
39+
1 <= s.length <= 15
40+
s 仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')
41+
题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999] 内
42+
题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
43+
IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
44+
关于罗马数字的详尽书写规则,可以参考 罗马数字 - Mathematics 。
45+
*/
46+
public class Question_13 {
47+
48+
// 时间复杂度是O(N),空间复杂度是O(1)
49+
public int solution1(String s){
50+
int sum = 0;
51+
int preNum = getValue(s.charAt(0));
52+
for (int i = 1; i < s.length(); i++) {
53+
int num = getValue(s.charAt(i));
54+
// 如果大于前面的数字,则需要做减法
55+
if(preNum < num){
56+
sum -= preNum;
57+
}else{
58+
sum += preNum;
59+
}
60+
preNum = num;
61+
}
62+
sum += preNum;
63+
return sum;
64+
}
65+
66+
private int getValue(char ch) {
67+
switch(ch) {
68+
case 'I': return 1;
69+
case 'V': return 5;
70+
case 'X': return 10;
71+
case 'L': return 50;
72+
case 'C': return 100;
73+
case 'D': return 500;
74+
case 'M': return 1000;
75+
default: return 0;
76+
}
77+
}
78+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.cjl.leetcode;
2+
3+
/*
4+
88. 合并两个有序数组
5+
给你两个按 非递减顺序 排列的整数数组nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
6+
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
7+
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
8+
示例 1:
9+
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
10+
输出:[1,2,2,3,5,6]
11+
解释:需要合并 [1,2,3] 和 [2,5,6] 。
12+
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
13+
示例 2:
14+
输入:nums1 = [1], m = 1, nums2 = [], n = 0
15+
输出:[1]
16+
解释:需要合并 [1] 和 [] 。
17+
合并结果是 [1] 。
18+
示例 3:
19+
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
20+
输出:[1]
21+
解释:需要合并的数组是 [] 和 [1] 。
22+
合并结果是 [1] 。
23+
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
24+
提示:
25+
nums1.length == m + n
26+
nums2.length == n
27+
0 <= m, n <= 200
28+
1 <= m + n <= 200
29+
-10^9 <= nums1[i], nums2[j] <= 10^9
30+
进阶:你可以设计实现一个时间复杂度为 O(m + n) 的算法解决此问题吗?
31+
*/
32+
public class Question_88 {
33+
34+
// 时间复杂度是O(N),空间复杂度是O(1)
35+
public void solution1(int[] nums1, int m, int[] nums2, int n) {
36+
int p = m-- + n-- - 1;
37+
while (m >= 0 && n >= 0) {
38+
nums1[p--] = nums1[m] > nums2[n] ? nums1[m--] : nums2[n--];
39+
}
40+
41+
while (n >= 0) {
42+
nums1[p--] = nums2[n--];
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)