文章目录
- 1. 比赛结果
- 2. 题目
- 1. 树木规划
- 2. 正三角形拼接
- 3. 大楼间穿梭
- 4. 对称前后缀
1. 比赛结果
通过了 3 题,第245名,进入复赛了,收获 T恤 一件,哈哈。
2. 题目
1. 树木规划
题目链接
描述
在一条直的马路上,有 n 棵树,每棵树有一个坐标,代表它们距离马路起点的距离。 如果每相邻的两棵树之间的间隔不小于 d,那么我们认为这些树是美观的。 请计算出最少移除多少棵树,可以让这些树变得美观。
树木的棵树为 n,1 <= n <= 10^5
。 树木的坐标用 trees 表示,0 <= trees[i] <= 10^9
。 最小美观间隔为 d,1 <= d <= 10^9
。 保证输入的坐标是排好序的,且两两不相同。
说明
样例中,将位置 2 和 6 的树木移走,剩下 [1, 3, 5] ,它们是美观的。
示例
输入:
[1,2,3,5,6]
2
输出:
2
解题:
- 直接遍历,不满足的移除
class Solution {
public:/*** @param trees: the positions of trees.* @param d: the minimum beautiful interval.* @return: the minimum number of trees to remove to make trees beautiful.*/int treePlanning(vector<int> &trees, int d) {// write your code here.int prev = trees[0], s = 0;for(int i = 1; i < trees.size(); ++i){if(trees[i]-prev < d)//不满足{s++;//移除}else{prev = trees[i];}}return s;}
};
2. 正三角形拼接
题目链接
描述
给出 n 根木棍,每次切割可以将1根木棍切成 2 段。请计算出最少切割几次,可以从所有木棍中选出 3 根,组成一个正三角形。
一开始的木棍根数为 n,3 ≤ n ≤ 1000。所有木棍的长度为一个整型数组 lengths,1 < length_i ≤ 10^9。
切割必须要将木棍分成 2 根整数长度的木棍,而且总长度要和原木棍相等。
说明
可以从长为7的木棍中,切出2根长为3的木棍,那么木棍的长度应该为[2,3,1,3,3,5],可以拼出边长为3的正三角形。
示例
输入:
[2,3,7,5]
输出:
2
解题:
class Solution {
public:/*** @param lengths: the lengths of sticks at the beginning.* @return: return the minimum number of cuts.*/int makeEquilateralTriangle(vector<int> &lengths) {// write your code here.map<int, int> m;int cut = 2;//最多切两次for(int i = 0; i < lengths.size(); i++) m[lengths[i]]++;//长度计数for(auto& mi : m){if(mi.second == 2)//有2段了{if(m.lower_bound(mi.first+1) != m.end())cut = min(cut, 1);//有更长的,切1次}else if(mi.second >= 3)//有3段了,不用切return 0;if(mi.first%2==0 && m.count(mi.first/2))cut = min(cut, 1);//如果能被平均切开,且有1段一样的,切1次就可以}return cut;}
};
3. 大楼间穿梭
题目链接
描述
蜘蛛侠在大楼间穿梭。大楼的高度可以看作是一个从左到右排列的数组。
现在蜘蛛侠站在第一栋大楼上,他想跳到最后一栋上。
- 蜘蛛侠的视野为 k,他可以花费 x 点体力,用蛛丝移动到右侧k幢建筑中第一栋比当前位置高的大楼(
应该是 高或者相同高度,题目有问题
)。 - 或者蜘蛛侠可以花费 y 点体力,跳跃到右侧接下来两栋大楼其中一栋。
请计算蜘蛛侠最少花费多少体力,到达最后一栋上。
大楼的高度为数组 heights,一共有 n 栋大楼,2 ≤ n ≤ 10^5,1 <= heights_i ≤ 10^9
.蜘蛛侠的视野为 k,1 ≤ k ≤ n
。两种行动的体力花费满足 1 ≤ x,y ≤ 10^9
。
说明
样例中,先花费6点体力跳到第三栋建筑,再花费10点到达最后一栋。
示例
输入:
heights=[1,5,4,3,3,5]
k=3
x=10
y=6
输出:
16
解题:
- 单调栈算出右侧高度 >= 当前的 第一个位置(逆序遍历)
- 然后简单的动态规划即可
class Solution {
public:/*** @param heights: the heights of buildings.* @param k: the vision.* @param x: the energy to spend of the first action.* @param y: the energy to spend of the second action.* @return: the minimal energy to spend.*/long long shuttleInBuildings(vector<int> &heights, int k, int x, int y) {// write your code here.int n = heights.size(), i, j, K;stack<int> s;vector<int> rightTall(n, -1);//右侧高或者相等的第一个位置for(int i = n-1; i >= 0; i--) //单调栈{while(!s.empty() && heights[s.top()] < heights[i])//右侧比我小的,没有用s.pop();if(!s.empty() && s.top()-i <= k)//有大于等于我的,且距离在 k 以内rightTall[i] = s.top();//记录下来s.push(i);}vector<long long> dp(n, LONG_LONG_MAX);dp[0] = 0;for(int i = 0; i < n; i++) // DP{if(dp[i] == LONG_LONG_MAX)continue;if(i+1 < n && dp[i+1] > dp[i]+y)//右侧1dp[i+1] = dp[i]+y;if(i+2 < n && dp[i+2] > dp[i]+y)//右侧2dp[i+2] = dp[i]+y;if(rightTall[i] != -1 && dp[rightTall[i]] > dp[i]+x)dp[rightTall[i]] = dp[i]+x;//直接跳到 k 以内的 第一个 >= 我的位置}return dp[n-1];}
};
4. 对称前后缀
题目链接
描述
给定一个字符串 s。我们令一个字符串的权值为一个字符串的最长对称前后缀长度。
请求出 s 的所有子串的权值的总和。
例如,”abcxyzcba”
的最长对称前后缀的长度为3,因为“abc”
和“cba”
对称。
字符串的长度为 n,1 ≤ n ≤ 3*10^3
。字符串均由小写英文字符组成。
说明
样例中,单个字符的子串的权值为1,它们的和为 7。
另外的权值为:
"bacb"->1
,
"bacbdab"->2
,
"bdab"->1
,
"acbda'->1
,
所以权值和为12。
示例
输入:
"bacbdab
输出:
12
解题:
- 区间DP
class Solution {
public:/*** @param s: a string.* @return: return the values of all the intervals.*/long long suffixQuery(string &s) {// write your code herelong long n = s.size(), ans = n;//区间DP,dp[i][j] 表示区间内的 子串的最大权值vector<vector<int>> dp(n, vector<int>(n, 0));for(int i = 0; i < n; i++)dp[i][i] = 1;for(int len = 1, i; len < n; len++){for(i = 0; i+len < n; i++){if(s[i] == s[i+len])//子串首尾相同{int length = len-1;//除去首尾 里面的子串[i+1, i+len-1]的长度if(dp[i+1][i+len-1] == length)// 里面正反序都相同dp[i][i+len] = dp[i+1][i+len-1]+2;//把两个端点都可以加上elsedp[i][i+len] = dp[i+1][i+len-1]+1;//只能加上1端}ans += dp[i][i+len];}}return ans;}
};
我的CSDN博客地址 https://michael.blog.csdn.net/
长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!