C++基础算法离散化及区间合并篇

📟作者主页:慢热的陕西人

🌴专栏链接:C++算法

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

主要讲解了双指针,位运算,离散化以及区间合并。

在这里插入图片描述

文章目录

    • Ⅴ. 双指针
    • Ⅵ. 位运算
    • Ⅶ.离散化:
    • Ⅶ. 区间合并

Ⅴ. 双指针

是一种利用单调规律将二重循环的时间复杂度降为O(N)的算法;

例如:剑指 Offer 48. 最长不含重复字符的子字符串 - 力扣(LeetCode)

如果我们用暴力算法的话,肯定是需要O(N)的复杂度,但是我们采用双指针方式可以实现在O(N)的时间复杂度实现

代码:

    int lengthOfLongestSubstring(string s) 
    {
        int map[257] = { 0 };
        int res = 0;
        for(int i = 0; i < s.size(); ++i)
        {
            map[s[i]]++;
            while(map[s[i]] > 1)
            {
                map[s[j]]--;
                ++j;
            }
            res = max(res, i - j + 1);
        }
        return res;
    }

Ⅵ. 位运算

位运算通常是利用二进制的一些性质展开的

例如:剑指 Offer 15. 二进制中1的个数 - 力扣(LeetCode)

class Solution {
public:
    uint32_t lowbit(uint32_t x)
    {
        return (x & ~x + 1);
    }
    int hammingWeight(uint32_t n) 
    {
        int sum = 0;
        while(lowbit(n)) n &= ~lowbit(n), sum++;
        return sum;
    }
};

其中lowbit(n)函数返回的是n的第一个1的数字:例如5(101),他就返回1;

Ⅶ.离散化:

离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。

通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小

有时候我们的数据范围是(0 , 10e9),但是数据的总数却可能只有(0, 10e5), 这时候我们没必要去开10e9的空间,只需要开最大10e5的空间所要离散化的数据映射到这个小空间里;

例如;{1000, 1111, 1200, 1100, 1250}

我们映射下来
[ 1000 − > 1 ] , [ 1100 − > 2 ] , [ 1111 − > 3 ] , [ 1200 − > 4 ] , [ 1250 − > 5 ] [1000->1],[1100->2],[1111->3],[1200->4],[1250->5] [1000>1],[1100>2],[1111>3],[1200>4],[1250>5]
所以我们要实现离散化需要做非常重要的两步:

①如何将离散化后的数据进行去重;

②如何计算出数据离散化后对应的值;

代码如下:

vector<int> alls;//存储待离散化的数据
sort(alls.begin(), alls.end());//排序
alls.erase(unique(alls.begin(), alls.end()), alls.end()); //①对排列好的数据进行去重

//②计算出数据离散化后对应的值
int find(int x)
{
    int l = 0; r = alls.size() - 1;
    while(l < r)
    {
        int mid = (l + r) >> 1;
        if(alls[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1;//根据题意
}

例题:

在这里插入图片描述

测试数据:

//输入
3 3
1 2
3 6
7 5
1 3
4 6
7 8
//输出
8
0
5

代码:

#include<iostream>
#include<vector>
#include<algorithm>

#define N 300010
using namespace std;

typedef pair<int, int> PII;

int a[N], s[N];

vector<int> alls;
vector<PII> add, query;

int n, m;//n次操作, m个区间

int find(int x)
{
    int l = 0, r = alls.size() - 1;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (alls[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1;
}
int main()
{

    cin >> n >>m;
    for (int i = 1; i <= n; ++i)
    {
        int x, c;
        cin >> x >> c;
        add.push_back({x, c});
        alls.push_back(x);
    }
    for (int i = 1; i <= m; ++i)
    {
        int l, r;
        cin >> l >> r;
        query.push_back({ l, r });
        alls.push_back(l);
        alls.push_back(r);
    }

    //去重操作
    sort(alls.begin(), alls.end());
    alls.erase(unique(alls.begin(), alls.end()), alls.end());

    //处理加数
    for (auto item : add)
    {
        int pot = find(item.first);
        a[pot] += item.second;
    }
    //计算前缀和
    for (int i = 1; i <= alls.size(); ++i) s[i] = s[i - 1] + a[i];

    //处理请求
    for (auto item : query)
    {
        int l = find(item.first), r = find(item.second);
        cout << s[r] - s[l - 1] << endl;
    }
    return 0;
}

Ⅶ. 区间合并

给定多个区间,然后将有交集的区间合并(取并集);

处理如下图的功能:

在这里插入图片描述

实现的思路步骤;

①先利用以区间的左端点为标准排序所有的区间。

②合并:

(1)先将第一个区间的端点作为标准stend;

(2)开始遍历后面的区间:

​ 如果区间的左端点小于标准end并且右端点小于标准的end那么就不用进行操作,直接遍历下一个区间;

​ 如果区间的左端点小于标准end并且右端点大于标准的end那么我们就更新标准的end为当前的区间的右端点;

​ 如果区间的左端点大于标准的end那么我们将当前的标准存储起来(已经称为一个合并后的区间),并且开始从(1)开始执行。

在这里插入图片描述

代码:

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

#define N 100010;

typedef pair<int, int>  PII;

int n;

vector<PII> segs;

void merge(vector<PII>& segs)
{
	vector<PII> res;
	sort(segs.begin(), segs.end()); // 按照左端点进行排序

	int st = -2e9, ed = -2e9;
	for (auto seg : segs)
		if (ed < seg.first)//判断是否要产生新的区间
		{
			if (ed != -2e9) res.push_back({ st, ed });//已经满足合并区间的条件,所以将这个区间存储起来
			st = seg.first, ed = seg.second; //即将开始合并新的区间,要将第一个区间的端点作为标准
		}
		else ed = max(ed, seg.second); //判断合并区间的右端点
	
	if (st != -2e9) res.push_back({ st, ed }); // 将最后一个区间存储到答案中

	segs = res;
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; ++i)
	{
		int l, r;
		cin >> l >> r;
		segs.push_back({ l, r });
	}
	 merge(segs);
	cout << segs.size();

	return 0;
}

到这本篇博客的内容就到此结束了。
如果觉得本篇博客内容对你有所帮助的话,可以点赞,收藏,顺便关注一下!
如果文章内容有错误,欢迎在评论区指正

在这里插入图片描述

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

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

相关文章

02 QPushButton的基本使用

Tips: 在使用控件的时候如果没有智能提示&#xff0c;可能是没有包含头文件 在运行时&#xff0c;报【invalid use of xxx】可能是没有包含相关头文件 如果出现中文乱码&#xff1a;设置编译器的编码格式为UTF-8 本节主要包含创建一个按钮控件、显示按钮、设置按钮的父窗口、设…

2023最新ChatGPT商业运营网站源码+支持ChatGPT4.0+新增GPT联网功能+支持ai绘画+实时语音识别输入+用户会员套餐+免费更新版本

2023最新ChatGPT商业运营网站源码支持ChatGPT4.0新增GPT联网功能支持ai绘画实时语音识别输入用户会员套餐免费更新版本 一、AI创作系统二、系统程序下载三、系统介绍四、安装教程五、主要功能展示六、更新日志 一、AI创作系统 提问&#xff1a;程序已经支持GPT3.5、GPT4.0接口…

SpringBoot——自动装配之@Import

文章目录 前言ImportImport 的作用1、Import(MyDemo1.class) 将某个对象加载至bean容器中2、Import一个类 该类实现了ImportSelector, 重写selectImports方法该方法返回了String[]数组的对象&#xff0c;数组里面的类都会注入到spring容器当中3、Import一个类&#xff0c;该类实…

解放研究者:GPT自动化科研

GPT Researcher 是一个自主代理程序&#xff0c;旨在进行多种任务的全面在线研究。 该代理能够生成详细、事实性和公正的研究报告&#xff0c;并提供个性化选项&#xff0c;以便关注相关资源、大纲和教训。受到AutoGPT和最近的Plan-and-Solve论文的启发&#xff0c;GPT Researc…

图像标注是什么?及其类型和应用

什么是图像标注&#xff1f; 图像标注是与您交互的许多人工智能产品的基础&#xff0c;并且是计算机视觉&#xff08;CV&#xff09;领域重要的过程之一。在图像标注过程中&#xff0c;数据标注员使用标签或元数据来标记AI模型学习识别的数据特征。然后&#xff0c;这些图像标…

线程池学习(六)线程池状态转化

线程池状态定义 // runState is stored in the high-order bits // 线程池创建之后的初始状态&#xff0c;这种状态下可以执行任务private static final int RUNNING -1 << COUNT_BITS; // 线程池不再接收新的任务&#xff0c;但是会将队列中的任务执行完 private s…

解决apkanalyzer.bat could NOT be found in D:\Download\Android SDK Tools!警告报错

appium安装过程中很可能出现以下警告报错&#xff0c;咱就按如下操作即可搞定&#xff01;&#xff01;&#xff01; apkanalyzer.bat could NOT be found in D:\Download\Android SDK Tools! 一、下载Command line tools 下载地址&#xff1a;​https://developer.android.g…

Jenkins (一)

Jenkins (一) Docker Jenkins 部署 一. 安装 jenkins $ mkdir -p /home/tester/data/docker/jenkins $ vim jenkins:lts-jdk11.sh./jenkins:lts-jdk11.sh 内容 #! /bin/bash mkdir -p /home/tester/data/docker/jenkins/jenkins_homesudo chown -R 1000:1000 /home/tester/da…

基于simulink的DPLL仿真笔记

该笔记主要用于本人思路整理与记录 本设计运用的是电荷泵一阶环路滤波器&#xff0c;二阶三阶则在此基础上举一反三&#xff0c;以后如有机会会慢慢补全 文章目录 一.仿真模型PS&#xff08;题外话&#xff09; 二.仿真结果三.环路滤波器分析1. 环路滤波器对比LPF2. 环路滤波器…

从零开发短视频电商 单元测试(TestNG)

文章目录 简介简单示例执行测试并查看测试报告方式一 在IDEA中运行testng.xml文件方式二 在IDEA中运行测试类或者package方式三 在Maven中运行测试 统计测试覆盖率方式一 IDEA 支持详细的代码测试覆盖率统计方式二 Maven支持测试覆盖率 在IDEA中创建测试用例使用 IDEA 快速创建…

ELK搭建

ELK介绍&#xff1a; ELK是一组开源工具的缩写&#xff0c;它由Elasticsearch、Logstash和Kibana三个组件组成&#xff0c;用于处理、分析和可视化大量日志数据。 入门级ELK搭建&#xff08;无Docker环境&#xff09; 安装前准备 1.获取安装包 https://artifacts.elastic…

【InsCode Stable Diffusion 美图活动一期】生成着玩

此为内容创作模板&#xff0c;请按照格式补充内容&#xff0c;在发布之前请将不必要的内容删除 一、 Stable Diffusion 模型在线使用地址&#xff1a; https://inscode.csdn.net/inscode/Stable-Diffusion 二、模型相关版本和参数配置&#xff1a; 三、图片生成提示词与反向…

【Docker】详解docker安装及使用

详解docker安装及使用 1. 安装docker1.1 查看docker版本信息 2. Docker镜像操作3. Docker容器操作4.知识点总结4.1 docker镜像操作4.2 docker容器操作4.3 docker run启动过程 参见docker基础知识点详解 1. 安装docker 目前Docker只能支持64位系统。 ###关闭和禁止防火墙开机自…

Hadoop: High Available

序言 在Hadoop 2.X以前的版本&#xff0c;NameNode面临单点故障风险&#xff08;SPOF&#xff09;&#xff0c;也就是说&#xff0c;一旦NameNode节点挂了&#xff0c;整个集群就不可用了&#xff0c;而且需要借助辅助NameNode来手工干预重启集群&#xff0c;这将延长集群的停…

Windows 组策略 部署打印机

一、服务端 1、打印机管理&#xff1a;添加打印机 2、选择打印机 3、第一次安装&#xff0c;选择这个 4、下载驱动&#xff0c;从磁盘安装 5、已成功安装 6、选中打印机右击属性&#xff1a;列出目录 7、创建一个组策略 8、组策略设置 用户设置 → 首选项 → 控制面板 → 打印…

C++day4 (拷贝构造函数、拷贝赋值函数、匿名对象、友元函数、常成员函数、常对象、运算符重载)

#include <iostream> #include <cstring> using namespace std;class mystring { private:char *str; //记录C风格字符串int size; //记录字符串的实际长度public://无参构造mystring():size(10){strnew char[size];//构造出一个长度为10的字符串strcpy(str,&…

22.代理模式

代理模式 二十三种设计模式中的一种&#xff0c;属于结构型模式。它的作用就是通过提供一个代理类&#xff0c;在调用目标方法的时候&#xff0c;不再是直接对目标方法进行调用&#xff0c;而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦…

移动端深度学习部署:TFlite

1.TFlite介绍 &#xff08;1&#xff09;TFlite概念 tflite是谷歌自己的一个轻量级推理库。主要用于移动端。 tflite使用的思路主要是从预训练的模型转换为tflite模型文件&#xff0c;拿到移动端部署。 tflite的源模型可以来自tensorflow的saved model或者frozen model,也可…

初识protobuf

Protobuf 全称Protocol Buffers&#xff08;协议缓冲区&#xff09;&#xff0c;是一种轻量级、高效的数据序列化格式&#xff0c;由Google开发。它被设计用于结构化数据的序列化、反序列化以及数据交换&#xff0c;常用于网络通信和数据存储等领域。 Protobuf使用简洁的消息描…

解决appium-doctor报 bundletool.jar cannot be found

一、下载bundletool.jar 下载地址&#xff1a;https://github.com/google/bundletool/releases 二、重命名 重命名这个jar包为bundletool.jar&#xff0c;在android sdk目录下&#xff0c;新建bundle-tool目录&#xff0c;把bundletool.jar包放入其中。 三、配置环境 path后追加…