1、两数之和
1 | class Solution { |
2、两数相加
1 | /** |
3、无重复字符的最长子串
1 | class Solution { |
4、两个排序数组的中位数
1 | class Solution { |
5、最长回文子串
Manacher算法,国内也叫“马拉车”。虽然 RL[i]=min(RL[2*pos-i], MaxRight-i)
,但是位于 i 半径右边界与 MaxRight之间的元素是不会被重复遍历的,否则会与 i 的对称 j 起冲突,也正因为如此,算法的复杂度是 O(n)。
1 | class Solution { |
6、Z字形变换
规律题,多些几个即可找到下标间的规律。
1 | class Solution { |
7、反转整数
1 | class Solution { |
8、字符串转整数 (atoi)
一个简单的模拟题,但不得不说leetcode的测试用例真的是强,考虑了 -1 ,给我报 +1的错,两者都考虑了,报了 -+1 的错,真的每一个可能但错误的细节都考虑到了,强!
1 | class Solution { |
9、回文数
将数字倒过来,比较前后两个数是否相同即可。
1 | class Solution { |
10、正则表达式匹配
动态规划的思想来解决这道题目,对于动态规划类的题目,是比较难的,难在状态转移方程写不出来。
首先,dp[i][j]
表示 s
中前 i
个字符和 p
中的前 j
个字符是否匹配。下面对 p
中的第 j
个字符是否是 *
号进行分类讨论(至于为啥是以*
号为关键字符进行讨论,自己想想,脑补脑补)。
1、 p[j-1] != '*'
:
只需要比较 s[i-1]
和 p[j-1]
是否匹配即可,匹配的条件为 s[i-1]==p[j-1] || p[j-1]=='.'
,转移方程为:
dp[i][j] = dp[i-1][j-1] && (s[i-1]==p[j-1] || p[j-1]=='.')
2、p[j-1] == '*'
,分3类情况讨论:
p[j-1]
的*
号不起作用,也就是没匹配,此情况下p[j-2]
和p[j-1]
是作废的,转移方程:dp[i][j] = dp[i][j-2]
p[j-1]
的*
号匹配一个字符,也就是 P 中的p[j-2] 和 p[j-1]
所组成的元素和 S 中的s[i-1]
相匹配,所以状态转移方程为:dp[i][j] = dp[i-1][j-2] && (s[i-1]==p[j-2] || p[j-2]=='.')
p[j-1]
的*
号匹配多个字符(>=2),如下图所示,很容易写出状态转移方程为:dp[i][j] =dp[i-1][j] && (s[i-1]==p[j-2] || p[j-2]=='.')
综上所述,总状态转移方程为:
接下来,对初始状态进行讨论:
当 S 不空, P 为空时,
dp[i][0] = false
当 S 空, P 不空时:
j%2!=0
时,dp[0][j] = false
j%2==0
时,dp[0][j] = dp[0][j-2] && p[j-1]=='*'
有了以上的分析,代码基本也就写完了,如下:
1 | class Solution { |