程序员代码面试指南刷题--第一章.生成窗口最大值数组

题目描述

有一个整型数组arr和一个大小为w的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置,求每一种窗口状态下的最大值。(如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值)

输入描述:

第一行输入n和w,分别代表数组长度和窗口大小
第二行输入n个整数XiX_iXi​,表示数组中的各个元素

输出描述:

输出一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值

示例1
输入


8 3
4 3 5 4 3 3 6 7

输出


5 5 5 4 6 7

说明

例如,数组为[43543367],窗口大小为3时:

[4 3 5] 4 3 3 6 7        窗口中最大值为5

4 [3 5 4] 3 3 6 7        窗口中最大值为5

4 3 [5 4 3] 3 6 7        窗口中最大值为5

4 3 5 [4 3 3] 6 7        窗口中最大值为4

4 3 5 4 [3 3 6] 7        窗口中最大值为6

4 3 5 4 3 [3 6 7]        窗口中最大值为7

输出的结果为{5 5 5 4 6 7}

解法一:利用堆(超时了)

import java.io.*;
import java.util.*;
public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] ss = br.readLine().trim().split(" ");
        int len = Integer.parseInt(ss[0]);
        int win = Integer.parseInt(ss[1]);
        ss = br.readLine().trim().split(" ");
        int[] arr = new int[len];
        for(int i=0;i<len;i++){
            arr[i] = Integer.parseInt(ss[i]);
        }
        String result = func(arr,len,win);
        System.out.println(result);
    }
    public static String func(int[] arr,int len,int win){
        PriorityQueue<Integer> pq = new PriorityQueue(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o2-o1;
			}
		});
        int i=0;
        StringBuilder sb = new StringBuilder();
        for(;i<win&&i<len;i++){
            pq.add(arr[i]);
        }
        sb.append(pq.peek());
        for(;i<len;i++){
            pq.remove(arr[i-win]);
            pq.add(arr[i]);
            sb.append(" "+pq.peek());
        }
        return sb.toString();
    }
}

解法二:双端队列

import java.io.*;
import java.util.*;
public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] ss = br.readLine().trim().split(" ");
        int len = Integer.parseInt(ss[0]);
        int win = Integer.parseInt(ss[1]);
        ss = br.readLine().trim().split(" ");
        int[] arr = new int[len];
        for(int i=0;i<len;i++){
            arr[i] = Integer.parseInt(ss[i]);
        }
        String result = func(arr,len,win);
        System.out.println(result);
    }
    public static String func(int[] arr,int len,int w){
        if(arr==null||w<1||w>len){
            return "";
        }
        LinkedList<Integer> list = new LinkedList<>();
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<len;i++){
        	//这里是先加入还是先去除第一个都是可以的
            while(!list.isEmpty()&&arr[list.peekLast()]<=arr[i]){
                list.pollLast();
            }
            list.addLast(i);
            if(list.peekFirst()==i-w){
                list.pollFirst();
            }
            if(i==w-1){
                sb.append(arr[list.peekFirst()]);
            }else if(i>w-1){
                sb.append(" "+arr[list.peekFirst()]);
            }
        }
        return sb.toString();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值