序言
终于leetcode完成了前100题,现在总结下前阶段部分我觉得值得总结的题的细节。并非完整的结题报告,那将没有任何意义,毕竟在leetcode官网有更多详解的信息。
1. Two Sum 和 3. Longest Substring Without Repeating Characters
这两个题都使用哈希表可以很快解决,但是在解决第三题的时候,我犯了点奇怪的错误,由此错误也回顾了map
的一些使用细节。第三题我的代码如下:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char,int> mp;
int len=0;
for(int i=0,j=0,tmp;i<s.size()&&j<s.size();)
if(mp.count(s[j]) == 0){
mp.insert(make_pair(s[j],j));
++j;
len=max(len,(int)mp.size());
}
else{
tmp=mp[s[j]];
//for(int k=i;k<=mp[s[j]];++k)
for(int k=i;k<=tmp;++k)
mp.erase(s[k]);
i=tmp+1;
}
return len;
}
};
上题的解题思想是滑窗法,使用map
的**陷阱为value=mp[x]
,如果x
对应的key不存在,则在当前map
插入x
(对应的value为空)。**这往往不会造成问题,但是上面注释的写法会导致make_pair(s[j],null)
的效果,致使程序发生死循环。**所以,使用[]
方式访问map
的key-value
要注意这样的细节问题。**以上程序的时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)。
5. Longest Palindromic Substring
该题为动态规划题,假设
F
[
i
,
j
]
F[i,j]
F[i,j]代表i
到j
位置的回文子串,那么状态转移方程如下:
F[i,j]=F[i+1,j-1] if s[i] == s[j]
伪代码如下:
for len=3 to s.size
for i=0 to s.size+1-len
if s[i] == s[len-1+i]
F[i,j]=F[i+1,len-2+i]
//求解的时候有两个方式
//1. 遍历状态数组
//2. 在上面的for循环中跟踪i和len的信息。
//第二种方式将第一种有时间复杂度方面的提升
**第二种定义状态的方式:**假设
F
[
i
,
j
]
F[i,j]
F[i,j]代表i
到j
位置的回文子串的长度,那么状态转移方程如下:
F[i,j]=F[i+1,j-1]+2; if s[i] == s[j]
伪代码如下:
for len=3 to s.size
for i=0 to s.size+1-len
if F[i+1,len-2+i] &&s[i] == s[len-1+i]
F[i,j]=F[i+1,len-2+i]+2;
//求解的时候,
//直接遍历状态数组,找到值最大的那项
第二种定义方式本质上与第一种相同,但是第二种会有细微的陷阱,如果不提前判断F[i+1,len-2+i]
,会得到错误的结论。这是因为在假定状态的时候有两个条件:1.i
到j
的子串本身是回文子串。2.i
到j
的子串的字符个数。
当然该状态设定的很冗余,因为通过j-i+1
也能得到字符个数。
其他题
第2题Add Two Numbers
,将来在43题Multiply Strings
中概括,第4题按照时间复杂度
O
(
m
+
n
)
O(m+n)
O(m+n)去解决,对数的解法比较繁琐,性价比低。其他题比较简单不总结。