Leetcode 10:正则表达式匹配
题目描述
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '* ' 的正则表达式匹配。
题目解析
详见:https://leetcode-cn.com/problems/regular-expression-matching/solution/c-ji-yi-hua-shen-du-you-xian-sou-suo-by-da-li-wa-2/
代码实现
class Solution {
public:
vector<vector<int>> mem;
int dfs(const string& s, const string& p, int i, int j) {
if (i == s.size()) return j == p.size() ? 1 : -1;
if (j == p.size()) return i == s.size() ? 1 : -1;
if (mem[i][j] != 0) return mem[i][j];
if (j == p.size() - 1 || p[j + 1] != '*') {
if (p[j] == '.' || p[j] == s[i]) {
mem[i][j] = dfs(s, p, i + 1, j + 1);
return mem[i][j];
}
} else {
if (dfs(s, p, i, j + 2) > 0) {
mem[i][j] = 1;
return mem[i][j];
}
if (p[j] == '.' || p[j] == s[i]) {
bool t = dfs(s, p, i + 1, j + 2) > 0 || dfs(s, p, i + 1, j) > 0;
mem[i][j] = t ? 1 : -1;
return mem[i][j];
}
}
mem[i][j] = -1;
return mem[i][j];
}
bool isMatch(string s, string p) {
s += '#';
p += '#';
mem = vector<vector<int> >(s.size(), vector<int>(p.size(), 0));
return dfs(s, p, 0, 0) > 0;
}
};
耗时&内存占用
Leetcode 21:合并两个有序链表
题目描述
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
解题思路
不需要多说,直接看代码就看得懂,这是迭代法。递归法曾经在博客发过,具体可以在博客里面搜索一下。
代码实现
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
{
ListNode* head = new ListNode(-1);
ListNode* p = head;
while (l1!=nullptr && l2!=nullptr) {
if (l1->val <= l2->val)
{
head->next = l1;
l1 = l1->next;
}
else {
head->next = l2;
l2 = l2->next;
}
head = head->next;
}
head->next = l1 ? l1 : l2;
return p->next;
}
耗时和内存消耗
Leetcode 23:合并K个排序链表
题目描述
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
解题思路
其实解题思路有很多,例如链表全部push到一个vector后然后排序,最后再转换成一个list,这个复杂度是O(n^2),这是我想到的方法,但是这个方法太麻烦,复杂度太高。
另外一种思想就是合并数组中第k个链表到第1个链表,合并数组中第k-1个链表到第2个链表,依次这样操作;一轮合并之后,新链表分布在数组的 第1 到 第(k+1)/2个链表中,继续1这样的合并直到新链表只在数组第一个位置。这种方法是时间复杂度为O(N* log(k)),其中k为链表个数,N为链表平均长度。
还有一种思想是首先将vector转化为queue,然后在queue中每次取出前两个链表,按照之前简单的两个链表合并的方式进行合并,将合并完之后的链表push到queue的最后。依次这样进行,其实和上面的方法思路总体上是一样的,只不过用了一个queue来做中间变量。
下面是这种方法的实现。
代码实现
ListNode* mergetwoLists(ListNode* l1, ListNode* l2)
{
ListNode* head = new ListNode(-1);
ListNode* p = head;
while (l1 && l2) {
if (l1->val < l2->val)
{
head->next = l1;
l1 = l1->next;
}
else {
head->next = l2;
l2 = l2->next;
}
head = head->next;
}
head->next = l1 ? l1 : l2;
return p->next;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
int numoflist = lists.size();
if (numoflist == 0)
return nullptr;
if (numoflist == 1)
return lists[0];
queue<ListNode*> temp(deque<ListNode*>(lists.begin(), lists.end()));
//将vector转化为队列
//如果队列元素大于1,则拿两个合并,合并后的链表继续添加到链表尾部
while (temp.size() > 1)
{
ListNode* temp1 = temp.front();
temp.pop();
ListNode* temp2 = temp.front();
temp.pop();
temp.push(mergetwoLists(temp1, temp2));
}
return temp.front();
}
复杂度
Leetcode 31:下一个排列
题目描述
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
解题思路
详见:
https://leetcode-cn.com/problems/next-permutation/solution/xia-yi-ge-pai-lie-by-leetcode/
代码实现
void reve(vector<int>& nums, int start)
{
int i = start, j = nums.size() - 1;
while (i < j)
{
swap(nums[i], nums[j]);
i++;
j--;
}
}
void nextPermutation(vector<int>& nums) {
int i = nums.size() - 2;
while (i >= 0 && nums[i + 1] <= nums[i])
{
i--;
}
if (i >= 0)
{
int j = nums.size() - 1;
while (j >= 0 && nums[j] <= nums[i])
{
j--;
}
swap(nums[i], nums[j]);
}
reve(nums,i+1);
}
复杂度
时间复杂度:O(n)
空间复杂度:O(1)
文章评论