IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 面试必刷算法TOP101之队列 TOP32 -> 正文阅读

[数据结构与算法]面试必刷算法TOP101之队列 TOP32

往完全二叉树添加节点

题目来源:leetcode

题目说明

完全二叉树是每一层(除最后一层外)都是完全填充(即,节点数达到最大,第 n 层有 2n-1?个节点)的,并且所有的节点都尽可能地集中在左侧。

设计一个用完全二叉树初始化的数据结构?CBTInserter,它支持以下几种操作:

CBTInserter(TreeNode root)?使用根节点为?root?的给定树初始化该数据结构;
CBTInserter.insert(int v)? 向树中插入一个新节点,节点类型为 TreeNode,值为 v 。使树保持完全二叉树的状态,并返回插入的新节点的父节点的值;
CBTInserter.get_root() 将返回树的根节点。

思路解析

思路:深度优先遍历

如图插入节点分为2中情况:

(1)插入当前节点之前的节点还存在子节点,保存当前行没有子节点的节点

(2)插入节点当前行节点都没有子节点,保存当前行节点。

首先定义一个队列,讲头节点插入到队列中,判断对头节点的左节点的是不是存在,如果存在就属于第一种情况在循环取出节点时,判断左子节点或者右子节点为空时就将节点插入到v数组中。,如果不存在就属于第二种情况在循环取出节点时,讲节点插入到另一个vm数组中。

插入节点时遍历v数组当前遇到左子节点或者右子节点为空时就将节点插入到当前节点的子节点中同时返回当前节点。判断v数组最后一个节点的右子节点是不是为NUll ,不为NULL就说明树的当前行已经满了。更新v数组(v=vm)。

返回根节点值直接return root→val.

代码实现

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class CBTInserter {
    TreeNode*root;
    vector<TreeNode*>vn;
    vector<TreeNode*>v;
    vector<TreeNode*>vm;
    vector<TreeNode*>vs;
public:
    CBTInserter(TreeNode* root) {
        this->root=root;
        //获取最后一行的节点
        queue<TreeNode*>q;
        q.push(root);
     
        while(!q.empty()){
            int size=q.size();
            if(q.front()->left!=NULL){
                while(size--){
                    TreeNode*node=q.front();
                    q.pop();
                    if(node->left==NULL||node->right==NULL){
                        vn.push_back(node);
                    }
                    if(node->left){
                        q.push(node->left);
                    }
                    if(node->right){
                        q.push(node->right);
                    }
                }
            }
            else{
                while(size--){
                    TreeNode*node=q.front();
                    q.pop();
                    v.push_back(node);
                }
            }
        }

        vs=v;
    }
    
    int insert(int v1) {
        if(vn.size()==0||vn.back()->right!=NULL){         
               if(vs==v){
                 vn=v; 
                v.clear();
               }else{
                  vn=vm;     
               }
           
        }
        for(int i=0;i<vn.size();i++){
            if(vn[i]->left==NULL){
                vn[i]->left=new TreeNode(v1);
                //讲新添加的节点加入到列表中
                vm.push_back(vn[i]->left);
                return vn[i]->val;
            }
            if(vn[i]->right==NULL){
                vn[i]->right=new TreeNode(v1);
                vm.push_back(vn[i]->right);
                return vn[i]->val;
            }
        }
        return -1;

    }
    
    TreeNode* get_root() {
        return root;

    }
};

/**
 * Your CBTInserter object will be instantiated and called as such:
 * CBTInserter* obj = new CBTInserter(root);
 * int param_1 = obj->insert(v);
 * TreeNode* param_2 = obj->get_root();
 */

滑动窗口的平均值

题目来源:leetcode

问题说明

给定一个整数数据流和一个窗口大小,根据该滑动窗口的大小,计算滑动窗口里所有数字的平均值。

实现 MovingAverage 类:

MovingAverage(int size) 用窗口大小 size 初始化对象。
double next(int val)?成员函数 next?每次调用的时候都会往滑动窗口增加一个整数,请计算并返回数据流中最后 size 个值的移动平均值,即滑动窗口里所有数字的平均值。

思路解析

定义3个成员对象 ,size表示初始化的窗口的大小,v用来存储窗口中的元素,sum用来计算窗口中元素的和

在构造函数中初始化窗口的大小,在next函数实现插入功能,首先判断v.size()和窗口大小是不是相等,相等就要删除v的头元素,接着sum减去v的头元素。

当数组v中元素个数还有没有窗口大小的时直接插入数据,最后计算平均值,并返回

代码实现

class MovingAverage {
    int sum=0;
    vector<int> v;
    int size=0;
public:
    /** Initialize your data structure here. */
    MovingAverage(int size) {
        this->size=size;
    }
    
    double next(int val) {
        if(v.size()==size){
            sum-=v[0];
            v.erase(v.begin());
        }
        v.push_back(val);
        sum+=val;
        double d=(sum*1.0)/v.size();
        return d;

    }
};

/**
 * Your MovingAverage object will be instantiated and called as such:
 * MovingAverage* obj = new MovingAverage(size);
 * double param_1 = obj->next(val);
 */

二叉树的右侧视图

题目来源:leetcode

问题说明

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

思路解析

思路:广度优先遍历

思路和树的层序遍历实现过程是一样的,线创建一个队列用来存储每一层的节点。首先讲头节点存储到队列中遍历队列:

(1)保存队列中节点数size

(2)节点出队判断节点的的左子节点和右子节点是不是为NULL,不为NULL直接插入到队列中

(3)判断size是不是到达0当size到达0就说明当前节点为最后一个节点,将节点插入到数组中

(4)遍历队列直到队列为NULL最后然会数组v

代码实现

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
         vector<int>v;
        if(root==NULL){
            return v;
        }
        queue<TreeNode*>q;

        q.push(root);
       
        while(!q.empty()){
            int s=q.size();
 
      
            while(s--){
                TreeNode*root=q.front();
                q.pop();
                if(s==0){
                    v.push_back(root->val);
                }
                if(root->left){
                    q.push(root->left);

                }
                if(root->right){
                    q.push(root->right);

                }


            }
        }
        return v;

    }
};

设计循环队列

题目来源:leetcode

题目说明

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。

思路解析

思路:双指针

用数组来存放元素,begin指向头元素没删除一个元素begin就会往后移动,end指向最后一个元素,当插入一个元素后就会往后移动一个位置。

构造函数实现:初始化循环列表的大小 接着开辟数组容量大小的val

插入函数:先判断首元素有没有插入,没有插入就先插入到首元素接着end++,接着判断队列有没有满,如果满直接返回false,没有满插入end位置同时更新end

删除元素:删除元素时先判断队列是不是为NULL。删除begin位置元素,同时begin往后移动一位并更新begin

判空函数;遍历数组如果全是-1就证明为NULL

判满函数:遍历数组如果没有出现-1就证明为满

代码实现

class MyCircularQueue {
        vector<int>v;
        int size=0;
        int begin=0;
        int end=0;
public:
    MyCircularQueue(int k) {
        size=k;
       
        v.resize(k,-1);


    }
    
    bool enQueue(int value) {
            if((begin==end)&&v[end]==-1){
                    v[begin]=value;
                    return true;
            }
            if(isFull()){
                return false;
            }
            end++;
            if(end>=size){
                end%=size;
            }
            v[end]=value;
            return true;
    }
    
    bool deQueue() {
        if(isEmpty()){
           return false;
        }
        v[begin++]=-1;
        if(begin>=size){
            begin%=size;
        }
        if(begin>=end){
                end=begin;
        }


      return   true;

    }
    
    int Front() {
            if(isEmpty()){
                    return -1;
            }
        return v[begin];

    }
    
    int Rear() {
            if(isEmpty()){
                    return -1;
            }
    
        return v[end];

    }
    
    bool isEmpty() {
       for(int i=0;i<size;i++){
               if(v[i]!=-1){
                       return false;
               }
       }
       return true;

    }
    
    bool isFull() {
       for(int i=0;i<size;i++){
               if(v[i]==-1){
                       return false;
               }
       }
       return true;

    }
};

/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * MyCircularQueue* obj = new MyCircularQueue(k);
 * bool param_1 = obj->enQueue(value);
 * bool param_2 = obj->deQueue();
 * int param_3 = obj->Front();
 * int param_4 = obj->Rear();
 * bool param_5 = obj->isEmpty();
 * bool param_6 = obj->isFull();
 */
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-06-16 21:51:22  更:2022-06-16 21:51:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:01:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码