剑指offer 打卡计划 | 每日进步一点点 | 第六天

158 阅读3分钟

image-20220409231852836.png

一起养成写作习惯!这是我参与「掘金日新计划 · 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、遍历整个链表,如果当前节点pval值等于val,我们就让pre->next = p->next,结束遍历。

3、最后返回虚拟头节点的下一个节点。

图片.png 时间复杂度分析: 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],那么'*'匹配0p[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])

图片.png


总结:

 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];
     }
 };