关于队列的一些题目

关于队列的一些题目

1、滑动窗口平均值

  • 描述:给定一个整数数据流和一个窗口大小,根据该滑动窗口的大小,计算滑动窗口里所有数字的平均值。
  • 解法:设置一个 sum,计算总和,在数值个数达到给定最大容量之前,一直添加,用 sum/que.size() 计算平均值。达到最大容量后,弹出最开始的那个,加入新的值,sum减去最开始的值,加上最后加入的值。sum/que.size() 计算平均值
  • 注意:sum 的类型用double,不然计算出来的值不会带小数
class MovingAverage {
Queue<Integer> que;
double sum = 0;
int size = 0;
/** Initialize your data structure here. */
public MovingAverage(int size) {
que = new LinkedList<Integer>();
this.size = size;
}
public double next(int val) {
if(que.size() == size){
sum -= que.poll();
}
que.add(val);
sum += val;
return sum/que.size();
}
}

2、最近请求次数

  • 描述:

    写一个 RecentCounter 类来计算特定时间范围内最近的请求。请实现 RecentCounter 类:RecentCounter() 初始化计数器,请求数为 0 。 int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回过去 3000 毫秒内发生的所有请求数(包括新请求)。确切地说,返回在 [t-3000, t] 内发生的请求数。
    保证 每次对 ping 的调用都使用比之前更大的 t 值。
  • 解法:与上面近似,加入新值时要判断 前面的值和这个值之间的差值是否大于 3000,大于就要while 弹出

class RecentCounter {
Queue<Integer> que;
public RecentCounter() {
que = new LinkedList<>();
}
public int ping(int t) {
while(que.size()!=0 && (t-que.peek())>3000){
que.poll();
}
que.add(t);
return que.size();
}
}

3、完全二叉树插入值

  • 描述:

    完全二叉树是每一层(除最后一层外)都是完全填充(即,节点数达到最大,第 n 层有 2n-1 个节点)的,并且所有的节点都尽可能地集中在左侧。
    设计一个用完全二叉树初始化的数据结构 CBTInserter,它支持以下几种操作:
    CBTInserter(TreeNode root) 使用根节点为 root 的给定树初始化该数据结构;
    CBTInserter.insert(int v)  向树中插入一个新节点,节点类型为 TreeNode,值为 v 。使树保持完全二叉树的状态,并返回插入的新节点的父节点的值;
    CBTInserter.get_root() 将返回树的根节点。
  • 解法:使用两个队列,普通队列用来遍历给定链表的节点,如果有空子节点的,就加入双端队列,先进去的编号最小,最接近 root 节点。双端队列用来给这些没孩子的加孩子。先要把这个新的节点加入到双端队列的尾部(他也莫得孩子),加孩子的顺序是:从最先进来双端队列的节点开始,先看左节点,如果左节点为空,就给这个节点的左孩子赋值,再看右节点,如果右节点为空,就给这个节点的右孩子赋值,赋值之后这个节点就左右孩子都有了,直接从双端队列里面删除。

class CBTInserter {
TreeNode root;
Deque<TreeNode> deque;
public CBTInserter(TreeNode root) {
this.root = root;
deque = new LinkedList<>();
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
TreeNode node = que.poll();
if(node.left==null || node.right==null) deque.offerLast(node);
if(node.left != null) que.offer(node.left);
if(node.right != null) que.offer(node.right);
}
}
public int insert(int val) {
TreeNode node = deque.peekFirst();
deque.offerLast(new TreeNode(val));
if(node.left == null) node.left=deque.peekLast();
else{
node.right=deque.peekLast();
deque.pollFirst();
}
return node.val;
}
public TreeNode get_root() {
return root;
}
}

4、二叉树每层的最大值

  • 描述:

    给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。
  • 解法:

    使用队列进行广度优先遍历,每一层都加入队列,对着一层的值寻找最大值,加入结果数组
  • 源码

    class Solution {
    public List<Integer> largestValues(TreeNode root) {
    if(root == null) return new ArrayList<Integer>();
    Queue<TreeNode> que = new LinkedList<>();
    List<Integer> res = new ArrayList<>();
    que.add(root);
    while(!que.isEmpty()){
    int queSize = que.size();
    int max = Integer.MIN_VALUE;
    while(queSize > 0){
    TreeNode node = que.poll();
    max = node.val>max ? node.val : max;
    if(node.left != null) que.add(node.left);
    if(node.right != null) que.add(node.right);
    queSize--;
    }
    res.add(max);
    }
    return res;
    }
    }

5、二叉树最底层最左边的值

  • 描述:

    给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
    假设二叉树中至少有一个节点。
  • 解法:

    对左右两边都进行深度优先遍历,维护一个深度值与遍历的左右子树的深度值进行比较,保留更大的值
  • 源码:

    class Solution {
    public int findBottomLeftValue(TreeNode root) {
    dfs(root,1);
    return max.val;
    }
    int height = 0;
    TreeNode max = null;
    public void dfs(TreeNode root,int h){
    if(root == null) return;
    if(h > height){
    height = h;
    max = root;
    }
    dfs(root.left,h+1);
    dfs(root.right,h+1);
    }
    }

6、二叉树的右侧视图

  • 描述:

    给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
  • 解法:

    1、仍然可以使用 4 中的广度优先遍历,先判断左边,在判断右边。只不过将每一层的最后一个数据放到结果数组里面。刚好就是最右边的数据了。
    2、深度优先:对于每一个深度总是先访问右子树,那么每层访问到的第一个节点就是我们要的结果了
  • 源码:

    广度优先:
    class Solution {
    public List<Integer> rightSideView(TreeNode root) {
    List<Integer> res = new ArrayList<Integer>();
    if(root == null) return res;
    Queue<TreeNode> que = new LinkedList<>();
    que.add(root);
    while(!que.isEmpty()){
    int queSize = que.size();
    while(queSize>0){
    TreeNode node = que.poll();
    queSize --;
    if(queSize == 0) {
    res.add(node.val);
    }
    if(node.left != null) que.add(node.left);
    if(node.right != null) que.add(node.right);
    }
    }
    return res;
    }
    }
    深度优先:
    class Solution {
    public List<Integer> rightSideView(TreeNode root) {
    Map<Integer, Integer> rightmostValueAtDepth = new HashMap<Integer, Integer>();
    int max_depth = -1;
    Deque<TreeNode> nodeStack = new ArrayDeque<TreeNode>();
    Deque<Integer> depthStack = new ArrayDeque<Integer>();
    nodeStack.push(root);
    depthStack.push(0);
    while (!nodeStack.isEmpty()) {
    TreeNode node = nodeStack.pop();
    int depth = depthStack.pop();
    if (node != null) {
    // 维护二叉树的最大深度
    max_depth = Math.max(max_depth, depth);
    // 如果不存在对应深度的节点我们才插入
    if (!rightmostValueAtDepth.containsKey(depth)) {
    rightmostValueAtDepth.put(depth, node.val);
    }
    nodeStack.push(node.left);
    nodeStack.push(node.right);
    depthStack.push(depth + 1);
    depthStack.push(depth + 1);
    }
    }
    List<Integer> rightView = new ArrayList<Integer>();
    for (int depth = 0; depth <= max_depth; depth++) {
    rightView.add(rightmostValueAtDepth.get(depth));
    }
    return rightView;
    }
    }
posted @   心是冰冰的  阅读(189)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示