Leetcode 第135场周赛解题报告
这周比赛的题目很有特点。几道题都需要找到一定的技巧才能巧妙解决,和以往靠数据结构的题目不太一样。
就是如果懂原理,代码会很简单,如果暴力做,也能做出来,但是十分容易出错。
第四题还挺难想的,想了好久才想明白。这次先讲第四题,然后再讲其他的题目。
下面是详细的题解和思考。
比赛的地址 Weekly Contest 135
https://leetcode-cn.com/contest/weekly-contest-135
移动石子直到连续 II
题目:移动石子直到连续 II(Moving Stones Until Consecutive II)
地址:
https://leetcode-cn.com/contest/weekly-contest-135/problems/moving-stones-until-consecutive-ii/
题意:
在数轴上摆放了n个石子,石子位置都是整数,并且不能重叠。游戏规则是:每个回合,将一颗端点石子拿起并移动到一个未占用的位置,使得该石子不再是一颗端点石子。无法移动时游戏停止。
问最小和最大移动次数分别是多少。
思路:
题目是上周第一题的扩展,但是有点不同。
由题意可知,每进行一轮操作,石子的左右端点的距离会缩短,一轮一轮收敛。最后会石子都紧邻游戏结束。
举个例子:
初始时有8颗石子,在数轴上的有石子的刻度为:
4,6,8,9,15,16,19,20
最大值求解方法:
石子可以放置的空间,等于左右两端石子之间的未占用位置。在例子中,一共有20-4+1-8个位置。
石子覆盖的线段长度是20-4个,加上一个端点的位置即20-4+1,再减去已经占用的8个位置。
用公式表示为
s1=stones[n-1]-stones[0]+1-n
。
但是第一次移动的左端点或右端点的石子后,这个移动的石子和它相邻的那颗石子之间的空间,后面就不能被放置了,因为与他相邻的那个点变为端点,他们之间的位置不可以被放置了。
例如第一步移动了4,那么5这个位置就不可能放置石子了。所以要计算不能被访问的空间
s2=min(stones[n-1]-stones[n-2]-1, stones[1]-stones[0] -1)
。
最大值为s1-s2
。因为在后面的步骤里,我们都可以做出策略,让每一轮左右端点的差值只减1。
最小值求解方法:
如果最后游戏结束,那么一定有n个连续坐标摆满了石子。如果我们要移动最少,必定要找一个石子序列,使得在n大小连续的坐标内,初始时有最多的石子。
设想有个尺子,上面有n个刻度点,我们用这个尺子在石子从最左边到最右边移动,每动一次都查看下在尺子范围内有m个石子,那么要使这个区间填满,就需要移动n-m次。
只要在尺子外部有石子,就有策略填满尺子内的。
这些次数中最小的就为虽少次数。
但是有一种特例:
1,2,3,4,7
这种1-4是最好的序列,但是7不能移动到端点,只能1先移动到6,然后7移动到5解决,这种情况要用2步。就是尺子内的石子都是连续的,中间没空洞,只在边上有空,要用2次。
代码:
class Solution {
public:
vector<int> numMovesStonesII(vector<int>& stones) {
sort(stones.begin(),stones.end());
int n = stones.size();
int mx = stones[n - 1] - stones[0] + 1 - n;
mx -= min(stones[n-1]-stones[n-2] - 1, stones[1]-stones[0] -1);
int mi = mx;
int i = 0;
int j = 0;
for(i = 0; i < n; ++i)
{
while(j + 1 < n && stones[j + 1] - stones[i] + 1 <= n)
++j;
int cost = n - (j - i + 1);
if(j - i + 1 == n - 1 && stones[j] - stones[i] + 1 == n - 1)
cost = 2;
mi = min(mi, cost);
}
return vector<int>{mi, mx};
}
};
有效的回旋镖
题目:有效的回旋镖(Valid Boomerang)
地址:
https://leetcode-cn.com/contest/weekly-contest-135/problems/valid-boomerang/
题意:
回旋镖定义为一组三个点,这些点各不相同且不在一条直线上。
给出平面上三个点组成的列表,判断这些点是否可以构成回旋镖。
思路:
题目说是回旋镖,其实就是三角形。只要能判断三点不共线就可以。
方法一:简单的想法可以用斜率和截距的方法,判断三点共线。
缺点:要用到除法,可能有精度问题,而且要考虑和坐标轴平行的特殊情况。
方法二:利用三角形变长的性质,两边之和大于第三边。
缺点:也存在用开方的操作,可能有精度问题。
方法三:最优的方法。利用向量叉积。因为a×b=|a|.|b|sinθ。如果共线sinθ为0。
向量叉积后还是的向量,这个向量的长度是两个向量所组成平行四边形的面积。如果共线,这个值为0。
具体可以参考维基百科:
https://zh.wikipedia.org/wiki/叉积
代码:
class Solution {
public:
bool isBoomerang(vector<vector<int>>& points) {
int x1=points[0][0],y1=points[0][1];
int x2=points[1][0],y2=points[1][1];
int x3=points[2][0],y3=points[2][1];
int cross = (y3-y1)*(x2-x1) - (y2-y1)*(x3-x1);
return cross != 0;
}
};
从二叉搜索树到更大和树
题目:
从二叉搜索树到更大和树(Binary Search Tree to Greater Sum Tree)
地址:
https://leetcode-cn.com/contest/weekly-contest-135/problems/binary-search-tree-to-greater-sum-tree/
题意:
修改树的每个节点的值,为访问的所有节点的和,包括当前节点。
访问的次序是先访问右子树,再访问根节点,再访问左子树。
思路:
代码比较简单,递归实现。
代码:
class Solution {
public:
int ans = 0;
TreeNode* bstToGst(TreeNode* root) {
if(root==nullptr)
return root;
bstToGst(root->right);
ans+=root->val;
root->val=ans;
bstToGst(root->left);
return root;
}
};
多边形三角剖分的最低得分
题目:多边形三角剖分的最低得分(Minimum Score Triangulation of Polygon)
地址:
https://leetcode-cn.com/contest/weekly-contest-135/problems/minimum-score-triangulation-of-polygon/
题意:
想象一个凸 N 边多边形,其顶点按顺时针顺序依次标记为 A[0], A[i], ..., A[N-1]。
假设您将多边形剖分为 N-2 个三角形。对于每个三角形,该三角形的值是顶点标记的乘积,三角剖分的分数是进行三角剖分后所有 N-2 个三角形的值之和。
返回多边形进行三角剖分后可以得到的最低分。
思路:
选定凸多边形的一条边为底(A[0]A[N-1]组成的线段),和A[i]为顶点,可以把凸多边形分为三部分,左侧A[0]A[1]...A[i]组成的凸多边形,右侧A[i]A[i+1]...A[N-1]组成的凸多边形,还有A[0]A[i]A[N-1]组成的三角形。
两个凸多边形还可以再递归分解,最后比较出最优解。递归算过的形状不用重复计算,可以用记忆化搜索,记录中间结果。
如果凸多边形只有两个点,那么组成不了三角形,可以直接返回权值为0。
递推公式为:
设w(i,k,j)为i,j,k三个点组成的三角形的权值。
v[i][j]=0
(当i+1==j时)
v[i][j]=v[i][k]+v[k][j]+w(i,k,j)
(当i + 1 < j时, i < k < j)
代码:
class Solution {
public:
int memo[51][51]={0};
inline int w(int i, int j, int k, vector<int>& A)
{
return A[i]*A[j]*A[k];
}
int dfs(int i, int j, vector<int>& A)
{
if(i==j-1)
return 0;
if(memo[i][j]!=0)
return memo[i][j];
memo[i][j]=INT_MAX;
for(int k = i+1; k < j; ++k)
{
int ans = dfs(i, k, A) + w(i, k, j, A) + dfs(k, j, A);
memo[i][j] = min(ans, memo[i][j]);
}
return memo[i][j];
}
int minScoreTriangulation(vector<int>& A) {
int n = A.size();
return dfs(0, n-1, A);
}
};
Leetcode 第135场周赛解题报告的更多相关文章
- Leetcode 第133场周赛解题报告
今天参加了leetcode的周赛,算法比赛,要求速度比较快.有思路就立马启动,不会纠结是否有更好的方法或代码可读性.只要在算法复杂度数量级内,基本上是怎么实现快速就怎么来了. 比赛时先看的第二题,一看 ...
- Leetcode 第137场周赛解题报告
今天的比赛的题目相对来说比较「直白」,不像前几周都是一些特定的算法,如果你没学过不可能想出来. 做了这些周,对leetcode比赛的题目也发现了一些「规律」. 一般前两道题都很「简单」,只要有想法,直 ...
- Leetcode 第136场周赛解题报告
周日的比赛的时候正在外面办事,没有参加.赛后看了下题目,几道题除了表面要考的内容,还是有些能发散扩展的地方. 做题目不是最终目的,通过做题发现知识盲区,去研究学习,才能不断提高. 理论和实际是有关系的 ...
- LeetCode 2 Add Two Sum 解题报告
LeetCode 2 Add Two Sum 解题报告 LeetCode第二题 Add Two Sum 首先我们看题目要求: You are given two linked lists repres ...
- LeetCode 第 165 场周赛
LeetCode 第 165 场周赛 5275. 找出井字棋的获胜者 5276. 不浪费原料的汉堡制作方案 5277. 统计全为 1 的正方形子矩阵 5278. 分割回文串 III C 暴力做的,只能 ...
- Leetcode第 217 场周赛(思维量比较大)
Leetcode第 217 场周赛 比赛链接:点这里 做完前两题我就知道今天的竞赛我已经结束了 这场比赛思维量还是比较大的. 1673. 找出最具竞争力的子序列 题目 给你一个整数数组 nums 和一 ...
- 【LeetCode】376. Wiggle Subsequence 解题报告(Python)
[LeetCode]376. Wiggle Subsequence 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.c ...
- 【LeetCode】649. Dota2 Senate 解题报告(Python)
[LeetCode]649. Dota2 Senate 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地 ...
- 【LeetCode】911. Online Election 解题报告(Python)
[LeetCode]911. Online Election 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ ...
随机推荐
- Kubernetes configMap(配置文件存储)
Kubernetes configMap(配置文件存储) 官方文档:https://kubernetes.io/docs/tasks/configure-pod-container/configure ...
- F#周报2019年第18期
新闻 FableConf 2019开始征集提案 2019理事会选举 如同DSL一般的Elmish封装器fable-elmish,可以创建控制台或者终端界面 介绍VS Code的远程开发 F#(.NET ...
- 【转】测试开发工程师必备软硬能力&高级测试开发工程师需要具备什么能力?
对于测试的基本知识,可以查看软件测试相关书籍 对于在公司成为一位优秀的测试开发工程师,我觉得下面这篇文章涉及到的是我们需要的,稍微进行改动https://blog.csdn.net/sinat_210 ...
- LinuxShell——特殊符号
LinuxShell——特殊符号 摘要:本文主要学习了Shell命令中具有特殊功能的一些符号. 多命令执行 顺序执行“;” 如果使用“;”连接多条命令,那么这些命令会依次执行,但是各命令之间没有任何逻 ...
- python 使用turtule绘制递归图形(螺旋、二叉树、谢尔宾斯基三角形)
插图工具使用Python内置的turtle模块,为什么叫这个turtle乌龟这个名字呢,可以这样理解,创建一个乌龟,乌龟能前进.后退.左转.右转,乌龟的尾巴朝下,它移动时就会画一条线.并且为了增加乌龟 ...
- 9.为什么要进行系统拆分?如何进行系统拆分?拆分后不用 dubbo 可以吗?
作者:中华石杉 面试题 为什么要进行系统拆分?如何进行系统拆分?拆分后不用 dubbo 可以吗? 面试官心理分析 从这个问题开始就进行分布式系统环节了,现在出去面试分布式都成标配了,没有哪个公司不问问 ...
- redis高并发总结
Redis是单线程的,省去了很多上下文切换线程的时间:(官方答案:因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽.既然单线程容易实现, ...
- mysql主从配置步骤
主服务器配置: 1)登陆MySQL数据库 mysql>mysql -uroot -p123 2)给从服务器设置授权用户 mysql>grant all slave on *.* to us ...
- javascript加载XML字符串或文件
1. 加载XML文件 方法1:ajax方式.代码如下: var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObje ...
- 201871010106-丁宣元 《面向对象程序设计(java)》第七周学习总结
201871010106-丁宣元 <面向对象程序设计(java)>第七周学习总结 正文开头: 项目 内容 这个作业属于哪个课程 https://home.cnblogs.com/u/nwn ...