面试题:在数组里查找这样的数,它大于(等于)左侧所有数,小于(等于)右侧所有数
Posted 夏夕空~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试题:在数组里查找这样的数,它大于(等于)左侧所有数,小于(等于)右侧所有数相关的知识,希望对你有一定的参考价值。
方法一
- 从左向右遍历一遍,得到数组
left_max
,left_max[i]
表示原数组nums
中第i
个元素左边(不包括nums[i]
)的最大值。 - 从右往左遍历一遍,得到数组
right_min
,right_min[i]
表示原数组nums
中第i
个元素右边(不包括nums[i]
)的最小值。 - 从左向右遍历,判断
nums[i]
与left_max[i]
,right_min[i]
的大小关系。
方法二
事实上,上面的第一次遍历可以合并进最后一次遍历中,且只需要用一个变量left_max
表示当前元素左边的最大值即可,这样只需要遍历两遍。
- 从右往左遍历一遍,得到数组
right_min
,right_min[i]
表示原数组nums
中第i
个元素右边(不包括nums[i]
)的最小值。
从左向右遍历,判断nums[i]
与left_max
,right_min[i]
的大小关系,并更新left_max
。
需要注意的几个地方
- 左右端点元素是否考虑
- 注意大小关系是>/<还是≥/≤
left_max[i]
表示原数组nums
中第i
个元素左边(不包括nums[i]
)的最大值。right_min[i]
表示原数组nums
中第i
个元素右边(不包括nums[i]
)的最小值。
若包括的话,有可能
nums[i]
会覆盖掉其左右两边的最大/最小值的信息,建议不包括。
C++代码
#include<iostream>
#include<vector>
using namespace std;
void printVec(const vector<int> nums){
for(auto num:nums)
cout<<num<<" ";
cout<<endl;
}
vector<int> leftMax(const vector<int> nums){
int n=nums.size();
vector<int> left_max(n, 0x80000000);
for(int i=1;i<n;i++){
left_max[i]=max(left_max[i-1], nums[i-1]);
}
return left_max;
}
vector<int> rightMin(const vector<int> nums){
int n=nums.size();
vector<int> right_min(n, 0x7FFFFFFF);
for(int i=n-2;i>=0;i--){
right_min[i]=min(right_min[i+1], nums[i+1]);
}
return right_min;
}
vector<int> findNum1(const vector<int> nums, bool end=false){
vector<int> res;
int n=nums.size();
vector<int> left_max=leftMax(nums);
vector<int> right_min=rightMin(nums);
if(end){
//考虑两个端点的情况
for(int i=0;i<n;i++){
//注意是>/<还是≥/≤
if(nums[i]>=left_max[i]&&nums[i]<=right_min[i]){
res.emplace_back(nums[i]);
}
}
}
else{
//不考虑两个端点的情况
for(int i=1;i<n-1;i++){
//注意是>/<还是≥/≤
if(nums[i]>=left_max[i]&&nums[i]<=right_min[i]){
res.emplace_back(nums[i]);
}
}
}
return res;
}
//left_min在向右遍历过程中便可实时更新,不需要用数组保存
vector<int> findNum2(const vector<int> nums, bool end=false){
vector<int> res;
int n=nums.size();
if(!n) return res;
vector<int> right_min=rightMin(nums);
if(end){
//考虑两个端点的情况
int left_max=0x80000000;
for(int i=0;i<n;i++){
//注意是>/<还是≥/≤
if(nums[i]>=left_max&&nums[i]<=right_min[i]){
res.emplace_back(nums[i]);
}
left_max=max(left_max, nums[i]);
}
}
else{
//不考虑两个端点的情况
int left_max=nums[0];
for(int i=1;i<n-1;i++){
//注意是>/<还是≥/≤
if(nums[i]>=left_max&&nums[i]<=right_min[i]){
res.emplace_back(nums[i]);
}
left_max=max(left_max, nums[i]);
}
}
return res;
}
int main(){
vector<int> nums={1,2,2,3,4,4,5};
vector<int> res1=findNum1(nums);
vector<int> res2=findNum2(nums);
vector<int> res3=findNum1(nums, true);
vector<int> res4=findNum2(nums, true);
printVec(nums);
cout<<endl;
printVec(res1);
printVec(res2);
cout<<endl;
printVec(res3);
printVec(res4);
system("pause");
return 0;
}
以上是关于面试题:在数组里查找这样的数,它大于(等于)左侧所有数,小于(等于)右侧所有数的主要内容,如果未能解决你的问题,请参考以下文章
面试题:在数组里查找这样的数,它大于(等于)左侧所有数,小于(等于)右侧所有数