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;
}