题意整理
- n个人站成一列,如果某个人的前面有身高比他高的,则第一个比他高的会中枪。
- 只要某个人中枪了,则荒唐度会增加对应那个人的编号,求最终的荒唐度。
方法一(暴力法)
1.解题思路
直接遍历所有的人,内层循环中找到第一个比他高的人,加上对应编号,如果找到,立即终止内层循环。
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param n int整型 n个人 * @param a int整型一维数组 ai代表第i个人的高度 * @return long长整型 */ public long solve (int n, int[] a) { //初始化结果变量 long res=0; //循环遍历数组 for(int i=1;i<n;i++){ //找到第一个大于当前身高的人 for(int j=i-1;j>=0;j--){ if(a[j]>a[i]){ res+=j+1; break; } } } return res; } }
3.复杂度分析
- 时间复杂度:最坏情况下,总是第一个人中枪,需要遍历 次,所以时间复杂度是。
- 空间复杂度:不需要额外的内存空间,所以空间复杂度是。
方法二(单调栈)
1.解题思路
- 初始化一个单调栈,顺序存储所有人的编号。
- 只要栈顶对应的那个人身高小于当前身高,说明不会被打中,直接从栈中移除。这个过程结束后,如果栈中还有人,则一定是第一个大于当前身高的人,加上对应荒唐度,继续下一轮循环。
动图展示:
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param n int整型 n个人 * @param a int整型一维数组 ai代表第i个人的高度 * @return long长整型 */ public long solve (int n, int[] a) { //初始化结果变量 long res=0; //初始化单调栈 LinkedList<Integer> stack=new LinkedList<>(); for(int i=0;i<n;i++){ //只要栈顶身高小于当前身高,就从栈中移除 while(!stack.isEmpty()&&a[stack.peek()-1]<=a[i]){ stack.pop(); } //如果栈中还有元素,则栈顶一定是第一个身高大于当前元素的 if(!stack.isEmpty()){ res+=stack.peek(); } //将每一个人的编号入栈 stack.push(i+1); } return res; } }
3.复杂度分析
- 时间复杂度:每个人最多入栈和出栈一次,所以时间复杂度是。
- 空间复杂度:需要额外大小为n的栈,所以空间复杂度是。