若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值
若它的右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值
它的左、右子树也分别为二叉搜索树
二叉搜索树的中序遍历是一个有序的序列
此题就变为已知中序遍历和前序遍历 建树
最为重要的一点就是题目没有保证元素不重复
原BST树取所有相同值的第一个
镜像BST树取所有相同值的最后一个
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1010;
int n;
int pre[N] , in[N];
vector<int>post;
bool build(int pl , int pr , int il , int ir , int type)
{
if(il > ir) return true;
int k = pre[pl];
int j;
if(!type)
{
j = il;
while(j <= ir && in[j] != k) j ++;
if(j > ir) return false;
}
else
{
// 右子树
j = ir;
while(j >= il && in[j] != k) j --;
if(j < il) return false;
}
if(!build(pl + 1 , j - il + pl , il , j - 1 , type)) return false;
if(!build(pr - ir + j + 1 , pr , j + 1 , ir , type)) return false;
post.push_back(k);
return true;
}
int main()
{
cin >> n;
for(int i = 0;i < n;i ++) cin >> pre[i] , in[i] = pre[i];
sort(in , in + n);
bool f = build(0 , n - 1 , 0 , n - 1 , 0);
if(f) puts("YES");
else
{
post.clear();
reverse(in , in + n);
f = build(0 , n - 1 , 0 , n - 1 , 1);
if(f) puts("YES");
else puts("NO");
}
if(f)
{
for(int i = 0;i < post.size();i ++)
{
if(i) cout << " ";
cout << post[i];
}
}
return 0;
}
双指针算法
//可以使用双指针法解决问题
#include<iostream>
#include<vector>
using namespace std;
const int N = 1e5 + 10;
int n,m;
vector<int>v(N);
vector< pair<int,int> >res;
int min_num = 0x3f3f3f3f;
void cal_qu()
{
int sum = 0;
//i向右移移动sum值变小
//j向右移动sum值变大
for(int i = 0,j = 0 , sum = 0;j < n || sum >= m;)
{
if(sum > m)//在i到j的区间内的和大于给定的值
{
min_num = min(sum,min_num);
//更新sum并且将i指针向右移动
sum -= v[i++];
}
else if(sum < m)//在i到j的区间内的和小于给定的值
{
//更新sum并且将j指针向右移动
sum += v[j++];
}
else//在i到j的区间内的和等于给定的值
{
//存入结果中
//注意起始坐标是从1开始的
res.push_back({i+1,j});
//更新sum并且将i指针向右移动
sum -= v[i++];
}
}
}
void print()
{
for(int i=0;i<res.size();i++)
{
cout<<res[i].first<<"-"<<res[i].second<<endl;
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>v[i];
cal_qu();
print();
if(!res.size())
{//表示没有一个结果等于原先的m
//更新m重新进行计算
m = min_num;
cal_qu();
print();
}
}