这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战
1964. 找出到每个位置为止最长的有效障碍赛跑路线
思路分析
题目中要求障碍赛的终点必须大于等于前一个障碍,这不就是不递减子序列么,算出最大长度可以通过前面其他节点作为其答案,所以这是一道十分简单的状态规划,状态转移方程也呼之欲出
其中k代表所有满足obstacies[i] >= obstacies[k]的下标。
vector<int> dp(n, 0);
//vector<int> arr;
dp[0] = 1;
for(int i = 0 ;i < obstacies.size(); i++){
for(int j = 0; j < i; j++){
if(obstacies[i] >= obstacies[j]){
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
return dp[n - 1];
然而这样就会使得时间复杂度变为O(n^2),那么是否有办法剪枝呢?
基于贪心的思路,我们想到,为了使障碍长度最大,也就是子序列长度最大,我们应该尽可能的让子序列的值增长速度缓慢,而增长速度缓慢的另一种表达就是在相同长度下,递增子序列的末尾的值越小越好。
有人可能觉得,为什么只看末尾呢
这是因为在末尾值一定是obstacies[i]的情况下,obstacies[i - 1]一定作为之前的末尾值,参与计算过。
同时我们会发现这个记录i长度递增子序列末尾值数组一定是不严格递增的,假设arr[i] > arr[j] 且i < j。那么arr[j]所代表的递增子序列的的第i个位置x如果大于等于arr[i],那么在x之后的arr[j]更应该大于等于arr[i],如果arr[j]所代表的递增子序列的的第i个位置x小于arr[i],那么arr[i]应该等于x。