找出无序数组中比左边大比右边小的元素

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

参考文献

算法题:找出数组中比左边大比右边的小的元素 - 52Heartz’s Blog

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值