131周的总结写好忘记发布了。。。今天都周五了才发现
5016. 删除最外层的括号
有效括号字符串为空 ("")
、"(" + A + ")"
或 A + B
,其中 A
和 B
都是有效的括号字符串,+
代表字符串的连接。例如,""
,"()"
,"(())()"
和 "(()(()))"
都是有效的括号字符串。
如果有效字符串 S
非空,且不存在将其拆分为 S = A+B
的方法,我们称其为原语(primitive),其中 A
和 B
都是非空有效括号字符串。
给出一个非空有效字符串 S
,考虑将其进行原语化分解,使得:S = P_1 + P_2 + ... + P_k
,其中 P_i
是有效括号字符串原语。
对 S
进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 S
。
示例 1:
输入:"(()())(())"
输出:"()()()"
解释:
输入字符串为 "(()())(())",原语化分解得到 "(()())" + "(())",
删除每个部分中的最外层括号后得到 "()()" + "()" = "()()()"。
示例 2:
输入:"(()())(())(()(()))"
输出:"()()()()(())"
解释:
输入字符串为 "(()())(())(()(()))",原语化分解得到 "(()())" + "(())" + "(()(()))",
删除每隔部分中的最外层括号后得到 "()()" + "()" + "()(())" = "()()()()(())"。
思路:
用一个栈模拟,我们的目的是去掉“第一层”括号,也就是优先级最低的括号。
当栈空的时候, '(' 入栈 ,记下 index。(栈空时不会遇到 ')' )
栈非空,遇到 '(' 入栈,遇到 ')' 就把栈顶元素出栈。当栈再次为空时,就代表我们已经遍历了一个最外层括号,从 index +1 处记录答案,就把最外层的 '( ··· )'给去掉了。
模拟一遍很容易懂的
class Solution {
public:
string removeOuterParentheses(string S) {
stack<char> ss;
string res;
int cur = 0;
for(int i=0;i<S.length();i++)
{
char c = S[i];
if(c=='(')
{
if(ss.empty()) cur = i;
ss.push(c);
}
else
{
ss.pop();
if(ss.empty())
{
for(int j=cur+1;j<i;j++)
{
res+=S[j];
}
}
}
}
return res;
}
};
5017. 从根到叶的二进制数之和
给出一棵二叉树,其上每个结点的值都是 0
或 1
。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1
,那么它表示二进制数 01101
,也就是 13
。
对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。
以 10^9 + 7 为模,返回这些数字之和。
输入:[1,0,1,0,1,0,1]
输出:22
解释:(100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22
提示:
- 树中的结点数介于
1
和1000
之间。 - node.val 为
0
或1
。
思路:
相当于树的 DFS了,不过要注意,这个必须要定义一个额外的数字来记录每次走到叶节点后相加的结果,注意取余。 避免超出 int 的表示范围。
class Solution {
public:
int res = 0;
int count = 0;
int sumRootToLeaf(TreeNode* root) {
if(!root) return 0;
rec(root,0);
return res;
}
void rec(TreeNode* root,int sum)
{
sum=sum*2+root->val;
sum%=1000000007;
if(!root->left&&!root->right)
{
res+=sum;
res%=1000000007;
return ;
}
if(root->left) rec(root->left,sum);
if(root->right) rec(root->right,sum);
}
};
5018. 驼峰式匹配
如果我们可以将小写字母插入模式串 pattern
得到待查询项 query
,那么待查询项与给定模式串匹配。(我们可以在任何位置插入每个字符,也可以插入 0 个字符。)
给定待查询列表 queries
,和模式串 pattern
,返回由布尔值组成的答案列表 answer
。只有在待查项 queries[i]
与模式串 pattern
匹配时, answer[i]
才为 true
,否则为 false
。
示例 1:
输入:queries = ["FooBar","FooBarTest","FootBall","FrameBuffer","ForceFeedBack"], pattern = "FB"
输出:[true,false,true,true,false]
示例:
"FooBar" 可以这样生成:"F" + "oo" + "B" + "ar"。
"FootBall" 可以这样生成:"F" + "oot" + "B" + "all".
"FrameBuffer" 可以这样生成:"F" + "rame" + "B" + "uffer".
提示:
1 <= queries.length <= 100
1 <= queries[i].length <= 100
1 <= pattern.length <= 100
- 所有字符串都仅由大写和小写英文字母组成。
思路:
对于 queries 中的每个字符串 s ,遍历 s 。对每一个字符 c ,如果与 pattern 当前位置字符相同,i++
(i 代表 s 中与pattern 相同的字符数量),其余则放入 temp。
如果 i = pattern.size() 并且 temp 中没有大写字母,就说明我们可以通过 pattern 加上小写字母的方式得到 s 。
class Solution {
public:
vector<bool> camelMatch(vector<string>& queries, string pattern) {
int n = pattern.size();
vector<bool> res;
for(auto s:queries)
{
int i=0;
string temp; //记录与pattern不同的字符
for(auto c:s)
{
if(c==pattern[i])
i++;
else temp+=c;
}
bool flag = false;
if(i==n) flag = true; //如果相同字符数量等于 pattern 大小
for(auto c:temp)
{
if(c<'a')
{
flag = false;
break;
}
}
res.push_back(flag);
}
return res;
}
};
5019. 视频拼接
你将会获得一系列视频片段,这些片段来自于一项持续时长为 T
秒的体育赛事。这些片段可能有所重叠,也可能长度不一。
视频片段 clips[i]
都用区间进行表示:开始于 clips[i][0]
并于 clips[i][1]
结束。我们甚至可以对这些片段自由地再剪辑,例如片段 [0, 7]
可以剪切成 [0, 1] + [1, 3] + [3, 7]
三部分。
我们需要将这些片段进行再剪辑,并将剪辑后的内容拼接成覆盖整个运动过程的片段([0, T]
)。返回所需片段的最小数目,如果无法完成该任务,则返回 -1
。
示例 1:
输入:clips = [[0,2],[4,6],[8,10],[1,9],[1,5],[5,9]], T = 10
输出:3
解释:
我们选中 [0,2], [8,10], [1,9] 这三个片段。
然后,按下面的方案重制比赛片段:
将 [1,9] 再剪辑为 [1,2] + [2,8] + [8,9] 。
现在我们手上有 [0,2] + [2,8] + [8,10],而这些涵盖了整场比赛 [0, 10]。
示例 2:
输入:clips = [[0,1],[1,2]], T = 5
输出:-1
解释:
我们无法只用 [0,1] 和 [0,2] 覆盖 [0,5] 的整个过程。
提示:
1 <= clips.length <= 100
0 <= clips[i][0], clips[i][1] <= 100
0 <= T <= 100
思路:
大神太强了orz,这道题竟然用动态规划写的。我就在那里模拟,一直超时,改了很久才对。。。看了第一名的代码,当时就震惊了!
先上我自己的思路,我一开始写的太复杂了,这是后来简化版的,不过思路一致:
贪心的思想,每次只维护上一个区间的右边界 last。在与上一个区间相交的区间中,找出其中最大的右边界即可。
若找不到区间与当前区间相交,则无法完成拼接。
class Solution {
public:
int res = 0;
int videoStitching(vector<vector<int>>& clips, int T) {
int last = 0,count = 0;
while(1)
{
if(last>=T) break;
int t = INT_MIN;
bool flag = false;
for(int i=0;i<clips.size();i++)
{
if(clips[i][0]<=last)
{
t = max(t,clips[i][1]);
}
}
if(t>last)
{
last = t;
count++;
flag = true;
}
if(!flag) break;
}
return last>=T?count:-1;
}
};
大神的dp @cuiaoxiang
const int INF = 1 << 30;
class Solution {
public:
int videoStitching(vector<vector<int>>& a, int T) {
sort(a.begin(), a.end(),
[](const vector<int>& u, const vector<int>& v) {
return u[1] < v[1];
});
int n = a.size();
vector<int> dp(n);
int ret = INF;
for (int i = 0; i < n; ++i) {
dp[i] = (a[i][0] == 0 ? 1 : INF);
for (int j = 0; j < i; ++j) {
if (a[j][1] >= a[i][0]) {
dp[i] = min(dp[j] + 1, dp[i]);
}
}
}
for (int i = 0; i < n; ++i) {
if (a[i][1] >= T) {
ret = min(ret, dp[i]);
}
}
if (ret == INF) ret = -1;
return ret;
}
};