https://leetcode-cn.com/contest/weekly-contest-135
移动石子直到连续II
描述
在一个长度无限的数轴上,第 i 颗石子的位置为 stones[i]。如果一颗石子的位置最小/最大,那么该石子被称作端点石子。
每个回合,你可以将一颗端点石子拿起并移动到一个未占用的位置,使得该石子不再是一颗端点石子。
值得注意的是,如果石子像 stones = [1,2,5] 这样,你将无法移动位于位置 5 的端点石子,因为无论将它移动到任何位置(例如 0 或 3),该石子都仍然会是端点石子。
当你无法进行任何移动时,即,这些石子的位置连续时,游戏结束。
要使游戏结束,你可以执行的最小和最大移动次数分别是多少? 以长度为 2 的数组形式返回答案:answer = [minimum_moves, maximum_moves] 。
示例 :
输入:[7,4,9]
输出:[1,2]
解释:
我们可以移动一次,4 -> 8,游戏结束。
或者,我们可以移动两次 9 -> 5,4 -> 6,游戏结束。
思路
这题比之前的难,但是最大值方面 跟之前差不多,也是看中间的空位数,只是多了端点石子移动之后不能还是端点这个要求,需要对两边端点都邻近空位的情况做一些不同的处理。
最小值,虽然代码能通过,但感觉怪怪的,逻辑上好像不对。。。
代码
class Solution {
public:
vector<int> numMovesStonesII(vector<int>& stones) {
int MAXSTONE = 1e9;
// 给石子位置排序
sort(stones.begin(), stones.end());
// 获取石子总数量
int n = stones.size();
int minstep = MAXSTONE, maxstep = -MAXSTONE;
// 最小
for (int i = 0, j = 0; i < n; i++) {
// 找一段能放下n个石子的区域
while (j + 1 < n && stones[j + 1] - stones[i] < n)
j++;
// 看还有多少个石子在区域之外,那么至少要移动那么多次才能将石子都移动到这个区域
int res = n - (j - i + 1);
// 如果这段区域本身就连续并且还剩一个在外面,并且这个落单的和连续的隔着不止一个空位,则需要再动一次
if (res==1 && stones[j] - stones[i] == j - i && ((j+1<n && (stones[j+1] - stones[j])>2) || ((i>0 && (stones[i] - stones[i-1])>2))))
res++;
minstep = min(minstep, res);
}
// 最大
maxstep = max(stones[n - 1] - stones[1], stones[n - 2] - stones[0]) - (n - 2);
return {minstep, maxstep};
}
};
多边形三角剖分的最低得分
描述
给定 N,想象一个凸 N 边多边形,其顶点按顺时针顺序依次标记为 A[0], A[i], …, A[N-1]。
假设您将多边形剖分为 N-2 个三角形。对于每个三角形,该三角形的值是顶点标记的乘积,三角剖分的分数是进行三角剖分后所有 N-2 个三角形的值之和。
返回多边形进行三角剖分后可以得到的最低分。
示例 :
输入:[3,7,4,5]
输出:144
解释:有两种三角剖分,可能得分分别为:375 + 457 = 245,或 345 + 347 = 144。最低分数为 144。
思路
本来是想用贪心来解的,尝试了几次,发现好像没办法做到。动态规划依旧不熟悉,先看别人的学习一下。
看了别人解答之后的代码
class Solution {
public:
void mst(int i, int j, vector<int>& A, int dp[51][51]) {
// 如果只剩两个点,则值为0
if (j - i == 1) {
dp[i][j] = 0;
return;
}
// 剩三个点,直接相乘
if (j - i == 2) {
dp[i][j] = A[i]*A[i+1]*A[j];
return;
}
int min = 1e9;
//开始以A[start] A[end]为底边分割
for(int top = i+1;top<j;++top){
if(dp[i][top] == -1){
mst(i,top,A,dp);
}
int mid = A[i]*A[top]*A[j];
if(dp[top][j] == -1){
mst(top,j,A,dp);
}
min = min<(dp[i][top]+mid+dp[top][j])?min:(dp[i][top]+mid+dp[top][j]);
}
dp[i][j] = min;
}
int minScoreTriangulation(vector<int>& A) {
int dp[51][51];
memset(dp, -1, sizeof(dp));
int n = A.size();
mst(0, n-1, A, dp);
return dp[0][n-1];
}
};
PS.参考的java版解答原文见 https://blog.youkuaiyun.com/weixin_36451489/article/details/89950753