南大高级算法作业之数组和窗口

input:

1

4 3 5 4 3 3 6 7

3

output:

32

  这个问题的思路采用滑动窗口,其实也就是简化了所谓的比较步骤,增加了判定:1.窗口要不断前移,因此必须要保证窗口中流通的元素不超过窗口大小;2.当下一个待进窗口的元素大于窗口内前面的元素时,说明前面元素已经不可能作为最大值,果然删除;3.当待进窗口的元素小于窗口内元素时,要给予保留,因为伴随着窗口移动,小元素也会成为大元素。考虑到这些特性,选用支持首尾操作的LinkedList比较好。

  实际写的时候主要是两个问题,第一是窗口的初始化,其实也可以不用初始化,从第一个元素开始判定,但是还是选择了先初始化;第二个就是自己一开始没有注意到,移动的问题,比如说窗口里是6 2,后面来了5 1,如果按之前的逻辑,会出现6 5 1的情况,也就是说我们没有模拟出来窗口容量这个概念,仅凭size方法是不够的,后来参考了一下别人的写法,发现在LinkedList中存放元素在原数组中的下标就能解决这个问题,比较的时候变成了比较下标差与size的关系,而在求和时只需要加上原数组中对应值即可。

代码

import java.util.*;

public class Main {
	
	public static void main(String[] args) {
    	
    	Scanner scan = new Scanner(System.in);
		
		int e_num = Integer.parseInt(scan.nextLine());//测试数
		
		while(e_num>0){
			
			String num[] = scan.nextLine().split(" ");//目标数组
			
			int size = Integer.parseInt(scan.nextLine());//窗口大小
			
			int res = 0;
			
			LinkedList<Integer> w = new LinkedList<Integer>();//储存元素在数组中位置
			
			for(int i=0;i < size-1;i ++){//先填满窗口
				
				while(!w.isEmpty() && Integer.parseInt(num[w.peekLast()]) < Integer.parseInt(num[i])){//如果尾部元素比即将到来的元素小,就删掉尾部元素后添加到后面

					w.removeLast();
						
				}
						
				w.addLast(i);
				
			}
			
			for(int i=size-1;i < num.length;i ++){
				
				
				
				while(!w.isEmpty() && Integer.parseInt(num[w.peekLast()]) < Integer.parseInt(num[i])){//如果尾部元素比即将到来的元素小,就删掉后添加到后面

					w.removeLast();
						
				}
						
				w.addLast(i);
				
				if(i - w.peekFirst()+1 > size){
						
					w.removeFirst();
						
				}
				
				
				res += Integer.parseInt(num[w.peekFirst()]);
				
			}
			
			System.out.println(res);
				
			e_num --;
		}
    }
    
}
发布了36 篇原创文章 · 获赞 2 · 访问量 2021

猜你喜欢

转载自blog.csdn.net/fumonster/article/details/102486047