Skip to content

Latest commit

 

History

History
179 lines (154 loc) · 5.89 KB

0033.逛街.md

File metadata and controls

179 lines (154 loc) · 5.89 KB

33.逛街

题目链接

C++

#include<iostream>
#include<vector>
#include<stack>

using namespace std;
string s;

void get_ans(vector<int>& nums) {
    stack<int> st1;
    stack<int> st2;
    // 先初始化答案为1,因为至少包括自己这栋楼
    vector<int> visible(nums.size(), 1);
    // 从左向右遍历数组
    for(int i = 0; i < nums.size(); ++i) {
        // 此时栈中的元素大小就是往左边看能看到的大楼数量
        visible[i] += st1.size();
        // 保证栈顶元素比nums[i]要大,把在栈顶但比nums[i]小的全部弹出
        // 因为高度比nums[i]低且在它左边的楼都将被遮住
        while(!st1.empty() && nums[i] >= st1.top()) {
            st1.pop();
        }
        // 此时比nums[i]小的都已经被弹出
        // 将nums[i]加入栈顶
        st1.push(nums[i]);
    }
    // 从右向左遍历数组,与上方同理
    for(int i = nums.size() - 1; i >= 0; --i) {
        visible[i] += st2.size();
        while(!st2.empty() && nums[i] >= st2.top()) {
            st2.pop();
        }
        st2.push(nums[i]);
    }
    //输出答案
    cout << "[";
    for(int i = 0; i < visible.size(); ++i) {
        if(i == visible.size() - 1) {
            cout << visible[i];
        }
        else {
            cout << visible[i] << ",";
        }
    }
    cout << "]" << endl;
}

int main() {
    while(cin >> s) {
        // 处理数据并存入nums数组
        vector<int> nums;
        int tmp = 0;
        for(int i = 1; i < s.size(); ++i) {
            if(s[i] == ']' || s[i] == ',') {
                nums.push_back(tmp);
                tmp = 0;
            }
            else {
                tmp = tmp * 10;
                tmp += (int)(s[i] - 48);
            }
        }
        get_ans(nums);   
    }
    return 0;
}

Java

import java.util.Arrays;
import java.util.Scanner;
import java.util.Stack;
/*

题意为计算在每栋楼的位置处可以看到多少栋楼,考虑了从左向右和从右向左两个方向的可见性。可以使用单调栈的特性进行解决。

这里是代码的主要思路:

首先将 visibleCounts 每个位置上的值加 1(因为包括自己本身的楼)。

从左向右遍历楼的高度数组 heights,使用栈 stack1 来保存之前遇到的楼的高度,保证栈顶元素总是比后面的元素要高。在遍历过程中,对于每一栋楼,将栈的大小(即之前楼的数量)存储在 visibleCounts 数组中的对应位置,表示往左看能看到的楼的数量。如果当前楼高度大于等于栈顶元素,则不断将栈顶元素弹出,直到满足条件。

从右向左遍历楼的高度数组 heights,使用栈 stack2 来保存之前遇到的楼的高度,保证栈顶元素总是比后面的元素要高。在遍历过程中,对于每一栋楼,将栈的大小(即之前楼的数量)加到 visibleCounts 数组中的对应位置,表示往右看能看到的楼的数量。如果当前楼高度大于等于栈顶元素,则不断将栈顶元素弹出,直到满足条件。

*/
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String buildings = scanner.nextLine();
        int[] heights = parseIntArray(buildings);
        int n = heights.length;
        int[] visibleCounts = new int[n];
        Arrays.fill(visibleCounts, 1);
        calculateVisibleCounts(heights, visibleCounts);
        System.out.println(Arrays.toString(visibleCounts).replaceAll(" ", ""));
    }

    public static void calculateVisibleCounts(int[] heights, int[] visibleCounts) {
        int n = heights.length;
        Stack<Integer> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();

        for (int i = 0; i < n; i++) {
            visibleCounts[i] += stack1.size();
            while (!stack1.empty() && stack1.peek() <= heights[i]) {
                stack1.pop();
            }
            stack1.push(heights[i]);
        }

        for (int i = n - 1; i >= 0; i--) {
            visibleCounts[i] += stack2.size();
            while (!stack2.empty() && stack2.peek() <= heights[i]) {
                stack2.pop();
            }
            stack2.push(heights[i]);
        }
    }

    public static int[] parseIntArray(String input) {
        String[] elements = input.substring(1, input.length() - 1).split(",");
        int[] parsedArray = new int[elements.length];
        for (int i = 0; i < elements.length; i++) {
            parsedArray[i] = Integer.parseInt(elements[i].trim());
        }
        return parsedArray;
    }
}

Python

###################
# 第33题
###################
#
# #小明在周末的时候和他的小伙伴来到大城市逛街,一条步行街上有很多高楼,共有 n 座高楼排成一行。  
# 小明从第一栋一直走到了最后一栋,小明从来都没有见到这么多的楼,所以他想知道他在每栋楼的位置处能看到多少栋楼呢?(当前面的楼的高度大于等于后面的楼时,后面的楼将被挡住)
# 
# 思路:利用单调栈,先从头到尾进行遍历得到向正方向看能看得到的楼数目,再reverse数组,计算得到反方向看楼的数目,最终将两个数组相加

def get_Num(nums):
    res = [0 for _ in nums]
    stack = [0]
    # 从头遍历,站在每个位置上向前看能看到的楼的数量,不管怎样在1号楼都能看见0号楼,同时,保证单调栈内单调递减
    for i in range(1, len(nums)):
        res[i] = len(stack)
        while len(stack) != 0 and nums[stack[-1]]<=nums[i]:
            stack.pop()
        stack.append(i)
    return res

s = input()
try:
    nums = eval(s)
except:
    print("error for input")
frot = get_Num(nums=nums)
nums.reverse()
back = get_Num(nums=nums)
for i in range(len(frot)):
    frot[i] += back[len(frot)-1-i] + 1
print("[" + ",".join(map(str, frot)) + "]")

Go

JS

C