ACM模式–每日一题练习 ——找朋友

题目描述

在学校中,N个小朋友站成一队, 第i个小朋友的身高为height[i],第i个小朋友可以看到的右边的第一个比自己身高更高的小朋友j,那么ji的好朋友(j > i)。请重新生成一个列表,对应位置的输出是每个小朋友的好朋友位置,如果没有看到好朋友,请在该位置用0代替。小朋友人数范围是 [0, 40000]

输入描述

第一行输入N,表示有N个小朋友

第二行输入N个小朋友的身高height[i],都是整数

输出描述

输出N个小朋友的好朋友的位置

示例一

输入

2
100 95

输出

0 0

示例二

输入

8
123 124 125 121 119 122 126 123

输出

1 2 6 5 5 6 0 0

题解

类似这种要求寻找左边/右边最近的更大/更小元素的题目 ,都可以使用单调栈 做。

该题是寻找右边最大,正序构建单调栈的做法如下:

/*
 * @hw id=2023C lang=java
 *
 * 找朋友
 */

// @hw code=start
import java.util.*;

public class Main{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] height = new int[n];
        for(int i=0;i<n;i++) {
            height[i] = in.nextInt();
        }
        List<Integer> stack = new ArrayList<>();
        int[] ans = new int[n];

        for(int i=0;i<n;i++) {
            int h = height[i];
            while(!stack.isEmpty() && h > height[stack.get(stack.size()-1)]) {
                int top = stack.get(stack.size()-1);
                stack.remove(stack.size()-1);
                ans[top] = i;
            }
            stack.add(i);
        }
        for(int i=0;i<n;i++) {
            System.out.print(ans[i] + " ");
        }
        System.out.println();
    }
}
// @hw code=end
#
# @hw id=2023C lang=python3
#
# 找朋友
#

# @hw code=start
n = int(input())
height = list(map(int, input().split()))

stack = list()

ans = [0] * n
for i, h in enumerate(height):
    while len(stack) > 0 and h > height[stack[-1]]:
        top = stack.pop()
        ans[top] = i
    stack.append(i)

print(" ".join(map(str, ans)))
# @hw code=end
/*
 * @hw id=2023C lang=cpp
 *
 * 找朋友
 */

// @hw code=start
#include<iostream>
#include<vector>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> height(n);
    for(int i=0;i<n;i++) {
        cin >> height[i];
    }

    vector<int> stack;
    vector<int> ans(n, 0);

    for(int i=0;i<n;i++) {
        int h = height[i];
        while(stack.size() != 0 && h > height[stack.back()]) {
            int top = stack.back();
            stack.pop_back();
            ans[top] = i;
        }
        stack.push_back(i);
    }
    for(int i=0;i<n;i++) {
        cout << ans[i] << " ";
    }
    cout << endl;

    return 0;
}
// @hw code=end

也可以使用逆向构造单调栈去做。

6 个赞

刷题佬2号!

1 个赞

只会直接遍历 :tieba_087:

1 个赞

练习佬!

1 个赞

每日一题,防止被优化

1 个赞

无邪哥能别卷了吗

1 个赞
#include <iostream>
#include <stack>
#include <vector>

using namespace std;

int main() {
    int n;
    cin >> n;

    vector<int> heights(n);
    for (int i = 0; i < n; i++) {
        cin >> heights[i];
    }

    stack<int> s;
    vector<int> result(n);

    for (int i = 0; i < n; i++) {
        while (!s.empty() && heights[s.top()] <= heights[i]) {
            result[s.top()] = i + 1;
            s.pop();
        }
        s.push(i);
    }

    while (!s.empty()) {
        result[s.top()] = 0;
        s.pop();
    }

    for (int i = 0; i < n; i++) {
        cout << result[i] << " ";
    }

    return 0;
}

1 个赞

深夜刷题啊

1 个赞

鹅佬!这月最佳!

1 个赞

我凑个热闹~脑子不够用

1 个赞

刷题佬!

1 个赞

:100:
不过题意是从0开始计数的

:hugs:哈哈,每日一题防止被优化

这是opus写的捏 我屁都不会

1 个赞

这么强,我赶紧再去注册个账号玩一玩

这个算是简单题吗

是吧,还比较简单的

From 算法 to 开发调优