騰訊2020校園招聘後臺開發面試編程題

騰訊一面的時候,面試官給出了一道題,題目如下,當初由於是第一次面試,比較緊張沒做出來,現在回顧總結一下。

題目

小Q在週末的時候和他的小夥伴來到大城市逛街,一條步行街上有很多高樓,共有n座高樓排成一行。
小Q從第一棟一直走到了最後一棟,小Q從來都沒有見到這麼多的樓,所以他想知道他在每棟樓的位置處能看到多少棟樓呢?(當前面的樓的高度大於等於後面的樓時,後面的樓將被擋住)

輸入描述

輸入第一行將包含一個數字n,代表樓的棟數,接下來的一行將包含n個數字wi(1<=i<=n),代表每一棟樓的高度。
1<=n<=100000;
1<=wi<=100000;

輸出描述

輸出一行,包含空格分割的n個數字vi,分別代表小Q在第i棟樓時能看到的樓的數量。

輸入示例

6 5 3 8 3 2 5
輸出示例
3 3 5 4 4 4

說明

當小Q處於位置3時,他可以向前看到位置2,1處的樓,向後看到位置4,6處的樓,加上第3棟樓,共可看到5棟樓。當小Q處於位置4時,他可以向前看到位置3處的樓,向後看到位置5,6處的樓,加上第4棟樓,共可看到4棟樓。

解法

暴力解

將輸入數組逐個遍歷,將當前元素和數組傳給 getCanLooks()方法處理,getCanLooks() 方法將返回給元素能看到的樓層數。
getCanLooks() 方法中,分別往index的左邊和index的右邊遍歷,遇到比 leftMax或者rightMax 大的,則將count++
暴力解思路上是對的,本地IDE能跑,但是牛客上就超時了。

public class Main {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int buildNum = scanner.nextInt();
		int[] array = new int[buildNum];
		for(int i=0;i<=buildNum-1;i++) {
			array[i] = scanner.nextInt();
		}
		
		//暴力解
		for(int i=0;i<=buildNum-1;i++) {
			System.out.print(getCanLooks(array,i) + " ");
		}
	}
	
	//獲取該位置能看到的樓數
	public static int getCanLooks(int[] array, int index) {
		int thisHeight = array[index];
		int count = 1;	//本身爲一棟,初始爲1
		int left = index-1;
		int leftMax = Integer.MIN_VALUE;
		int right = index+1;
		int rightMax = Integer.MIN_VALUE;
		//從index位置往左遍歷
		while(left >= 0) {
			if(array[left] > leftMax) {
				count++;
				leftMax = array[left];
			}
			left--;
		}
		//從index位置往右遍歷
		while(right <= array.length-1) {
			if(array[right] > rightMax) {
				count++;
				rightMax = array[right];
			}
			right++;
		}
		return count;
	}
}

使用單調棧

這種方法的思路:
創建一個棧Stack用來記錄從左往右看或者從右往左看能看到的樓層的下標;
創建leftLook數組用來記錄從右往左看能看到的樓層數;
創建rightLook數組用來記錄從左往右看能看到的樓層數;
分別從左往右和從右往左遍歷一次,leftLookrightLook分別記錄,最後兩者相加再+1就得到當前下標能看到的樓層數。

import java.util.Scanner;
import java.util.Stack;

public class Main {
	public static void main(String[] args) {
	    Scanner sc = new Scanner(System.in);
	    int len = sc.nextInt();
	    int[] arr = new int[len];
	    for(int i = 0 ; i < len ; i++){
	        arr[i] = sc.nextInt();
	    }
	    //棧記錄能看到的元素下標
	    Stack<Integer> stack = new Stack<>();
	    //記錄往左看能看到的數量
	    int[] leftLook = new int[len];
	    //記錄往右看能看到的數量
	    int[] rightLook = new int[len];
	    
	    //從右往左看
	    for(int i=0;i<=len-1;i++) {
	  	  //棧大小就是當前位置往左能看到的數量
	  	  leftLook[i] = stack.size();
	  	  //棧不爲空,並且棧頂元素小於當前元素,將棧頂元素移除
	  	  while(!stack.isEmpty() && arr[i] >= arr[stack.peek()]) {
	  		  stack.pop();
	  	  }
	  	  //將當前元素下標入棧
	  	  stack.push(i);
	    }
	    //將棧清空
	    stack.clear();
	    
	    //從左往右看
	    for(int i=len-1;i>=0;i--) {
	  	  rightLook[i] = stack.size();
	  	  while(!stack.isEmpty() && arr[i] >= arr[stack.peek()]) {
	  		  stack.pop();
	  	  }
	  	  stack.push(i);
	    }
	    
	    //leftLook 和 rightLook相加,並加1
	    for(int i=0;i<=len-1;i++) {
	  	  leftLook[i] += 1+rightLook[i];
	  	  System.out.print(leftLook[i] + " ");
	    }
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章