A题链接

给你一个目标数组 target 和一个整数 n。每次迭代,需要从 list = {1,2,3..., n} 中依序读取一个数字。

请使用下述操作来构建目标数组 target :

  • Push:从 list 中读取一个新元素, 并将其推入数组中。
  • Pop:删除数组中的最后一个元素。
  • 如果目标数组构建完成,就停止读取更多元素。

题目数据保证目标数组严格递增,并且只包含 1 到 n 之间的数字。

请返回构建目标数组所用的操作序列。

题目数据保证答案是唯一的。

示例 1

输入:target = [1,3], n = 3
输出:["Push","Push","Pop","Push"]
解释:
读取 1 并自动推入数组 -> [1]
读取 2 并自动推入数组,然后删除它 -> [1]
读取 3 并自动推入数组 -> [1,3]

示例 2:

输入:target = [1,2,3], n = 3
输出:["Push","Push","Push"]

示例 3:

输入:target = [1,2], n = 4
输出:["Push","Push"]
解释:只需要读取前 2 个数字就可以停止。

提示:

  • 1 <= target.length <= 100
  • 1 <= target[i] <= 100
  • 1 <= n <= 100
  • target 是严格递增的
class Solution {
public:
//正常判断是否需要在target数组中存储,同时如果足够了即可break
vector<string> buildArray(vector<int>& target, int n) {
vector<string>v;
int len = target.size();
int j = 0;
for(int i = 1;i <=n ;++i){
if(j == len)break;
if(i == target[j]){
v.push_back("Push");
++j;
}
else{
v.push_back("Push");
v.push_back("Pop");
}
}
return v;
}
};



[B题](https://leetcode-cn.com/problems/count-triplets-that-can-form-two-arrays-of-equal-xor/)

给你一个整数数组 arr 。

现需要从数组中取三个下标 i、j 和 k ,其中 (0 <= i < j <= k < arr.length) 。

a 和 b 定义如下:

  • a = arr[i] ^ arr[i + 1] ^ ... ^ arr[j - 1]
  • b = arr[j] ^ arr[j + 1] ^ ... ^ arr[k]

注意:^ 表示 按位异或 操作。

请返回能够令 a == b 成立的三元组$ (i, j , k)$ 的数目。

示例 1:

输入:arr = [2,3,1,6,7]
输出:4
解释:满足题意的三元组分别是 (0,1,2), (0,2,2), (2,3,4) 以及 (2,4,4)

示例2:

输入:arr = [1,1,1,1,1]
输出:10

示例 3:

输入:arr = [2,3]
输出:0

思路:

arr[i]...arr[j-1]的异或结果可以转化为(arr[0]...arr[j-1])(arr[0]...^arr[i-1]),因为相同的值异或为0,而异或一个0是不影响原结果的。因此事先计算出会用到的异或结果,用数组dp保存。

class Solution {
public:
int countTriplets(vector<int>& a) {
int n = a.size();
vector<int> s(n+1);
for (int i = 1; i <= n; ++ i)
s[i] = s[i-1]^a[i-1];
int ret = 0;
for (int i = 1; i <= n; ++ i)
for (int j = i+1; j <= n; ++ j)
for (int k = j; k <= n; ++ k)
{
if ((s[j-1]^s[i-1]) == (s[k]^s[j-1])) ret ++;
}
return ret;
}
};



[C题](https://leetcode-cn.com/problems/minimum-time-to-collect-all-apples-in-a-tree/)

给你一棵有 n 个节点的无向树,节点编号为 0 到 n-1 ,它们中有一些节点有苹果。通过树上的一条边,需要花费 1 秒钟。你从 节点 0 出发,请你返回最少需要多少秒,可以收集到所有苹果,并回到节点 0 。

无向树的边由 edges 给出,其中 edges[i] = [fromi, toi] ,表示有一条边连接 from 和 toi 。除此以外,还有一个布尔数组 hasApple ,其中 hasApple[i] = true 代表节点 i 有一个苹果,否则,节点 i 没有苹果。

示例 1:

输入:n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,true,true,false]
输出:8
解释:上图展示了给定的树,其中红色节点表示有苹果。一个能收集到所有苹果的最优方案由绿色箭头表示。

示例 2:

输入:n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,false,true,false]
输出:6
解释:上图展示了给定的树,其中红色节点表示有苹果。一个能收集到所有苹果的最优方案由绿色箭头表示。

思路:

只要那个节点是true,向上一直将父节点同化,那么路径就等于:每两个连接(子、父都为true)的点的那条线x 2 后的和

class Solution {
public:
int minTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {
int i,res=0;
//若子节点为true,则父节点同化为true
for(i=edges.size()-1; i>=0; i--)
if(hasApple[edges[i][1]]==true)
hasApple[edges[i][0]]=true;
// 收集苹果的路径即为所有节点为true的拓扑图的所有连线*2
for(i=0; i<edges.size(); i++)
if(hasApple[edges[i][1]]==true) res +=2;
return res;
}
};

D题

给你一个 rows x cols 大小的矩形披萨和一个整数 k ,矩形包含两种字符: 'A' (表示苹果)和 '.' (表示空白格子)。你需要切披萨 k-1 次,得到 k 块披萨并送给别人。

切披萨的每一刀,先要选择是向垂直还是水平方向切,再在矩形的边界上选一个切的位置,将披萨一分为二。如果垂直地切披萨,那么需要把左边的部分送给一个人,如果水平地切,那么需要把上面的部分送给一个人。在切完最后一刀后,需要把剩下来的一块送给最后一个人。

请你返回确保每一块披萨包含 至少 一个苹果的切披萨方案数。由于答案可能是个很大的数字,请你返回它对 10^9 + 7 取余的结果。

示例 1:

输入:pizza = ["A..","AAA","..."], k = 3
输出:3
解释:上图展示了三种切披萨的方案。注意每一块披萨都至少包含一个苹果。

示例 2:

输入:pizza = ["A..","AA.","..."], k = 3
输出:1

示例 3:

输入:pizza = ["A..","A..","..."], k = 1
输出:1
  • 1 <= rows, cols <= 50
  • rows == pizza.length
  • cols == pizza[i].length
  • 1 <= k <= 10
  • pizza 只包含字符 'A' 和 '.' 。

思路:

本题是统计切割方案数,一看就是使用dp,怎么来思考呢?

首先我们考虑存在的状态数:

毫无疑问,披萨被切成k块肯定是状态之一。

而如何表示当前剩余部分的披萨呢?题中说把左边和上边给一个人,可以知道,右下部分总是会剩余下来。

所以可以记录左上角的位置来表示剩余的披萨。

因此一个三维数组可以做为dp数组:dp[i][j][k]

i,j表示披萨剩余部分的左上角,k表示当前披萨被切成k块

初始状态显而易见,由于只有一块,没有切,左上角为(0,0),所以dp[0][0][1]=1

状态转移

知道初始状态后,我们就要开始进行状态转移了~

首先让我们来考虑怎么从一块变成两块

披萨:
A..
AAA
...

由于我们知道可以水平切和垂直切,左上角为(i,j),一刀切下去,可以从k变成k+1

因此,我们可以穷举每个状态水平切和垂直切的所有切法,来得到k+1的状态。

因为每切一次得到的剩余披萨左上角都不同,所以不会出现重复。

首先水平切:

左上角为(0,0),k=1
A.. A..
+++ AAA
AAA +++
... ...
剩余部分:左上角为(1,0),k=2 剩余部分:左上角为(2,0),k=2 (不合理)

有这两种切法,很清楚看出来,第二种切法是不可以的,因为下面那一部分不存在A,不符合题意。

如何判断剩余和切出来的披萨存不存在A,我们先记下这个问题,后面会提到。

所以可以得到水平切的状态转移方程:

记原来的左上角为(i,j),新的左上角为(x,y)
if(两部分都存在A){
dp[x][y][k+1]+=dp[i][j][k]
}

垂直切是和水平切一样的,就不说了。

解决存在A的问题

我们如何判断切开后的两块披萨是否存在A呢?

方法1:直接暴力求解,我不知道会不会超时,我没有试,有兴趣可以写一下。

方法2:利用数学知识,计算出来对应披萨块中A的数量,假如数量大于0,则存在A

方法3:别的方法,假如有人愿意分享更简单的,可以在评论分享,大家一起进步

我使用方法2,所以就写一下方法2:

用数组num[i][j]表示以(0,0)为左上角,(i,j)为右下角的披萨块中包含的A数量

上例中:
num:
1 1 1
2 3 4
2 3 4

怎么计算num数组使用简单的dp和数学知识就可以了,这里就不再赘述。

通过num数组和获得披萨块的左上角和右下角就可以轻易地算出A的个数:

这个大家肯定都会,就举个例子吧,就是简单的数学关系:
例:计算以(1,0)为左上角,(2,2)为右下角的披萨块A数目:
num[2][2]-num[0][2]-num[2][-1]+num[0][-1];
下标中出现-1的num值都用0代替:所以为4-1-0-0=3

看不懂的可以直接看代码如何计算A数目,一看就明白了

#define ll long long int

class Solution {
public: const ll mod=1e9+7;
int ways(vector<string>& pizza, int k) {
int row=pizza.size(),col=pizza[0].length();
//计算num
vector<vector<int>> num(row,vector<int>(col,0));
if(pizza[0][0]=='A') num[0][0]=1;
for(int i=1;i<row;i++) num[i][0]=num[i-1][0]+(pizza[i][0]=='A');
for(int i=1;i<col;i++) num[0][i]=num[0][i-1]+(pizza[0][i]=='A');
for(int i=1;i<row;i++) for(int j=1;j<col;j++)
num[i][j]=num[i-1][j]+num[i][j-1]-num[i-1][j-1]+(pizza[i][j]=='A'); //初始化dp
vector<vector<vector<ll>>> dp(row,vector<vector<ll>>(col,vector<ll>(k+1,0)));
dp[0][0][1]=1; //从k=2开始填充
for(int x=2;x<=k;x++){
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
//dp为0代表不存在这种情况
if(dp[i][j][x-1]==0)
continue;
//穷举水平切
for(int z=i+1;z<row;z++){
if(hasA(num,i,j,z-1,col-1) && hasA(num,z,j,row-1,col-1)){
dp[z][j][x]+=dp[i][j][x-1];
dp[z][j][x]%=mod;
}
}
//穷举垂直切
for(int z=j+1;z<col;z++){
if(hasA(num,i,j,row-1,z-1) && hasA(num,i,z,row-1,col-1)){
dp[i][z][x]+=dp[i][j][x-1];
dp[i][z][x]%=mod;
}
}
}
}
} //计算答案
ll ans=0;
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
ans+=dp[i][j][k];
}
ans%=mod;
}
return ans;
} //计算存在A吗
bool hasA(vector<vector<int>>& num,int sr,int sc,int er,int ec){
int num1=0,num2=0,num3=0,res;
if(sr!=0 && sc!=0) num1=num[sr-1][sc-1];
if(sr!=0) num2=num[sr-1][ec];
if(sc!=0) num3=num[er][sc-1];
return num[er][ec]-num2-num3+num1>0;
}
};

LeetCode #188场周赛题解的更多相关文章

  1. LeetCode--179场周赛题解

    水题: class Solution { public: string generateTheString(int n) { string s; string a="a",b=&q ...

  2. AcWing 第11场周赛题解

    计算abc 首先 \(0<=a<=b<=c\) 会随机给出 \(a+b,a+c,b+c,a+b+c\)的值 因为\(a,b,c\)都为正整数,所以\(a+b+c\)一定为最大值 然后 ...

  3. LeetCode 第 165 场周赛

    LeetCode 第 165 场周赛 5275. 找出井字棋的获胜者 5276. 不浪费原料的汉堡制作方案 5277. 统计全为 1 的正方形子矩阵 5278. 分割回文串 III C 暴力做的,只能 ...

  4. Leetcode第 217 场周赛(思维量比较大)

    Leetcode第 217 场周赛 比赛链接:点这里 做完前两题我就知道今天的竞赛我已经结束了 这场比赛思维量还是比较大的. 1673. 找出最具竞争力的子序列 题目 给你一个整数数组 nums 和一 ...

  5. LeetCode All in One题解汇总(持续更新中...)

    突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...

  6. Leetcode 10. 正则表达式匹配 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  7. C#版 - Leetcode 306. 累加数 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  8. C#版(击败100.00%的提交) - Leetcode 372. 超级次方 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...

  9. C#版(打败97.89%的提交) - Leetcode 202. 快乐数 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

随机推荐

  1. 【MyBatis深入剖析】应用分析与最佳实践

    ##### 文章目标1. 了解ORM框架的发展历史,了解MyBatis特性2. 掌握MyBatis编程式开发方法和核心对象3. 掌握MyBatis核心配置含义4. 掌握MyBatis的高级用法与扩展方 ...

  2. Complete the Sequence HDU - 1121

    题目大意: 输入两个数n和m,n表示有n个数,这n个数是一个多项式的前n项,让输出这个序列的n+1,n+2,..n+m项. 题解:差分规律,一直差分,直到全为0或者只剩下一个数.然后再递推回去. 给出 ...

  3. PHP函数:fwrite

    fwrite()  - 写入文件(可安全用于二进制文件) 说明: fwrite ( resource $handle , string $string [, int $length ] ) : int ...

  4. SpringBoot全局异常处理与定制404页面

    一.错误处理原理分析 使用SpringBoot创建的web项目中,当我们请求的页面不存在(http状态码为404),或者器发生异常(http状态码一般为500)时,SpringBoot就会给我们返回错 ...

  5. Linux下nginx自启动配置

    1.在linux系统的/etc/init.d/目录下创建nginx文件 vim /etc/init.d/nginx 在脚本中添加一下命令(内容主要参考官方文档) #!/bin/sh # # nginx ...

  6. 全网最全最细的fiddler使用教程以及工作原理

    目录:导读 一.Fiddler抓包工具简介 二.Fiddler工作原理 三.Fiddler安装 四.Fiddler界面介绍​ 五.Fiddler菜单栏介绍 六.Fiddler工具栏介绍 七.Fiddl ...

  7. [Java网络安全系列面试题] GET 和 POST 的区别在哪里?

    一. 概述 本文的内容源自其他博客的总结,属于笔者的读书笔记,结构如下: HTTP 的请求报文 GET 方法的特点 POST 方法的特点 GET 和 POST 的区别 二. HTTP 的请求报文 首先 ...

  8. Say goodbye

    Since September 28th 2015 Scriptogram officially closed. We considered every option before making th ...

  9. php的一个有意思的命令:-S

    php -S localhost:8188 /web 会启动一个监控IP:PORT 的http服务,算是简易的web服务器吧.基本上,实现了PHP+MySQL就可以建立一个简易测试网站的环境.

  10. 小程序里json字符串转json对象需注意的地方

    一.JSON字符串转换为JSON对象 要使用上面的str1,必须使用下面的方法先转化为JSON对象: //由JSON字符串转换为JSON对象 var obj = eval('(' + str + ') ...