1.树木规划
贪心即可,最左边第一个不移动,如果之和一个与之前间隔小于d,就移除掉。
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.
*/
bool check(vector<int> trees,int a,int d)
{
int ss=0;
int last=-1000000000,tmp;
for(int i=0;i<trees.size();++i)
{
tmp=trees[i];
if(tmp-last>=d)
last=tmp;
else
{
ss++;
if(ss>a)
return false;
}
}
return true;
}
int treePlanning(vector<int> &trees, int d) {
// write your code here.
int l,r,mid;
l=0,r=trees.size()-1;
int ans=1000000000;
while(l<=r)
{
mid=(l+r)>>1;
if(check(trees,mid,d))
{
ans=min(ans,mid);
r=mid-1;
}
else
l=mid+1;
}
return ans;
}
};
2.正三角形拼接
因为n>=3,所以只有答案只有可能是0,1,2。如果此时已经有三个一样的,就是0,如果此时有两个一样的,如果还有一个比一样的这个要大,那么就是1,如果现在一个可以分成两个一样的,并且此时场上还有一个一样的,也是1,其它情况都是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>mp;
int a[1001];
int b[1001];
int cnt1=0;
int cnt2=0;
for(int i=0;i<lengths.size();++i)
{
mp[lengths[i]]++;
if(mp[lengths[i]]==3)
return 0;
}
for(int i=0;i<lengths.size();++i)
{
if(mp[lengths[i]]==1)
a[++cnt1]=lengths[i];
if(mp[lengths[i]]==2)
b[++cnt2]=lengths[i];
}
sort(a+1,a+1+cnt1);
sort(b+1,b+1+cnt2);
sort(lengths.begin(),lengths.end(),greater<int>());
for(int i=1;i<=cnt2;++i)
for(int j=0;j<lengths.size();++j)
{
if(lengths[j]>b[i])
return 1;
else
break;
}
for(int i=1;i<=cnt1;++i)
{
for(int j=0;j<lengths.size();++j)
{
if(lengths[j]>a[i])
{
if(lengths[j]==a[i]*2)
return 1;
}
else
break;
}
}
return 2;
}
};
3.大楼间穿梭
求右边第一个大于它的,是经典的单调栈模型,预处理完之后,再dp。dp[i]表示到第i个楼的最小消耗体力。就是通过两种方式转移dp[l[i]]=min(dp[l[i]],dp[i]+x),dp[i+2]=min(dp[i+2],dp[i]+y),dp[i+1]=min(dp[i+1],dp[i]+y),最后输出dp[n]即可.
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 stc[100005];
int l[100005];
long long dp[100005];
memset(stc,0,sizeof(stc));
memset(l,-1,sizeof(l));
int h=0;
int n=heights.size();
stc[++h]=n;
l[n]=-1;
for(int i=n-1;i>=1;i--)
{
bool flag=0;
while(h)
{
if(stc[h]-i>k)
break;
else
if(heights[i-1]>heights[stc[h]-1])
{
h--;
}
else
{
l[i]=stc[h];
flag=1;
break;
}
}
if(!flag)
l[i]=-1;
stc[++h]=i;
}
for(int i=1;i<=n;++i)
dp[i]=1e15;
dp[1]=0;
for(int i=1;i<n;++i)
{
if(l[i]!=-1)
dp[l[i]]=min(dp[l[i]],dp[i]+x);
if(i<=n-2)
{
dp[i+1]=min(dp[i+1],dp[i]+y);
dp[i+2]=min(dp[i+2],dp[i]+y);
}
if(i<=n-1)
dp[i+1]=min(dp[i+1],dp[i]+y);
}
return dp[n];
}
};
4.对称前后缀
可以暴力,我们枚举中间元素为起点,向外扩,更新答案。我们发现,只有aba,abba这两种状态,其它状态都可以在扩的过程中出现。所以枚举,以i为中心,或者以i,i+1为中心,像两边扩。如果两边相等,长度+1,如果此时是回文串,那么就贡献子串的长度。
class Solution {
public:
/**
* @param s: a string.
* @return: return the values of all the intervals.
*/
long long suffixQuery(string &s) {
// write your code here
int len=s.length();
long long ans=0;
for(int i=0;i<len;++i)
{
ans++;
int l=i-1;
int r=i+1;
int length=0;
while(l>=0&&r<=len-1)
{
int d=r-l+1;
if(s[l]==s[r])
{
length++;
if(d==2*length+1)
ans+=d;
else
ans+=length;
}
else
length=0;
l--;
r++;
}
if(i+1<len)
{
length=0;
if(s[i]==s[i+1])
{
ans+=2;
length=1;
}
l=i-1;
r=i+2;
while(l>=0&&r<=len-1)
{
int d=r-l+1;
if(s[l]==s[r])
{
length++;
if(d==2*length)
ans+=d;
else
ans+=length;
}
else
length=0;
l--;
r++;
}
}
}
return ans;
}
};