一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
剑指 Offer 17. 打印从1到最大的n位数
思路
(模拟) O(n)
1、求出最大的n位十进制数。
2、枚举[1, n],将其加入res中。
时间复杂度分析: O(n)。
c++代码
class Solution {
public:
vector<int> printNumbers(int n) {
int num = 0; //记录最大的n位十进制数
while(n) num = num * 10 + 9, n--;
vector<int> res;
for(int i = 1; i <= num; i++){
res.push_back(i);
}
return res;
}
};
剑指 Offer 18. 删除链表的节点
思路
(链表, 遍历) O(n)
为了方便处理边界情况,我们定义一个虚拟元素dummy指向链表头节点,即dummy->next = head,同时定义一个pre指针,记录当前遍历到的节点的前驱节点。
具体过程如下:
1、初始化虚拟头节点dummy->next = head,前驱节点pre = dummy。
2、遍历整个链表,如果当前节点p的val值等于val,我们就让pre->next = p->next,结束遍历。
3、最后返回虚拟头节点的下一个节点。
时间复杂度分析: O(n)
c++代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* pre = head;
for(ListNode* p = head; p; pre = p, p = p->next){
if(p->val == val){
pre->next = p->next;
break;
}
}
return dummy->next;
}
};
剑指 Offer 19. 正则表达式匹配
思路
(动态规划) O(nm)
状态表示: f[i][j] 表示字符串s 的前 i个字符和字符串 p 的前j 个字符能否匹配。
状态计算:
根据p[j] 是什么来划分集合:
-
1、
p[j] != '*',即p[j]是字符, 看p[j]和s[i]的关系。如果p[j] == s[i],则需判断s的前i - 1个字母 能否和p的前j -1个字母匹配 ,即f[i][j] == f[i - 1][j - 1],不匹配 , 无法转移。 -
2
P[j]是匹配符:- 如果
p[j] == '.',则p[j]和s[j]匹配 ,则需判断s的前i - 1个字母能否和p的前j -1个字母匹配 ,即f[i][j] == f[i - 1][j - 1]。 p[j]为'*',得看p[j - 1]和s[i]的关系。如果不匹配,即p[j - 1] != s[i],那么'*'匹配0个p[j - 1],则需判断s的前i个字母 能否和p的前j - 2个字母匹配 ,即f[i][j] == f[i][j - 2]。如果匹配,即p[j - 1] == s[i] || p[j - 1] == '.',若'*'匹配多个p[j - 1],则需判断s的前i - 1个字母 能否和p的前j个字母匹配 ,即f[i][j] == f[i - 1][j])。
- 如果
总结:
f[i][j] == f[i - 1][j - 1], 前提条件为p[j] == s[i] || p[j] == '.'
f[i][j] == f[i][j - 2], 前提条件为p[j] == '*' && p[j - 1] != s[i]
f[i][j] == f[i - 1][j], 前提条件为p[j] == '*' && ( p[j - 1] == s[i] || p[j - 1] == '.')
c++代码
class Solution {
public:
bool isMatch(string s, string p) {
int n = s.size(), m = p.size();
vector<vector<bool>>f(n + 1, vector<bool>(m + 1));
s = ' ' + s; // 下标从1开始
p = ' ' + p;
f[0][0] = true;
for(int i = 0; i <= n; i++){
for(int j = 1; j <= m; j++){
if(j + 1 <= m && p[j + 1] == '*') continue; // 不去处理*的前一位字符。
if(p[j] != '*'){
if((s[i] == p[j] || p[j] == '.')&& i)
f[i][j] = f[i - 1][j - 1];
}else{
if(j >= 2) f[i][j] = f[i][j - 2]; //匹配0个
if(i && (p[j - 1] == '.' || s[i] == p[j - 1] ) && f[i - 1][j]) //匹配多个
f[i][j] = f[i - 1][j];
}
}
}
return f[n][m];
}
};