给定一个不含有重复值的数组 arr,找到每一个 i 位置左边和右边离 i 位置最近且值比 arr[i] 小的位置。返回所有位置相应的信息。
第一行输入一个数字 n,表示数组 arr 的长度。
以下一行输出 n个数字,表示数组的值。
输出n行,每行两个数字 L 和 R,如果不存在,则值为-1,下标从0开始。
7 3 4 1 5 6 2 7
-1 2 0 2 -1 -1 2 5 3 5 2 -1 5 -1
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int a[n+1]={-INT_MAX}, l[n+1]={0}, r[n+1]={0}, s[n+1]={0};
for(int i=1;i<=n;i++)
scanf("%d", &a[i]);
for(int i=1,t=0;i<=n;){
if(a[i]>a[s[t]]){
l[i] = s[t];
s[++t] = i++;
}else
r[s[t--]] = i;
}
for(int i=1;i<=n;i++)
printf("%d %d\n", l[i]-1, r[i]-1);
return 0;
} 单调栈,顾名思义,栈中的内容是单调的,我们可以利用这里特性解决一些有趣的问题,如:
水池问题: 给定一组高度,如[0,1,0,2,1,0,1,3,2,1,2,1],返回可以装的水量6
最大面积问题:给定一组高度如[2,1,5,6,2,3],返回最大矩形面积10
题目中要求所有值左边👈和右边👉最近的较小值,可以利用单调递增栈:
遍历完整个数组后,如果栈不为空,一一出栈,此时下标对应的元素无右边较小值,左边较小值为下一个栈顶对应的数组元素。
//
// Created by jt on 2020/8/27.
//
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> vec;
for (int i = 0; i < n; ++i) { int a; cin >> a; vec.push_back(a); }
stack<int> st; // 单调递增栈
vector<int> left(n, -1), right(n, -1); // 分别存储左边较小值和右边较小值的下标
for (int i = 0; i < n; ++i) {
while(!st.empty() && vec[i] < vec[st.top()]) {
int cur = st.top(); st.pop();
if (!st.empty()) left[cur] = st.top();
right[cur] = i;
}
st.push(i); // 将当前元素的下标入栈
}
while(!st.empty()) {
int cur = st.top(); st.pop();
if (!st.empty()) left[cur] = st.top();
}
for (int i = 0; i < n; ++i) {
cout << left[i] << ' ' << right[i] << endl;
}
} import java.util.Scanner;
import java.util.Stack;
public class Main {
public static int[][] getNearLessNoRepeat(int[] arr) {
int[][] res = new int[arr.length][2];
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < arr.length; i++) {
// 如果当前遍历到的数组的值小,需要弹出
while (!stack.isEmpty() && arr[stack.peek()] > arr[i]) {
int popIndex = stack.pop();
int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();
res[popIndex][0] = leftLessIndex;
res[popIndex][1] = i;
}
// 否则当前遍历到的数组的值大,压入不会破坏stack从栈顶到栈底递减的顺序
stack.push(i);
}
// 遍历结束,清算栈中剩下的位置,因为没有当前遍历到的位置,右边位置一律为-1
while (!stack.isEmpty()) {
int popIndex = stack.pop();
int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();
res[popIndex][0] = leftLessIndex;
res[popIndex][1] = -1;
}
return res;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextInt()) {
int n = sc.nextInt();
int[] data = new int[n];
for (int i = 0; i < data.length; i++) {
data[i] = sc.nextInt();
}
int[][] result = getNearLessNoRepeat(data);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < result.length; i++) {
sb.append(result[i][0]).append(" ").append(result[i][1]).append('\n');
}
System.out.print(sb);
}
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
String[] strArr = br.readLine().split(" ");
int[] arr = new int[n];
int[][] res = new int[n][2]; // res[i]分别表示arr[i]左边和右边离它最近且比它小的数
for(int i = 0; i < n; i++){
res[i][0] = -1;
res[i][1] = -1;
}
Stack<Integer> stack = new Stack<>();
for(int i = 0; i < n; i++){
arr[i] = Integer.parseInt(strArr[i]);
if(stack.isEmpty()){
stack.push(i);
}else{
if(arr[stack.peek()] < arr[i]){
// 单调性保持,压栈
stack.push(i);
}else{
// 单调性被破坏,弹栈
while(!stack.isEmpty() && arr[stack.peek()] > arr[i]){
int temp = stack.pop();
res[temp][1] = i; // 栈中所有右边比它小的元素都是arr[i]
if(!stack.isEmpty()) res[temp][0] = stack.peek(); // arr[temp]左边是temp下边压着的数
else res[temp][0] = -1;
}
if(stack.isEmpty()) res[i][0] = -1;
else res[i][0] = stack.peek();
stack.push(i);
}
}
}
// 清算阶段
while(!stack.isEmpty()){
int temp = stack.pop();
if(!stack.isEmpty()) res[temp][0] = stack.peek();
else res[temp][0] = -1;
}
for(int i = 0; i < n; i++) System.out.println(res[i][0] + " " + res[i][1]);
}
} n = int(input())
arr = list(map(int, input().split(' ')))
res = [0]*n
stack = []
for i in range(n):
while stack and arr[stack[-1]]>arr[i]:
pop_index = stack.pop()
if stack:
left_less_index = stack[-1]
else:
left_less_index = -1
res[pop_index] = [left_less_index, i]
stack.append(i)
while stack:
pop_index = stack.pop()
if stack:
left_less_index = stack[-1]
else:
left_less_index = -1
res[pop_index] = [left_less_index, -1]
for j in res:
print(str(j[0]) + ' ' + str(j[1]))
function solution(n, nums) {
// 初始化结果数组和单调栈
const res = new Array(n), stack = []
let popIndex, leftLessIndex
// 遍历给定的数组
// 因为结果是求数组中每个位置的左右较小的位置,所以单调栈从顶向下应该是递减的
for (let i = 0; i < n; i++) {
// 违反单调栈的结构时,需要弹出栈顶,并且将当前位置压入
while (stack.length && nums[stack[stack.length - 1]] > parseInt(nums[i])) {
popIndex = stack.pop()
leftLessIndex = stack.length ? stack[stack.length - 1] : -1
res[popIndex] = [leftLessIndex, i]
}
stack.push(i)
}
// 栈中还有元素,说明即使遍历完数组也没有比栈中剩余的元素小的元素,所以其右边没有比栈中剩余元素小的元素
while (stack.length) {
popIndex = stack.pop()
leftLessIndex = stack.length ? stack[stack.length - 1] : -1
res[popIndex] = [leftLessIndex, -1]
}
return res
}
let n = parseInt(readline())
let nums = readline().split(' ')
let result = solution(n, nums)
for (let i = 0; i < n; i++) {
print(result[i][0] + ' ' + result[i][1])
}
今天真的去吃了【周末愉快】
let n=parseInt(readline())
let line=readline()
let arr=line.split(' ').map(item=>parseInt(item))
let res=Array.from({length:n},()=>[-1,-1])
let stack=[]
for(let i=0;i<n;i++){
if(stack.length==0){
stack.push(i)
}else{
while(arr[i]<=arr[stack[stack.length-1]]){
var curIndex=stack.pop()
res[curIndex][1]=i
}
if(stack.length)res[i][0]=stack[stack.length-1]
stack.push(i)
}
}
res.forEach(item=>console.log(item.join(' ')))
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int main()
{
int n;
cin>>n;
int *p_arr = new int[n];
for(int i = 0;i<n;i++)
{
cin>>p_arr[i];
}
int (* ans)[2] = new int[n][2];
stack<int> stacks;
for(int i = 0;i<n;i++)
{
while(!stacks.empty()&&p_arr[stacks.top()] > p_arr[i])
{
int cur = stacks.top();
stacks.pop();
ans[cur][0] = stacks.empty()? -1 : stacks.top();
ans[cur][1] = i;
}
stacks.push(i);
}
while(!stacks.empty())
{
int cur = stacks.top();
stacks.pop();
ans[cur][0] = stacks.empty()? -1 : stacks.top();
ans[cur][1] = -1;
}
for(int i = 0;i<n;i++)
{
cout<<ans[i][0]<<' '<<ans[i][1]<<endl;
}
} #include <iostream>
#include <vector>
#include <stack>
using namespace std;
vector<vector<int>> process(const vector<int>& v){
stack<int> st;
vector<vector<int>> ans(v.size(), vector<int>(2, 0));
for(int i = 0; i < v.size(); i++){
while(!st.empty() && v[st.top()] > v[i]){
int j = st.top();
st.pop();
//L
ans[j][0] = st.empty() ? -1 : st.top();
ans[j][1] = i;
}
st.push(i);
}
while(!st.empty()){
int j = st.top();
st.pop();
//L
ans[j][0] = st.empty() ? -1 : st.top();
ans[j][1] = -1;
}
return ans;
}
int main(void){
int n;
cin >> n;
vector<int> v(n);
for(int i = 0; i < n; i++){
cin >> v[i];
}
vector<vector<int>> ans = process(v);
for(auto a : ans){
cout << a[0] << " " << a[1] << endl;
}
return 0;
}
#include<bits/stdc++.h>
int arr[1000001];
int left[1000001];
int right[1000001];
int main()
{
int N;
scanf("%d",&N);
int x = 0;
for(int i = 0; i < N; ++i)
{
scanf("%d",&x);
arr[i] = x;
}
std::stack<int> st;
for(int i = 0; i < N; ++i)
{
while(!st.empty() && arr[st.top()] >= arr[i])
{
right[st.top()] = i;
st.pop();
}
left[i] = (st.empty() ? -1 : st.top());
st.push(i);
}
while(!st.empty())
{
right[st.top()] = -1;
st.pop();
}
for(int i = 0; i < N; ++i)
{
printf("%d %d\n",left[i],right[i]);
}
return 0;
} #include<iostream>
#include<vector>
#include<stack>
using namespace std;
int main() {
int n;scanf("%d", &n);
vector<int> a(n);
for(int i=0;i<n;++i) {
scanf("%d",&a[i]);
}
vector<int>left(n,-1);
vector<int>right(n,-1);
stack<int> less;
for(int i=0;i<n;++i) {
while(less.size() && a[less.top()] > a[i]) {
int pre = less.top();less.pop();
right[pre] = i;
if(less.size()) left[pre] = less.top();
}
less.push(i);
}
while(less.size()) {
int x = less.top();less.pop();
if(less.size()) left[x] = less.top();
}
for(int i=0;i<n;++i) {
cout << left[i]<<' '<<right[i]<<endl;
}
return 0;
}
#include <iostream>
#include <stack>
#include <utility>
using namespace std;
pair<int, int> loc;
pair<int, int> *maxLoc(int arr[], int size){
pair<int, int> *res = new pair<int, int>[size];
stack<int> S;
for(int i = 0; i < size; i++){
if(S.empty() || arr[S.top()] < arr[i]){
S.push(i);
}else{
while(!S.empty() && arr[S.top()] > arr[i]){
int temp = S.top();
S.pop();
int L = S.empty() ? -1 : S.top();
res[temp] = make_pair(L,i);
}
S.push(i);
}
}
while(!S.empty()){
int temp = S.top();
S.pop();
int L = S.empty() ? -1 : S.top();
res[temp] = make_pair(L, -1);
}
return res;
}
int main()
{
int n;
cin >>n;
int *arr = new int[n];
for(int i = 0; i < n; i++) cin >> arr[i];
pair<int, int> *res = maxLoc(arr, n);
for(int i = 0; i < n; i++)
cout << res[i].first << " " << res[i].second << endl;
return 0;
}
import java.util.*;
//第一行输入一个数字 n,表示数组 arr 的长度。
//
//以下一行输出 n个数字,表示数组的值。
//7
//3 4 1 5 6 2 7
//-1 2
//0 2
//-1 -1
//2 5
//3 5
//2 -1
//5 -1
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int m= sc.nextInt();
int[] nums=new int[m];
for (int i = 0; i < m; i++) {
nums[i]=sc.nextInt();
}
Stack<Integer> s=new Stack<>();
s.push(0);
int[][] res=new int[m][2];
res[0][0]=-1;
int index=1;
while (index<m){
int cur=nums[index];//取出当前值
if(!s.isEmpty()&&cur>nums[s.peek()]){//如果栈不为空,且比栈顶的值大,为了保持单调栈的结构,直接压入栈,后面出栈的时候再设置其左侧和右侧最小就行
s.push(index);
index++;
}else if(s.isEmpty()){//如果栈为空,压入当前的下标
s.push(index);
index++;
}
else {//栈不为空,且cur<当前的栈顶,这道题数组是不含有重复值的,所以只有大于或者等于
while (!s.isEmpty()&&cur<nums[s.peek()]){
int temp=s.pop();
res[temp][1]=index;
res[temp][0]= s.isEmpty()?-1:s.peek();
}
s.push(index);
index++;
}
}
while(!s.isEmpty()){//如果有些值本身就比较小,会一直在栈中,所以得设置其值
int cur=s.pop();
res[cur][1]=-1;
res[cur][0]=s.isEmpty()?-1:s.peek();
}
res[m-1][1]=-1;//末尾元素的右侧肯定是-1
for (int i = 0; i < res.length; i++) {
System.out.printf(String.valueOf(res[i][0])+" ");
System.out.printf(String.valueOf(res[i][1])+'\n');
}
}
}
import java.util.Scanner;
import java.util.Stack;
public class Main {
private int[][] minIndex;
private int[] arr;
Main(int[] arr){
this.arr = arr;
int n = arr.length;
minIndex = new int[n][2];
for (int i=0; i<n; i++){
minIndex[i][0] = -1;
minIndex[i][1] = -1;
}
}
public int[][] findMinIndex(){
Stack<Integer> stack = new Stack<>();
for (int i=0; i < arr.length; i++){
int cur = arr[i];
if (stack.isEmpty()){
stack.push(i);
}else {
if (cur > arr[stack.peek()]){
minIndex[i][0] = stack.peek();
}else {//cur < stack.peek()
while (!stack.isEmpty() && arr[stack.peek()] > cur) {
minIndex[stack.pop()][1] = i;
}
if (!stack.isEmpty()){
minIndex[i][0] = stack.peek();
}
}
stack.push(i);
}
}
return minIndex;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int count = sc.nextInt();
int[] arr = new int[count];
for(int i = 0;i < count;i++){
arr[i] = sc.nextInt();
}
Main singleStack = new Main(arr);
int[][] minIndex = singleStack.findMinIndex();
for (int i=0; i<arr.length; i++){
System.out.println(minIndex[i][0]+" "+minIndex[i][1]);
}
}
} import java.util.*;
public class PrintMassage{
public static void PrintIndex(int[] arr,int count){
int[] A = new int[2];
for(int i = 0;i < count;i++){
if(i == 0){
A[0] = -1;
}
if(i == count - 1){
A[1] = -1;
}
int j = i;
while(j >= 0 && j <= count - 1){
j -= 1;
if(j >= 0) {
if (arr[i] > arr[j]) {
A[0] = j;
break;
}
}
//注意判断没有的情况
else {
A[0] = -1;
}
}
//注意上面的j变化的问题
j = i;
while(j >= 0 && j <= count - 1){
j += 1;
if(j <= count - 1) {
if (arr[i] > arr[j]) {
A[1] = j;
break;
}
}else {
A[1] = -1;
}
}
System.out.println(A[0] + " " + A[1]);
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int count = sc.nextInt();
int[] arr = new int[count];
for(int i = 0;i < count;i++){
arr[i] = sc.nextInt();
}
PrintIndex(arr,count);
}
} #include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
int arr[n];
for(int i=0; i<n; i++)
cin >> arr[i];
pair<int, int> help_vec[n];
stack<int> stk;
for(int i=0; i<n; i++){
while(!stk.empty() && arr[i]<arr[stk.top()]){
int top = stk.top();
stk.pop();
help_vec[top].first = (stk.empty()) ? -1 : stk.top();
help_vec[top].second = i;
}
stk.push(i);
}
while(!stk.empty()){
int top = stk.top();
stk.pop();
help_vec[top].first = (stk.empty()) ? -1: stk.top();
help_vec[top].second = -1;
}
// output
for(int i=0; i<n; i++){
cout<< help_vec[i].first << ' ' << help_vec[i].second << endl;
}
return 0;
} import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class Main {
/**
* 没有重复数字时使用单调栈结构,时间复杂度O(N)
*/
public static int[][] getNearLessNoRepeat(int[] arr) {
int[][] res = new int[arr.length][2];
// 排除两种特例:null 空数组[]
if (arr == null || arr.length < 1) {
return null;
}
// 单调栈初始化
Stack<Integer> stack = new Stack<>();
int i = 0;
int cur;
while (i < arr.length) {
if (stack.isEmpty() || arr[i] > arr[stack.peek()]) {
// 满足从栈顶到栈底单调递减时,压入
stack.push(i);
i++;
} else {
// 不满足从栈顶到栈底单调递减时,弹出
cur = stack.pop();
res[cur][0] = stack.isEmpty() ? -1 : stack.peek();
res[cur][1] = i;
}
}
// 清算栈中剩余的元素,这些元素右边没有比它小的数字
while (!stack.isEmpty()) {
cur = stack.pop();
res[cur][0] = stack.isEmpty() ? -1 : stack.peek();
res[cur][1] = -1;
}
return res;
}
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.valueOf(bufferedReader.readLine());
int[] arr = new int[n];
String[] numbers = bufferedReader.readLine().split(" ");
for (int i = 0; i < n; i++) {
arr[i] = Integer.valueOf(numbers[i]);
}
int[][] res = getNearLessNoRepeat(arr);
for (int i = 0; i < res.length; i++) {
System.out.println(res[i][0] + " " + res[i][1]);
}
}
}