算法系列题目

文章目录

  • 一. 下一个更大元素
    • 1. 下一个更大元素 Ⅰ
    • 2. 下一个较大元素II
  • 二. 区间问题
    • 1. 贪心策略
      • 最少射箭问题
      • 无重叠区间
      • 合并区间
      • 划分字母区间
    • 2. 差分数组
  • 三. 设计类题目
    • 1. LRU(最近最少使用)缓存
    • 2. LFU(最不经常使用)缓存
  • 四. 括号类

一. 下一个更大元素

1. 下一个更大元素 Ⅰ

添加链接描述
算法系列题目_第1张图片

2. 下一个较大元素II

算法系列题目_第2张图片
添加链接描述

  • 思路分析
    维护单调递减的主栈(用来取结果,题目要求最小,因此是单调递减)和单调递增(跟主栈反过来)的辅助栈
    题目要求的是在当前元素后面比它大,且是最小的那个元素,因此相当于后边的元素要一直用,且排好序,因此想到用一个栈接住弹出的元素,再将其添加到原来的栈中
    为了处理后边的元素排序,因此需要从后边开始遍历
    当主栈不满足单调递减时,弹出元素,且用辅助栈保存结果
import java.util.*;

public class NextElement {
    public int[] findNext(int[] A, int n) {
        int[] res = new int[n];
        Stack<Integer> stack = new Stack<>();//主栈
        Stack<Integer> stack2 = new Stack<>();//辅助栈
        for (int i = n - 1; i >= 0; i--) {
            while (!stack.isEmpty() && stack.peek() <= A[i]) {//保证单调递减
                stack2.push(stack.pop());//用辅助栈保留结果,
            }
            res[i] = stack.isEmpty() ? -1 : stack.peek();//单调递减的栈顶元素为所求
            stack.push(A[i]);//入栈
            while (!stack2.isEmpty()) {//其余元素也需要回到栈
                stack.push(stack2.pop());
            }
        }
        return res;
    }
}

二. 区间问题

1. 贪心策略

最少射箭问题

板子题,排序后,比较后一个元素的左边界和前一个元素的右边界,无重叠+1,出现重叠就更新右边界

无重叠区间

前一题的变形,反过来求结果,区别在于边界相等时的处理不一样

合并区间

前几题的变形,left和right记录最新边界

class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals,(a,b)->(a[0]-b[0]));
        int left = intervals[0][0];
        int right = intervals[0][1];
        LinkedList<int[]> res = new LinkedList<>();
        for(int i=1;i<intervals.length;i++){
            if(intervals[i][0]>intervals[i-1][1]){
                res.add(new int[]{left,right});
                left = intervals[i][0];
                right = intervals[i][1];
            }else{
                intervals[i][1] = Math.max(intervals[i][1],intervals[i-1][1]);
                right = Math.max(intervals[i][1],intervals[i-1][1]);
            }
        }
        res.add(new int[]{left,right});
        return res.toArray(new int[res.size()][2]);
    }
}

划分字母区间

记录每个字母最大索引,当i==最大索引,则满足条件

2. 差分数组

三. 设计类题目

1. LRU(最近最少使用)缓存

添加链接描述

  • Node类:包含key,value,prev和next指针
  • DoubleLinkedList类:双向链表,初始化head和tail相连,head表示最近使用,内含添加节点到头部,删除节点,返回最后一个节点三个方法
  • size记录大小
  • HashMap来缓存值 key:Node
  • 双向链表类来维护最近使用
  • get方法:从缓存中拿,拿不到返回空;拿到的话,更新双向链表中的节点,返回值
  • put方法:先判断是否存在,若存在,更新值和链表;若不存在,判断容量大小,若到达容量大小,删除尾部的元素(链表和hashmap),加入新节点

2. LFU(最不经常使用)缓存

添加链接描述

  • Node类和DoubleLinkedList类,size同前面
  • HashMap保存值,key:Node
  • 另一个HashMap 保存 频率和链表,freq:DoubleLinkedList。说白了就是给每个频率开一个双向链表
  • 开一个遍历minFreq记录最小频率
  • get方法:不存在返回空;存在,更新频率,返回值
  • 更新频率:先找到原来的链表,删除节点;需要判断是否更新最小频率(非常容易漏);更新新的频率,查找是否已存在对应链表,若不存在,创建;存在,加入头节点
  • put方法:判断是否存在,存在,更新值和频率;不存在,判断容量,如果到达容量大小,删除频率最小的最不经常使用的;未达到容量大小,创建节点,放入cache缓存和链表,此时最小频率必然为1,更新最小频率

四. 括号类

你可能感兴趣的:(算法题,算法,java,数据结构)