1.问题描述
给定一个无序数组,找出比左边大比右边小的所有元素。
输入输出示例:
- [1,2,3,1,4,5,7,6] 输出 [4,5]
- [1,2,3,1,4,0,4,5] 输出 [5]
- [1,2,3,4,5,6,7] 输出 [1,2,3,4,5,6,7]
2.难度级别
middle
3.热门指数
★★★★☆
该问题在字节、腾讯和其他厂面试时经常出现。如我在腾讯内部活水以及外部的富途面试时都有碰到,比较热门,必须掌握。
4.解题思路
一个数要比它左边的所有数要大,比右边的所有数要小,那么它必定大于左边元素的最大值,同时小于右边元素的最小值。
两次遍历。第一次遍历从后向前,找出第 i 个元素右边元素的最小值,保存在 rightMin 数组中。第二次遍历,从前向后,使用一个临时变量保存左边元素的最大值,一边判断一边更新。
时间复杂度:
两次遍历,所以是 O(2n)。
空间复杂度:
一个是保存右边的最小值数组,一个是临时变量保存左边元素的最大值,还有一个保存满足条件的元素的数组,最长情况下为 n,所以空间复杂度是 O(2n+1)。
5.实现示例
5.1 Golang
package main
import (
"fmt"
"math"
)
// getPivotElems 获取比左边大比右边小的所有元素。
func getPivotElems(values []int) []int {
l := len(values)
// 从右往左,寻找每个位置及其之后的最小数。
rightMin := make([]int, l)
rightMin[l-1] = math.MaxInt
for i := l - 2; i >= 0; i-- {
if values[i+1] < rightMin[i+1] {
rightMin[i] = values[i+1]
continue
}
rightMin[i] = rightMin[i+1]
}
// 从左往右,寻找比左边大且比右边小的数。
var max int
var rslts []int
for i := 0; i < l; i++ {
if values[i] > max {
max = values[i]
if values[i] < rightMin[i] {
rslts = append(rslts, values[i])
}
}
}
return rslts
}
验证:
func main() {
values1 := []int{1, 2, 3, 1, 4, 5, 7, 6}
fmt.Println(getPivotElems(values1))
values2 := []int{1, 2, 3, 1, 4, 0, 4, 5}
fmt.Println(getPivotElems(values2))
values3 := []int{1, 2, 3, 4, 5, 6, 7}
fmt.Println(getPivotElems(values3))
}
输出:
[4 5]
[5]
[1 2 3 4 5 6 7]
5.2 C++
#include <limits.h>
#include <iostream>
#include <vector>
using namespace std;
// getPivotElems 获取比左边大比右边小的所有元素。
vector<int> getPivotElems(int data[], int len) {
// 从右往左,寻找每个位置及其之后的最小数。
int* rightMin = new int[len];
rightMin[len-1] = INT_MAX;
for (int i = len - 2; i >= 0; i--) {
if (data[i+1] < rightMin[i+1]) {
rightMin[i] = data[i+1];
continue;
}
rightMin[i] = rightMin[i+1];
}
// 从左往右,寻找比左边大且比右边小的数。
int max = 0;
vector<int> vec;
for (int i = 0; i < len; i++) {
if (data[i] > max) {
max = data[i];
if (data[i] < rightMin[i]) {
vec.push_back(data[i]);
}
}
}
return vec;
}
验证:
int main() {
int values1[] = {1,2,3,1,4,5,7,6};
auto vec1 = getPivotElems(values1, sizeof(values1) / sizeof(values1[0]));
for (auto v : vec1) {
cout << v << ' ';
}
int values2[] = {1,2,3,1,4,0,4,5};
auto vec2 = getPivotElems(values2, sizeof(values2) / sizeof(values2[0]));
for (auto v : vec2) {
cout << v << ' ';
}
int values3[] = {1,2,3,4,5,6,7};
auto vec3 = getPivotElems(values3, sizeof(values3) / sizeof(values3[0]));
for (auto v : vec3) {
cout << v << ' ';
}
}
输出:
4 5
5
1 2 3 4 5 6 7