leetcode6080
lao里人,每天都坐lao,每天都坐lao,花光所有时间用来看题解。
先看题解的做法:
int q[100010],top,c[100010]; class Solution { public: int totalSteps(vector<int>& nums) { top=0,c[top]=0; for(int y:nums) { while(top&&q[top]<=y) top>1?c[top-1]++:0,c[top-1]=max(c[top-1],c[top]),--top; q[++top]=y,c[top]=0; } while(top) top>1?c[top-1]++:0,c[top-1]=max(c[top-1],c[top]),--top; return c[0]; } };
我对题解的理解:
首先,这做法为什么是正确的,假设有(10,1,9,6,7,8),答案是3
如果直接认为以10为头,然后依次去除后面比10小的数,那么答案是5,显然不对,因为9会与10同时去除。1去掉的同时6会去掉。
模拟的话是
1:10,9,7,8
2:10,8
3:10
8是被10去掉的,如果8是被9去掉的,那么9去掉(6,7,8)而10去掉(1,9)之后取max答案为什么是正确的呢?
8不管是被9,还是10移除,都是最后一段。如果10去除9的时候,8已经被9去除了,那么8不能被10去除。如果10去除9的时候,8还在,那时10和9的答案大小都是一样的,那么不管是在9或10后面移除,答案都一样。
因此该问题可以分为更多相同子问题。
如10找第一个小的,如10去除(1)的时候,1一个都不能去除,那么10再次去除(9)的时候,10已经去除了(1,9)值为2,而9去除了(6,7,8)值为3,答案即为max(2,3)=3
那么设置一个c数组,表示的是从i节点出发,可以去除的值是多大。上面c[节点=9]=3。
那么,可不可以用递归去做?事实上,递归就是用栈实现的。
那么为什么单调递减栈可以实现?
首先是先找一个比他小的,如10找了1,所以1进栈。之后再找了9,为什么1要出栈?因为1不能去除9,所以1和9不相干,
所以C[节点为10]=max(c[节点为1],c[节点为9],c[节点为10])
如[6,3,4,5,9,8,7],最后栈会是(9,8,7)。答案会保存在C[0]中,注意的就是0不能去除任何一个数,因此6去除的是(3,4,5)为3次,而9去除的是(8,7)为1次,答案即为3
实际上就是要把子序列合并,说起子序列合并,又与线段树有关。线段树能做吗?
对线段树的理解不深刻,所以觉得实现起来很难。题解中,有提了一口单调栈+线段树的做法,用线段树维护区间值,之后再不断向上更新?这种做法与单调递减栈什么区别呢?单调递减栈是把区间值堆在一起,然后更新区间值,一旦出栈后面的数就与之无关了。而用线段树可以维持数据,但是实现难度大?
分割线----------
下面分析我错误思路。
第一次:
class Solution { public: int totalSteps(vector<int>& nums) { int n=nums.size(); int mx=0; int ans=0; int f=-1; for(int i=0;i<n;++i) { if(nums[i]>=mx) { mx=nums[i]; ans=max(ans,i-f-1); f=i; } } return ans; } };
这求的是找到更大的值时,区间按从小到大排的,中间突然波折了一下就错误了。
第二次:
class Solution { public: int totalSteps(vector<int>& nums) { int n=nums.size(); int mx=nums[0]; int ans=0; int f=0; int wei=0; int flag=0; for(int i=1;i<n;++i) { if(nums[i]<nums[i-1]) { flag=1; f=1; mx=nums[i-1]; flag=1; } if(nums[i]>=nums[i-1]&&nums[i]<mx) { if(flag)f++; } // cout<<nums[i]<<" "<<f<<endl; ans=max(ans,f); if(nums[i]>=mx) { f=0; mx=nums[i]; flag=0; } } return ans; } };
在上一次错误样例改的,这回学乖了,算的是递增的长度,又是找到更大的数之前,逢增的就算他可以增几次,中间有递减就重新算
分析下其他人的:
class Solution { public: int getlen(vector<int>& arr) { if(arr.size() == 1) return 1; stack<pair<int, int>> s; int time = 1; for(auto a : arr) { if(s.size() == 0) s.push({a, time}); else { int tmp = 0; while(!s.empty() && s.top().first <= a) { tmp = max(tmp, s.top().second); s.pop(); } s.push({a, tmp+1}); time = max(time, tmp+1); } } return time; } int totalSteps(vector<int>& nums) { int n = nums.size(); int ans = 0, last = nums[0]; vector<int> arr; for(int i = 1; i < n; i++) { if(nums[i] >= last) { if(arr.size()) ans = max(ans, getlen(arr)); arr = {}; last = nums[i]; } else arr.push_back(nums[i]); } if(arr.size()) ans = max(ans, getlen(arr)); return ans; } };
这代码就是把[6,3,4,5,9,8,7]这个,分为[6,3,4,5]和[9,8,7]分开计算。然后用ans维护最大值,也是用单调栈,实际上是一样的。

浙公网安备 33010602011771号