左神_基础提升班_04_滑动窗口以及单调栈

1.滑动窗口
(1)通用形式

	public static class WindowMax{
		public int L;
		public int R;
		public int[] arr;
		public LinkedList<Integer> list;
		public WindowMax(int [] a){
			this.arr=a;
			this.L=-1;
			this.R=0;
			this.list=new LinkedList<>();
		}
		public void addNumFromRight(){
			if(R==arr.length){
				return;
			}
			while(!list.isEmpty()&&arr[R]>=arr[list.peekLast()]){//注意条件完整性
				list.pollLast();
			}
			list.addLast(R);
			R++;
		}
		public void removeFromLeft(){
			if(L>=R-1){//注
				return;
			}
			L++;
			if(list.peekFirst()==L){//若不等于,它都没放进去,不用删
				list.pollFirst();
			}
			
		}
		public Integer getMax(){
			if(!list.isEmpty()){
				return arr[list.peekFirst()];//注意返回的是数组中的值
			}
			return null;
		}
	}

(2)针对于题目

	public static void getMaxWindow(int[] arr, int w) {
		if(arr==null||arr.length<1||arr.length<w){
			return ;
		}
		WindowMax windowMax = new WindowMax(arr);
		for (int i = 0; i < w; i++) {
			windowMax.addNumFromRight();
		}
		List<Integer> list=new ArrayList<>();
		list.add(windowMax.getMax());
		while(windowMax.R<arr.length){
			windowMax.addNumFromRight();
			windowMax.removeFromLeft();
			list.add(windowMax.getMax());
		}
		for (Integer integer : list) {
			System.out.println(integer);
		}
	}
	public static void main(String[] args) {
		int[] arr = { 4, 3, 5, 4, 3, 3, 6, 7 };
		int w = 3;
		getMaxWindow(arr,w);
	}

2.单调栈
(1)无重复

	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[i] > arr[stack.peek()] ) {//注意是arr[stack.peek()
				int popIndex = stack.pop();
				int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();
				res[popIndex][0] = leftLessIndex;
				res[popIndex][1] = i;
			}
			stack.push(i);
		}
		while (!stack.isEmpty()) {
			int popIndex = stack.pop();
			int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();
			res[popIndex][0] = leftLessIndex;
			res[popIndex][1] = -1;
		}
		return res;
	}

(2)有重复

	public static int[][] getNearLess(int[] arr) {
		int[][] res = new int[arr.length][2];
		Stack<List<Integer>> stack = new Stack<>();
		for (int i = 0; i < arr.length; i++) {
			while (!stack.isEmpty() && arr[i] > arr[stack.peek().get(0)] ) {//注意是arr[stack.peek().get(0)]
				List<Integer> popIs = stack.pop();
				// 取位于下面位置的列表中,最晚加入的那个
				int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(
						stack.peek().size() - 1);
				for (Integer popi : popIs) {
					res[popi][0] = leftLessIndex;
					res[popi][1] = i;//注意是i
				}
			}
			if (!stack.isEmpty() && arr[stack.peek().get(0)] == arr[i]) {
				stack.peek().add(Integer.valueOf(i));
			} else {
				ArrayList<Integer> list = new ArrayList<>();
				list.add(i);
				stack.push(list);
			}
		}
		while (!stack.isEmpty()) {
			List<Integer> popIs = stack.pop();
			// 取位于下面位置的列表中,最晚加入的那个
			int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(
					stack.peek().size() - 1);
			for (Integer popi : popIs) {
				res[popi][0] = leftLessIndex;
				res[popi][1] = -1;
			}
		}
		return res;
	}

3.数组中累积和与最小值的乘积,叫做指标A,给定一个数组,返回子数组中,指标A最大的值
(1)暴力解法:

	public static int max1(int[] arr) {
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < arr.length; i++) {
			for (int j = i; j < arr.length; j++) {
				int minNum = Integer.MAX_VALUE;
				int sum = 0;
				for (int k = i; k <= j; k++) {
					sum += arr[k];
					minNum = Math.min(minNum, arr[k]);
				}
				max = Math.max(max, minNum * sum);
			}
		}
		return max;
	}

(2)单调栈解法

	public static int max2(int[] arr) {
		int size=arr.length;
		int sums[] =new int[arr.length];
		sums[0]=arr[0];
		for (int i = 1; i < sums.length; i++) {
			sums[i]=sums[i-1]+arr[i];
		}
		Stack<Integer> stack=new Stack<>();
		int max=Integer.MIN_VALUE;
		for(int i=0;i<arr.length;i++){
			while(!stack.isEmpty()&&arr[i]<=arr[stack.peek()]){
				int j=stack.pop();
				int sum=(stack.isEmpty()?sums[i-1]:sums[i-1]-sums[stack.peek()])*arr[j];
				max=Math.max(sum,max);
			}
			stack.push(i);
		}
		while(!stack.isEmpty()){
			int j=stack.pop();
			int sum=(stack.isEmpty()?sums[size-1]:sums[size-1]-sums[stack.peek()])*arr[j];
			max=Math.max(sum,max);
		}
		return max;
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值