剑指offer题解合集——Week2day5

文章目录

  • 剑指offerWeek2
    • 周五:删除链表中重复的节点
      • AC代码
      • 思路:
    • 周五:正则表达式匹配
      • AC代码
      • 思路:
      • 部分模拟

剑指offerWeek2

周五:删除链表中重复的节点

题目链接:删除链表中重复的节点

在一个排序的链表中,存在重复的节点,请删除该链表中重复的节点,重复的节点不保留。

数据范围
链表中节点 val 值取值范围 [0,100]
	
链表长度 [0,100]


样例1
输入:1->2->3->3->4->4->5

输出:1->2->5
样例2
输入:1->1->1->2->3

输出:2->3

AC代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplication(ListNode* head) {
        auto dummy = new ListNode(-1);
        dummy->next = head;
        auto cur = dummy;
        while (cur->next)
        {
            auto ne = cur->next;
            while (ne && cur->next->val == ne->val) ne = ne->next;
            if (cur->next->next == ne) cur = cur->next;
            else cur->next = ne;
        }
        
        return dummy->next;
    }
};

思路:

整体思路

简单的遍历,然后如果是重复数值则删去即可

周五:正则表达式匹配

题目链接:正则表达式匹配

请实现一个函数用来匹配包括'.'和'*'的正则表达式。

模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次)。

在本题中,匹配是指字符串的所有字符匹配整个模式。

例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。

数据范围
输入字符串长度 [0,300]

样例
输入:

s="aa"
p="a*"

输出:true

AC代码

class Solution {
public:
    vector> f;
    int n, m;
    bool isMatch(string s, string p) {
        n = s.size();
        m = p.size();
        f = vector>(n + 1, vector(m + 1, -1));
        return dp(0, 0, s, p);
    }
    
    bool dp(int x, int y, string& s, string& p)
    {
        if (f[x][y] != -1) return f[x][y];
        if (y == m) // 如果p串一直匹配到末尾,则能匹配成功的唯一条件就是s串也匹配到末尾
            return f[x][y] = x == n;
        // flag的含义是当前位置是否匹配
        bool flag = x < n && (s[x] == p[y] || p[y] == '.'); // 两个相等或者p串出现'.'
        bool ans;
        if (y + 1 < m && p[y + 1] == '*')   // p串下一个位置是'*'
        {
            // 0 || 非0
            // 非0:当前位置都必须匹配 && s串的下一位置和p串的当前位置开始都必须匹配
            ans = dp(x, y + 2, s, p) || flag && dp(x + 1, y, s, p);
        }
        else
            ans = flag && dp(x + 1, y + 1, s, p);
        
        return f[x][y] = ans;
    }
};

思路:

整体思路

这题还是很难的,能理解就理解,不能理解就直接记结论,想理解的可以看看编译原理的状态机,再回来看详细阐述

直接给结论:
给出状态f[i][j]表示路径集合s从i开始一直到结束都能和路径集合p从j开始一直到结束都能匹配
- 如果p[j+1]为普通字母,则f[i][j]是真,当且仅当s[i]可以和p[j]匹配,且f[i+1][j+1]是真
- 如果p[j + 1]是'.',那么f[i][j] = f[i + 1][j + 1]
- 如果p[j+1]是通配符'*',则下面的情况只要有一种满足,f[i][j]就是真;
	- f[i][j+2]是真;
	- s[i]可以和p[j]匹配,且f[i+1][j]是真;










建议看过编译原理的状态机再往下看

样例
字符串"aaa"与模式"a.a"和"ab*a"匹配

假设存在4个点,s1, s2, s3, s4
从s1到s2有路径a, s2到s3也有路径a,s3到s4也有路径a
则称之为s1到s4的路径为aaa

那么记'.'为任意一个路径
'*'为某路径走任意次
则a.a可以称之为s1到s2经过路径a,s2到s3经过路径c,s3到s4经过路径a
ab*a则为:s1到s2经过路径a
	- s2就是s3,即*为0,s2(s3)经过路径a到s4
	- s2到s3经过若干次路径b,而后,s3经过路径a到s4
	

明白原理以后,则:
给出任意两个字符串q和p
对于字符串q,构筑点集s1……sn,使得q中元素为相邻点集的路径
那么q和p匹配的意思是,经过(路径集合)p和q都能从s1到sn
例如:
q串:aaa
p串:a.a:可以称之为s1到s2经过路径a,s2到s3经过路径c,s3到s4经过路径a
p串:ab*a则为:s1到s2经过路径a,然后
	- s2就是s3,即*为0,s2(s3)经过路径a到s4
	- s2到s3经过若干次路径b(显然这里的*只能为0),而后,s3经过路径a到s4
p串:aa*a,则s1到s2的路径为a,然后
	- s2就是s3,即*代表经过0次路径a,s2(s3)经过路径a到s4
	- s2到s3经过若干次路径a,而后,s3经过一次路径a到s4

那么
给出任意两个字符串q和p
- q[i + 1]为普通字母:那么q和p匹配的意思是,两个路径集合都要经过路径q[i],也就是存在相同值,即:q[i] == p[j],并且前面的路径要匹配,后面的路径也要匹配
- q[i + 1]为'.'  那么,q和p匹配的意思是,当前路径可以不匹配,但是前面/后续路径一定要匹配
- q[i + 1]为'*',那么要分*含义为0还是非0
	- 0:si和sk重合,并且后续路径匹配,即q[i + 2 ~ n]和p[j ~ m]都要匹配( + 2是跳过子母和'*')
	- 非0:经过若干次路径q[i],这个q[i]可以为经过1次,也可以为n次,但是重点是至少经过一次,并且那么p[j + 1]一直到结束必须和q[i]一直到结局是匹配的,并且前面也要匹配,(p串之所以 + 1,是p[j] == q[i],也就是当前位置已经匹配了)

部分模拟

字符串"aaa"与模式"a.a"和"ab*a"匹配

假设存在4个点,s1, s2, s3, s4
从s1到s2有路径a, s2到s3也有路径a,s3到s4也有路径a
则称之为s1到s4的路径为aaa

那么记’.'为任意一个路径
'*'为某路径走任意次
则a.a可以称之为s1到s2经过路径a,s2到s3经过路径c,s3到s4经过路径a
ab*a则为:s1到s2经过路径a

  • s2就是s3,即*为0,s2(s3)经过路径a到s4
    • s2到s3经过若干次路径b,而后,s3经过路径a到s4

你可能感兴趣的:(剑指offer,算法,leetcode,c++,剑指offer)