LeetCode刷题【树状数组、并查集】

目录

  • 树状数组
    • 307. 区域和检索 - 数组可修改
      • 406. 根据身高重建队列
      • 673. 最长递增子序列的个数
      • 1409. 查询带键的排列
  • 并查集
      • 128. 最长连续序列
      • 130. 被围绕的区域

树状数组

307. 区域和检索 - 数组可修改

给你一个数组 nums ,请你完成两类查询。

其中一类查询要求 更新 数组 nums 下标对应的值
另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 ,其中 left <= right

实现 NumArray 类:

NumArray(int[] nums) 用整数数组 nums 初始化对象
void update(int index, int val) 将 nums[index] 的值 更新 为 val
int sumRange(int left, int right) 返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 (即,nums[left] + nums[left + 1], ..., nums[right])
class NumArray {
private:
    vector<int> tree;
    vector<int> &nums;
    int lowBit(int x){
        return x & -x;
    }
    void add(int index, int val){
        while(index < tree.size()){
            tree[index] += val;
            index += lowBit(index);
        }
    }
    int prefixSum(int index){
        int sum = 0;
        while(index > 0){
            sum += tree[index];
            index -= lowBit(index);
        }
        return sum;
    }

public:
    NumArray(vector<int>& nums) : tree(nums.size() + 1), nums(nums) {
        for(int i = 0; i < nums.size(); i++){
            add(i + 1, nums[i]);
        }
    }
    
    void update(int index, int val) {
        add(index + 1, val - nums[index]);
        nums[index] = val;
    }
    
    int sumRange(int left, int right) {
        return prefixSum(right + 1) - prefixSum(left);
    }
};

406. 根据身高重建队列

假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。

请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

示例 1:
输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
解释:
编号为 0 的人身高为 5 ,没有身高更高或者相同的人排在他前面。
编号为 1 的人身高为 7 ,没有身高更高或者相同的人排在他前面。
编号为 2 的人身高为 5 ,有 2 个身高更高或者相同的人排在他前面,即编号为 0 和 1 的人。
编号为 3 的人身高为 6 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
编号为 4 的人身高为 4 ,有 4 个身高更高或者相同的人排在他前面,即编号为 0、1、2、3 的人。
编号为 5 的人身高为 7 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新构造后的队列。
class Solution {
public:
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(), people.end(), [](const vector<int>& u, const vector<int>& v){
            return u[0] < v[0] || (u[0] == v[0] && u[1] > v[1]);
        });
        int n = people.size();
        vector<vector<int>> ans(n);
        for(vector<int>& person : people){
            int spaces = person[1] + 1;
            for(int i = 0; i < n; i++){
                if(ans[i].empty()){
                    spaces--;
                    if(!spaces){
                        ans[i] = person;
                        break;
                    }
                }
            }
        }
        return ans;
    }
};

673. 最长递增子序列的个数

给定一个未排序的整数数组 nums , 返回最长递增子序列的个数 。

注意 这个数列必须是 严格 递增的。

示例 1:
输入: [1,3,5,4,7]
输出: 2
解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。
class Solution {
public:
    int findNumberOfLIS(vector<int>& nums) {
        int n = nums.size();
        vector<int> dp(n, 1), cnt(n, 1);
        int maxs = 1;
        int count = 0;
        for(int i = 0; i < n; i++){
            for(int j = 0; j < i; j++){
                if(nums[j] < nums[i]){
                    if(dp[i] < dp[j] + 1){
                        dp[i] = dp[j] + 1;
                        cnt[i] = cnt[j];
                    }
                    else if(dp[i] == dp[j] + 1){
                        cnt[i] += cnt[j];
                    }
                }
            }
            if(dp[i] > maxs){
                maxs = dp[i];
                count = cnt[i];
            }
            else if(dp[i] == maxs){
                count += cnt[i];
            }
        }
        return count;
    }
};

1409. 查询带键的排列

给定一个正整数数组 queries ,其取值范围在 1 到 m 之间。 请你根据以下规则按顺序处理所有 queries[i](从 i=0 到 i=queries.length-1):

首先,你有一个排列 P=[1,2,3,...,m]。
对于当前的 i ,找到 queries[i] 在排列 P 中的位置(从 0 开始索引),然后将它移到排列 P 的开头(即下标为 0 处)。注意, queries[i] 的查询结果是 queries[i] 在 P 中移动前的位置。

返回一个数组,包含从给定 queries 中查询到的结果。

示例 1:
输入:queries = [3,1,2,1], m = 5
输出:[2,1,2,1] 
解释:处理 queries 的过程如下:
对于 i=0: queries[i]=3, P=[1,2,3,4,5], 3 在 P 中的位置是 2,然后我们把 3 移动到 P 的开头,得到 P=[3,1,2,4,5] 。
对于 i=1: queries[i]=1, P=[3,1,2,4,5], 1 在 P 中的位置是 1,然后我们把 1 移动到 P 的开头,得到 P=[1,3,2,4,5] 。 
对于 i=2: queries[i]=2, P=[1,3,2,4,5], 2 在 P 中的位置是 2,然后我们把 2 移动到 P 的开头,得到 P=[2,1,3,4,5] 。
对于 i=3: queries[i]=1, P=[2,1,3,4,5], 1 在 P 中的位置是 1,然后我们把 1 移动到 P 的开头,得到 P=[1,2,3,4,5] 。 
因此,包含结果的数组为 [2,1,2,1] 。  
struct BIT{
    vector<int> a;
    int n;
    BIT(int _n): n(_n), a(_n + 1){}
    static int lowbit(int x){
        return x & (-x);
    }
    int query(int x){
        int ret = 0;
        while(x){
            ret += a[x];
            x -= lowbit(x);
        }
        return ret;
    }
    void update(int x, int dt){
        while(x <= n){
            a[x] += dt;
            x += lowbit(x);
        }
    }
};

class Solution {
public:
    vector<int> processQueries(vector<int>& queries, int m) {
        int n = queries.size();
        BIT bit(m + n);
        
        vector<int> pos(m + 1);
        for (int i = 1; i <= m; ++i) {
            pos[i] = n + i;
            bit.update(n + i, 1);
        }
        
        vector<int> ans;
        for (int i = 0; i < n; ++i) {
            int& cur = pos[queries[i]];
            bit.update(cur, -1);
            ans.push_back(bit.query(cur));
            cur = n - i;
            bit.update(cur, 1);
        }
        return ans;
    }
};

并查集

128. 最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

使用哈希表,先找到最小的元素,再遍历,我之前的方法是直接使用sort(nums.begin(), nums.end());

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_set<int> num_set;
        for(int num : nums){
            num_set.insert(num);
        }
        int longstStreak = 0;
        for(int num : num_set){
            if(!num_set.count(num - 1)){
                int currentNum = num;
                int currentStreak = 1;
                while(num_set.count(currentNum + 1)){
                    currentNum += 1;
                    currentStreak += 1;
                }
                longstStreak = max(longstStreak, currentStreak);
            }
        }
        return longstStreak;
    }
};

130. 被围绕的区域

给你一个 m x n 的矩阵 board ,由若干字符 ‘X’ 和 ‘O’ ,找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
在这里插入图片描述

考虑边界上的‘O’,将其置为‘A’,之后再对矩阵中剩下的‘O’进行操作。

class Solution {
public:
    int n, m;
    void dfs(vector<vector<char>>& board, int x, int y){
        if(x < 0 || x >= n || y < 0 || y>= m || board[x][y] != 'O'){
            return;
        }
        board[x][y] = 'A';
        dfs(board, x + 1, y);
        dfs(board, x - 1, y);
        dfs(board, x, y + 1);
        dfs(board, x, y - 1);
    }
    void solve(vector<vector<char>>& board) {
        n = board.size();
        if(n == 0){
            return;
        }
        m = board[0].size();
        for(int i = 0; i < n; i++){
            dfs(board, i, 0);
            dfs(board, i, m - 1);
        } 
        for(int i = 1; i < m - 1; i++){
            dfs(board, 0, i);
            dfs(board, n - 1, i);
        }
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(board[i][j] == 'A'){
                    board[i][j] = 'O';
                }
                else if(board[i][j] == 'O'){
                    board[i][j] = 'X';
                }
            }
        }         
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/472082.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EasyExcel模板填充list时按第一行格式合并单元格(含分页线设置)

前言&#xff1a; 在使用easyExcel填充list时&#xff0c;第一行存在合并单元格的情况下&#xff0c;后面使用forceNewRow()填充的行却没有合并样式。 模板&#xff1a; 填充后&#xff1a; 自定义拦截器&#xff1a; 根据官方文档的提示&#xff0c;我们需要自定义拦截器来…

21个 JVM 技术点详解(附面试解答)

最近兄弟们面试&#xff0c;都逃不过被 JVM 问题轰炸的命运&#xff0c;为啥面试官喜欢拿 JVM 说事呢&#xff1f;V 哥认为&#xff0c;除了要问倒你&#xff0c;就是要压你薪水&#xff0c;咱绝对不能怂&#xff0c;俗话说的好&#xff1a;兵来将挡&#xff0c;水来土掩&#…

VS+QT Debug正常但Release无法识别头文件

&#xff01;&#xff01;&#xff01;&#xff0c;这个问题一般是在第一次编译的时候遇见的&#xff0c;包括之前使用debug也是 在Qt Installation一定要修改成自己版本的编译器&#xff0c;修改一次以后基本是不用再修改的

力扣---括号生成---回溯---dfs/二进制

暴力--二进制 采用与&#xff1a;力扣---子集---回溯&#xff08;子集型回溯&#xff09;---递归-CSDN博客 中二进制求解一样的思路&#xff0c;即遍历0~-1&#xff08;从二进制去考虑&#xff09;&#xff0c;如果这个数的第 i 位为0&#xff0c;则括号的第 i 位为‘&#xff…

记一次Oracle 19C RAC 在线更换数据盘和OCR盘操作记录

欢迎您关注我的公众号【尚雷的驿站】 **************************************************************************** 公众号&#xff1a;尚雷的驿站 CSDN &#xff1a;https://blog.csdn.net/shlei5580 墨天轮&#xff1a;https://www.modb.pro/u/2436 PGFans&#xff1a;ht…

华为ensp中rip动态路由协议原理及配置命令(详解)

CSDN 成就一亿技术人&#xff01; 作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; CSDN 成就一亿技术人&#xff01; ————前言————— RIP&#xff08;Routing Information Protocol&#xff0c;路由信息协议&#xff09;是一种距离矢…

【Java】Oracle发布Java22最新版本

甲骨文&#xff08;ORACLE&#xff09;已经于2023年3月19日正式发布了最新版本的JDK&#xff0c;版本号&#xff1a;22 根据官方声明&#xff0c;Java 22 (Oracle JDK 22) 在性能、稳定性和安全性方面进行了数千种改进&#xff0c;包括对Java 语言、其API 和性能&#xff0c;以…

raid规划配置

一 raid基本知识 1、RAID磁盘阵列概述 磁盘阵列的全名&#xff08;Redundant Arrays of Inexpensive Disk&#xff0c;RAID&#xff09;&#xff0c;中文简称是独立冗余磁盘阵列。 RAID可以通过技术&#xff08;软件或者硬件&#xff09;将多个独立的物理硬盘整合成为一个较大…

探索山海鲸可视化:相较于Excel的独特优势分析

作为一名新用户&#xff0c;我近期开始接触并尝试使用山海鲸可视化工具&#xff0c;这款软件最初吸引我的点在其免费可视化编辑、本地化部署的特点&#xff0c;用了一段时间后&#xff0c;我发现相较于之前使用的Excel来制作可视化看板&#xff0c;两者在多个方面有着显著的区别…

electron-builder允许安装时请求提升权限

场景 在下面的场景中可能会需要管理员权限&#xff1a; electron开发的软件具有文件操作功能&#xff0c;如果electron安装到C盘&#xff0c;并操作项目中&#xff08;C盘&#xff09;的文件&#xff0c;就会因权限不足报错。electron需要操作注册表等系统级关键配置某些命令…

浅尝大菠萝Pinia

1、pinia简介 Pinia&#xff08;发音为 /piːnjʌ/&#xff0c;类似于英语中的“peenya”&#xff09;是最接近有效包名 pia&#xff08;西班牙语中的_pineapple_&#xff09;的词。 Pinia 是由 Vue.js 团队成员开发&#xff0c;新一代的状态管理器&#xff0c;即 Vuex5.x。 …

Godot 学习笔记(2):信号深入讲解

文章目录 前言相关链接环境信号简单项目搭建默认的信号先在label里面预制接收函数添加信号 自定义无参数信号为了做区分&#xff0c;我们在label新增一个函数 自定义带参数信号Button代码label代码连接信号 自定义复杂参数信号自定义GodotObject类ButtonLabel连接信号 父传子Ca…

如何查看zip文件的MD5码

目录 Windows macOS 和 Linux 要查看zip文件的MD5码&#xff0c;你可以使用不同的方法&#xff0c;具体取决于你使用的操作系统。以下是一些常见平台的指导&#xff1a; Windows 可以使用PowerShell来计算文件的MD5码。打开PowerShell&#xff0c;然后使用以下命令&#xf…

wireshark 使用实践

1、打开wireshark软件&#xff0c;选择网卡&#xff0c;开始抓包 2、打开浏览器&#xff0c;访问一个http网站&#xff1a;这里我用 【邵武市博物馆】明弘治十一年&#xff08;1498&#xff09;铜钟_文物资源_福建省文 测试&#xff0c;因为它是http的不是https&#xff0c;方…

基于深度学习的场景文本检测

CTPN 简介&#xff1a; 基于目标检测方法的文本检测模型&#xff0c;在Faster RCNN的基础上进行了改进&#xff0c;并结合双向LSTM增强了序列提取特征&#xff0c;通过anchor和gt的设计将文本检测任务转化为一连串小尺度文本框的检测。 解决问题&#xff1a; 文本长短不一&…

jenkins gradle 编译时jvm不足情况

gradle 编译时jvm不足情况 #开启线程守护&#xff0c;第一次编译时开线程&#xff0c;之后就不会再开了org.gradle.daemontrue#配置编译时的虚拟机大小org.gradle.jvmargs-Xmx2048m -XX:MaxPermSize512m -XX:HeapDumpOnOutOfMemoryError -Dfile.encodingUTF-8#开启并行编译&…

JL15-400/11过电流继电器 400A 一开一闭 380V 柜内安装JOSEF约瑟

系列型号 JL15-1.5/11电流继电器JL15-2.5/11电流继电器 JL15-5/11电流继电器JL15-10/11电流继电器 JL15-15/11电流继电器JL15-20/11电流继电器 JL15-30/11电流继电器JL15-40/11电流继电器 JL15-60/11电流继电器JL15-80/11电流继电器 JL15-100/11电流继电器JL15-150/11电流…

顺序表的动态分配基本操作

#include <stdio.h> #include <stdlib.h>// 顺序表存储空间动态分配 #define InitSize 10 // 顺序表初始长度 typedef int ElemType; // int类型重命名为ElemType&#xff0c;方便后续调整typedef struct { // 定义结构体ElemType *data; // 用静…

LeetCode 刷题 --- 快速幂

前言&#xff1a; 幂运算是一种常见的运算&#xff0c;求取a^n,最容易想到的方法便是通过循环逐个累乘&#xff0c;其复杂度为O(n)&#xff0c;这在很多时候是不够快的&#xff0c;所以我们需要一种算法来优化幂运算的过程。 快速幂&#xff0c;二进制取幂&#xff08;Binary…

Transformer的前世今生 day03(Word2Vec、如何使用在下游任务中)

前情回顾 由上一节&#xff0c;我们可以得到&#xff1a; 任何一个独热编码的词都可以通过Q矩阵得到一个词向量&#xff0c;而词向量有两个优点&#xff1a; 可以改变输入的维度&#xff08;原来是很大的独热编码&#xff0c;但是我们经过一个Q矩阵后&#xff0c;维度就可以控…