数组中的沉默元素计数
阿里研发岗 0530笔试 第一题
题目内容
TkTkTk 有一个长度为 nnn 的数组 {a1,a2,...,ana_1, a_2, ..., a_na1,a2,...,an},对于下标满足 1<i<n1 < i < n1<i<n 的元素 aia_iai,若其左侧所有元素的最大值到它的距离,等于其右侧所有元素的最大值到它的距离,那么这个数字就是沉默的。若左侧(或右侧)区域存在多个数值相等的最大值,则选择其中与 iii 距离最近的下标计算距离。
TkTkTk 想知道数组中一共有多少位置不同的沉默的数字,请输出这个值。
输入描述
每个测试文件均包含多组测试数据。
- 第一行输入一个整数 T(1≤T≤104)T(1 ≤ T ≤ 10^4)T(1≤T≤104),代表数据组数。
- 每组测试数据描述如下:
- 第一行输入一个整数 n(3≤n≤2×105)n(3 ≤ n ≤ 2 × 10^5)n(3≤n≤2×105),表示数组长度。
- 第二行输入 nnn 个整数 a1,a2,...,an(1≤ai≤109)a_1, a_2, ..., a_n(1 ≤ a_i ≤ 10^9)a1,a2,...,an(1≤ai≤109),表示数组
a。
- 保证单个测试文件的 nnn 之和不超过 2×1052 × 10^52×105。
输出描述
对于每一组测试数据,新起一行,输出一个整数表示结果。
样例1
输入
2
3
1 1 1
5
1 4 4 5 2
输出
1
2
题解和思路
思路
实现思路:模拟
- 定义
left和right分别记录当前元素位置左侧最大值位置和右侧最大值位置。、 - 计算
left和right对应值,以left为例,定义maxValue = -1和maxValueIndex = -1分贝表示对应侧最大值和对应位置,从前往后进行遍历,对于位置i的处理逻辑如下:- 如果
maxValueIndex != -1, 更新left[i] = maxValueIndex - 尝试更新
maxValueIndex, 如果a[i] >= maxValue, 更新maxValueIndex = i , maxValue = a[i]
- 如果
- 统计每组沉默数字,从前往后遍历如果
abs(i - left[i]) == abs(i - right[i])对应沉默数字+1.前提left[i] != -1 and right[i] != -1
C++
cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
// 记录左侧最大值位置
vector<int> left(n , -1);
// 记录右侧最大值位置
vector<int> right(n, - 1);
// 处理左侧
int maxValue = -1;
int maxValueIndex = -1;
for (int i = 0; i < n; i++) {
int val = a[i];
if (maxValueIndex != -1) {
left[i] = maxValueIndex;
}
if (maxValue <= val) {
maxValue = val;
maxValueIndex = i;
}
}
// 处理右侧
maxValue = -1;
maxValueIndex = -1;
for (int i = n - 1; i >= 0; i--) {
int val = a[i];
if (maxValueIndex != -1) {
right[i] = maxValueIndex;
}
if (maxValue <= val) {
maxValue = val;
maxValueIndex = i;
}
}
int count = 0;
for (int i = 0; i < n; i++) {
if (left[i] == -1 || right[i] == -1) {
continue;
}
if (abs(i - left[i]) == abs(i - right[i])) {
count++;
}
}
cout << count << endl;
}
return 0;
}
Java
java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while (T-- > 0) {
int n = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
// 记录左侧最大值位置
int[] left = new int[n];
Arrays.fill(left, -1);
// 记录右侧最大值位置
int[] right = new int[n];
Arrays.fill(right, -1);
// 处理左侧
int maxValue = -1;
int maxValueIndex = -1;
for (int i = 0; i < n; i++) {
int val = a[i];
if (maxValueIndex != -1) {
left[i] = maxValueIndex;
}
if (maxValue <= val) {
maxValue = val;
maxValueIndex = i;
}
}
// 处理右侧
maxValue = -1;
maxValueIndex = -1;
for (int i = n - 1; i >= 0; i--) {
int val = a[i];
if (maxValueIndex != -1) {
right[i] = maxValueIndex;
}
if (maxValue <= val) {
maxValue = val;
maxValueIndex = i;
}
}
int count = 0;
for (int i = 0; i < n; i++) {
if (left[i] == -1 || right[i] == -1) {
continue;
}
if (Math.abs(i - left[i]) == Math.abs(i - right[i])) {
count++;
}
}
System.out.println(count);
}
}
}
python
python
t = int(input())
for _ in range(t):
n = int(input())
a = list(map(int, input().split()))
# 记录左侧最大值位置
left = [-1] * n
# 记录右侧最大值位置
right = [-1] * n
# 处理左侧
max_value = -1
max_value_index = -1
for i in range(n):
val = a[i]
if max_value_index != -1:
left[i] = max_value_index
if max_value <= val:
max_value = val
max_value_index = i
# 处理右侧
max_value = -1
max_value_index = -1
for i in range(n - 1, -1, -1):
val = a[i]
if max_value_index != -1:
right[i] = max_value_index
if max_value <= val:
max_value = val
max_value_index = i
count = 0
for i in range(n):
if left[i] == -1 or right[i] == -1:
continue
if abs(i - left[i]) == abs(i - right[i]):
count += 1
print(count)
Javascript
js
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const input = [];
rl.on('line', line => {
input.push(...line.trim().split(/\s+/).map(Number));
});
rl.on('close', () => {
let idx = 0;
let T = input[idx++];
while (T--) {
const n = input[idx++];
const a = [];
for (let i = 0; i < n; i++) {
a.push(input[idx++]);
}
// 记录左侧最大值位置
const left = new Array(n).fill(-1);
// 记录右侧最大值位置
const right = new Array(n).fill(-1);
// 处理左侧
let maxValue = -1;
let maxValueIndex = -1;
for (let i = 0; i < n; i++) {
const val = a[i];
if (maxValueIndex !== -1) {
left[i] = maxValueIndex;
}
if (maxValue <= val) {
maxValue = val;
maxValueIndex = i;
}
}
// 处理右侧
maxValue = -1;
maxValueIndex = -1;
for (let i = n - 1; i >= 0; i--) {
const val = a[i];
if (maxValueIndex !== -1) {
right[i] = maxValueIndex;
}
if (maxValue <= val) {
maxValue = val;
maxValueIndex = i;
}
}
let count = 0;
for (let i = 0; i < n; i++) {
if (left[i] === -1 || right[i] === -1) {
continue;
}
if (Math.abs(i - left[i]) === Math.abs(i - right[i])) {
count++;
}
}
console.log(count);
}
});
Go
go
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
in := bufio.NewReader(os.Stdin)
var T int
fmt.Fscan(in, &T)
for ; T > 0; T-- {
var n int
fmt.Fscan(in, &n)
a := make([]int, n)
for i := 0; i < n; i++ {
fmt.Fscan(in, &a[i])
}
// 记录左侧最大值位置
left := make([]int, n)
// 记录右侧最大值位置
right := make([]int, n)
for i := 0; i < n; i++ {
left[i] = -1
right[i] = -1
}
// 处理左侧
maxValue := -1
maxValueIndex := -1
for i := 0; i < n; i++ {
val := a[i]
if maxValueIndex != -1 {
left[i] = maxValueIndex
}
if maxValue <= val {
maxValue = val
maxValueIndex = i
}
}
// 处理右侧
maxValue = -1
maxValueIndex = -1
for i := n - 1; i >= 0; i-- {
val := a[i]
if maxValueIndex != -1 {
right[i] = maxValueIndex
}
if maxValue <= val {
maxValue = val
maxValueIndex = i
}
}
count := 0
for i := 0; i < n; i++ {
if left[i] == -1 || right[i] == -1 {
continue
}
if abs(i-left[i]) == abs(i-right[i]) {
count++
}
}
fmt.Println(count)
}
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}