整理字符串 | 找出第N个二进制字符串中的第K位 | 和为目标值的最大数目不重叠非空子数组数目 | 切棍子的最小成本 |
---|---|---|---|
3分 简单 | 4分 中等 | 6分 中等 | 7分 困难 |
√ | √ | √ | √ |
用栈维护,类似于合法括号的抵消
枚举字符串s,与栈顶元素比较,符合条件的就弹出栈顶
否则加入栈顶
O(n)
4ms
6.5MB
class Solution { public: string makeGood(string s) { stackst; for(int i=0;i ='a'&&x1<='z')?(x1-'a'):(x1-'A'); int f2=(x2>='a'&&x2<='z')?(x2-'a'):(x2-'A'); if(x1!=x2&&f1==f2){ st.pop(); } else st.push(x2); } } string ans=""; while(!st.empty()){ ans+=st.top(); st.pop(); } reverse(ans.begin(),ans.end()); return ans; } };
按题意模拟出第n个字符串 s 即可
292 ms
74.8 MB
class Solution { public: char findKthBit(int n, int k) { string s="0"; for(int i=2;i<=n;i++){ string tmp=s; for(auto& it:tmp){ if(it=='1') it='0'; else it='1'; } reverse(tmp.begin(),tmp.end()); s=s+"1"+tmp; } return s[k-1]; } };
贪心的想,从最左边开始,一旦找到一个和为目标值的非空子数组,就选择这一组非空子数组
用前缀和的思想找和为target的子数组,mp[i]记录前缀和为i的最右位置, l 表示可选元素的最左边界,若当前位置为i,以i为右端点且和为target的子数组存在,那么选择这个子数组,l=i+1,我们不能在选择 l 之前的元素了
num是当前的前缀和,若num-target在mp中存在,说明,mp[num-target]+1~i 这一段是和为target的子数组 另外,还要满足mp[num-target]+1>=l if(mp.find(num-target)!=mp.end()){ if(mp[num-target]+1>=l){ l=i+1; ans++; } }
O(nlogn)
824 ms
86.7MB
class Solution { public: int maxNonOverlapping(vector& nums, int target) { int l=0; int n=nums.size(); int num=0; map mp; mp[0]=-1; int ans=0; for(int i=0;i =l){ l=i+1; ans++; } } mp[num]=i; } return ans; } };
这道题使把棍子从1份,切到m份
而动态规划中的石子归并是最开始m堆,合并成1堆的最小花费,所以我们只要转换一下,这道题就是石子归并的模板题。
转化过程:
先从小到大sort一遍,然后与前一个元素做差就是新的石子的大小,注意特判下第一个和最后一个石子
sort(cuts.begin(),cuts.end()); int m=cuts.size()+1; for(int i=1;i<=m;i++) { if(i==1) a[i]=cuts[0]; else if(i==m) a[i]=n-cuts[i-2]; else a[i]=cuts[i-1]-cuts[i-2]; sum[i]=sum[i-1]+a[i]; }
动态规划转移方程
dp[i][j]
表示合并第i堆到第j堆的最小花费
第一维:从小到大枚举合并的长度len
第二维: i 为区间左端点,j为区间右端点
第三维: 该区间原本是两份石子,现在要合并到一份石子,枚举左边一份石子的右端点s
dp[i][j]=min(dp[i][j],dp[i][s]+dp[s+1][j]+sum[j]-sum[i-1]);
for(int len=1;len
复杂度
O(N^3)
执行用时
116 ms
内存消耗
22.1 MB
class Solution { public: int minCost(int n, vector& cuts) { sort(cuts.begin(),cuts.end()); int m=cuts.size()+1; vector a(150,0); vector sum(150,0); vector >dp(150,vector (150,0)); int INF=0x3f3f3f3f; for(int i=1;i<=m;i++) { if(i==1) a[i]=cuts[0]; else if(i==m) a[i]=n-cuts[i-2]; else a[i]=cuts[i-1]-cuts[i-2]; sum[i]=sum[i-1]+a[i]; } for(int len=1;len