【算法】双指针、位运算、离散化、合并区间

news2024/11/17 7:55:31

文章目录

    • 1.双指针
    • 2.位运算
    • 3.离散化
    • 4.区间合并

1.双指针

双指针的算法可以优化时间复杂度,双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向( 快慢指针 )或者相反方向( 对撞指针 )的指针进行扫描,从而达到相应的目的。将双层暴力循环O(n^2)优化到O(n),所以双指针算法最核心的用途就是优化时间复杂度。双指针是比较常见的把,直接看例子既可以。

给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。

输入格式

第一行包含整数 n。

第二行包含 n 个整数(均在 0∼1050∼105 范围内),表示整数序列。

输出格式

共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。

数据范围

1≤n≤1051≤n≤105

输入样例:

5
1 2 2 3 5

输出样例:

3
#include <iostream>
using namespace std;

const int N = 100010;

int n;
int a[N],s[N];

int main()
{
    cin>>n;
    for(int i = 0;i<n;i++) cin>>a[i];
    int res = 0;
    for(int i = 0,j=0;i<n;i++)
    {
        s[a[i]]++;
        while(s[a[i]]>1)
        {
            s[a[j]]--;
            j++;
        }
        res = max(res,i-j+1);
    }
    cout<<res<<endl;
    return 0;
}

2.位运算

位运算也是非常常见的,位运算就是直接对整数在内存中的二进制位进行 操作,这里简单过一下即可,同时对于这部分不太熟悉的,建议先熟悉一下位运算的相关操作,以及整数二进制存储的内容

常见的有:1.比如求一个数n以二进制方式表示,第k位数字是几:把第k位移到最后一位既n>>k,然后看此时的个位是几,&1即可

2.lowbit(x):返回x的最后一位1。lowbit()的实现就是在x&-x. 怎么理解-x:对于一个整数的负数是原数的补码,相当于 -x=~x+1

也就是说x&-x相当于x&(~x+1)

image-20221228153143281

可以统计1的个数

题目练习:

给定一个长度为 nn 的数列,请你求出数列中每个数的二进制表示中 11 的个数。

输入格式

第一行包含整数 nn。

第二行包含 nn 个整数,表示整个数列。

输出格式

共一行,包含 nn 个整数,其中的第 ii 个数表示数列中的第 ii 个数的二进制表示中 11 的个数。

数据范围

1≤n≤1000001≤n≤100000,
0≤数列中元素的值≤1090≤数列中元素的值≤109

输入样例:

5
1 2 3 4 5

输出样例:

1 1 2 1 2
#include <iostream>
 using namespace std;
 
 int lowbit(int x)
 {
     return x&-x;
 }
 int main()
 {
     int n;
     cin>>n;
     while(n--)
     {
         int x;
         cin>>x;
         int res = 0;
         while(x)
         {
             x-=lowbit(x);
             res++;
         }
         cout<<res<<' ';
     }
     return 0;
 }

3.离散化

这里的离散化指的是特指整数有序的离散化,保序的离散化:值域比较大,但是个数却很少,类似哈希,以里面的值为下标来做即可,不需要开很大的数组,只需要进行映射即可。一个问题是去重,另一个问题是如何具体算出a[i]离散化的值是多少,a是有序的自然可以通过二分进行查找,而去重可以利用unique函数

假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。

现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。

接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r][l,r] 之间的所有数的和。

输入格式

第一行包含两个整数 n 和 m。

接下来 n 行,每行包含两个整数 x 和 c。

再接下来 m 行,每行包含两个整数 l 和 r。

输出格式

共 m行,每行输出一个询问中所求的区间内数字和。

数据范围

−109≤x≤109−109≤x≤109,
1≤n,m≤1051≤n,m≤105,
−109≤l≤r≤109−109≤l≤r≤109,
−10000≤c≤10000

输入样例:

3 3
1 2
3 6
7 5
1 3
4 6
7 8

输出样例:

8
0
5
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 300010; 
int n, m;
int a[N];
int s[N];
vector<int> alls; 
vector<pair<int, int>> add, query; 

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() 
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) 
    {
        int x, c;
        scanf("%d%d", &x, &c);
        add.push_back({x, c});
        alls.push_back(x);
    }
    for (int i = 1; i <= m; i++) 
    {
        int l , r;
        scanf("%d%d", &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 x = find(item.first);
        a[x] += 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);
        int r = find(item.second);
        printf("%d\n", s[r] - s[l-1]);
    }
    return 0;
}

4.区间合并

简单理解为2个有交集的区间合并成一个更大的区间即可,区间合并就是快速让我们把有交集的区间进行合并。

区间的合并先按左端点进行排序,然后去进行维护:image-20221231085523439

给定 n 个区间 [li,ri][li,ri],要求合并所有有交集的区间。

注意如果在端点处相交,也算有交集。

输出合并完成后的区间个数。

例如:[1,3][1,3] 和 [2,6][2,6] 可以合并为一个区间 [1,6][1,6]。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含两个整数 l和 r。

输出格式

共一行,包含一个整数,表示合并区间完成后的区间个数。

数据范围

1≤n≤1000001≤n≤100000,
−109≤li≤ri≤109−109≤li≤ri≤109

输入样例:

5
1 2
2 4
5 6
7 8
7 9

输出样例:

3
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int n;

typedef pair<int,int> PII;
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(st!=-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()<<endl;
    return 0;
}

合并区间比较常见把:比如leetcode的56合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> result;
        sort(intervals.begin(),intervals.end());
        int begin = intervals[0][0],end = intervals[0][1];
        for(size_t i = 0;i<intervals.size();i++)
        {
            if(intervals[i][0]>end)
            {
                result.push_back({begin,end});
                begin = intervals[i][0];
                end = intervals[i][1];
            }
            else
            {
                end = max(end,intervals[i][1]);
            }
        }
        result.push_back({begin,end});
        return result;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL调优SQLSERVER 数据页

1. 什么是数据页 一般来说&#xff0c;对大块资源或者数据进行高效管理都会按照一定粒度来划分的&#xff0c;比如说 Windows 对内存的管理就是按照 内存页 (4k) 来进行划分&#xff0c;言外之意就是 SQLSERVER 对 mdf 的管理也是按照 数据页 &#xff08;8k) 来划分的&#x…

(小记)matlab散点图

Matlab散点图两种画法一、plot画散点图二、scatter画散点图三、matlab工具画散点图plot画我可以设置坐标轴之类的&#xff0c;方便论文使用&#xff1b;scatter没设置成功。一、plot画散点图 参考&#xff1a;matlab中二维散点图,MATLAB实例&#xff1a;二维散点图 自用代码 …

一站式迁移,人大金仓助力保险业务无感升级

2021年3月&#xff0c;国家发布《中华人民共和国国民经济和社会发展第十四个五年规划和2035年远景目标纲要》&#xff0c;纲要明确提出“稳妥发展金融科技&#xff0c;加快金融机构数字化转型”、“推进金融业信息化核心技术安全可控&#xff0c;维护金融基础设施安全”。2022年…

如果通过股价均线分析股票

目录如果通过股价均线分析股票获取数据为什么要计算均价计算均价分析结果如果通过股价均线分析股票 获取数据 股票数据获取渠道非常丰富&#xff0c;可以通过上一篇文章 各大股票开放接口介绍中接口获取数据&#xff0c;需要提供技术支持的可以私聊。 为什么要计算均价 股票…

MongoDB:基础概述

MongoDB 是一个开源的、跨平台的、面向文档的、基于分布式文件存储的数据库系统&#xff0c;MongoDB 是由 C 语言开发&#xff0c;旨在为 Web 应用提供可扩展的高性能数据存储解决方案。在高负载的情况下&#xff0c;通过添加更多的节点&#xff0c;可以保证服务器性能。 本篇内…

【技术分享】无纸化会议|智慧教室同屏走RTSP组播还是RTMP?

技术背景 我们在做内网多人同屏&#xff08;比如无纸化会议、智慧教室同屏&#xff09;技术方案的时候&#xff0c;遇到个问题&#xff1a;到底使用轻量级RTSP服务实现组播&#xff0c;还是基于RTMP的解决方案&#xff1f; 先说为什么大家喜欢组播吧&#xff1a; 组播技术方…

js实现复制粘贴剪切功能

文章目录js实现复制粘贴功能方式一&#xff1a;原生方式实现复制粘贴剪切&#xff08;不推荐&#xff09;方式二&#xff1a;浏览器自带clipboard API实现复制粘贴&#xff08;推荐&#xff09;简介特点clipboard对象及相关APIClipboard.readText()Clipboard.read()Clipboard.w…

二叉树之红黑树

红黑树的起源 二分查找具有Ologn的时间复杂度&#xff0c;使用二分查找的基础是数据有序。很明显数组可以完成这一条件&#xff0c;但是数组也有缺点&#xff0c;扩容&#xff0c;增加&#xff0c;删除非常不方便。而链表则没有这些缺点&#xff0c;但是链表却不满足随机存取&…

第二十七讲:神州路由器PPP CHAP认证的配置

实验拓扑图如下所示 操作步骤&#xff1a; 步骤1&#xff1a;连接网络拓扑图。 步骤2&#xff1a;RouterA基本配置。 Router>enable &#xff01;进入特权模式 Router#config &#xff01;进入全局配置模式 …

React jsx 简介与一些语法规则

什么是 Jsx 简单例子&#xff1a; //create virtual dom , single quotes is not needconst VDOM <h1> Hello, React </h1> //appy virtual dom to pageReactDOM.render(VDOM, document.getElementById("test")) //first parameter is virtual dom, …

2022,我们追逐群星,也在追逐AIGC的无尽可能

2022年&#xff0c;是中国人追逐群星的里程碑之年。今年10月31日&#xff0c;中国天宫空间站的第二个科学实验模块——梦天实验舱&#xff0c;搭载长征五号B遥四运载火箭发射升空。随着之后天实验舱成功与之前发射的天和核心舱完成精准对接&#xff0c;中国空间站历史性地完成了…

使用支付宝沙盒 nodejs

1、 进入官网 https://auth.alipay.com/login/index.html 登录 2、下载秘钥转换工具 https://render.alipay.com/p/f/fd-jwq8nu2a/pages/home/index.html 3、生成密钥 注意&#xff0c;此时得到的应用私钥的格式是不对的&#xff0c;应用格式转换转换格式 4、通过3中的应用公钥…

并发编程——2.Java 线程

目录2.Java 线程2.1.创建和运行线程2.1.1.方法一&#xff1a;直接使用 Thread 类2.1.2.方法二&#xff1a;使用 Runnable 接口配合 Thread2.1.3.方法三&#xff1a;使用 FutureTask 配合 Thread2.2.观察多个线程同时运行2.3.查看进程线程的方法2.4.原理之线程运行2.5.线程的常见…

React学习06-React Router 6

React Router 6 概述 React Router 以三个不同的包发布到 npm 上&#xff0c;它们分别为&#xff1a; react-router: 路由的核心库&#xff0c;提供了很多的&#xff1a;组件、钩子。react-router-dom: 包含react-router所有内容&#xff0c;并添加一些专门用于 DOM 的组件&…

Elasticsearch处理表关联关系的N种方式

Elasticsearch处理表关联关系是比较复杂的问题&#xff0c;处理不好会出现性能问题、数据一致性问题等&#xff1b; 今天我们特意分享一下几种方式&#xff0c;对象类型&#xff08;宽表&#xff09;、嵌套类型、父子关联关系、应用端关联&#xff0c;每种方式都有特定的业务需…

CycloneDDS(3)安全Security

本规范定义了符合DDS实现的安全模型和服务插件接口(SPI)架构。DDS安全模型通过DDS实现调用这些SPI来实现。 构成DDS安全模型的三个插件是: 1、身份验证服务插件 提供验证调用DDS操作的应用程序和/或用户身份的方法。包括在参与者之间执行相互身份验证和建立共享秘密的设施…

深度学习模型训练的tricks总结

学习率角度 学习率是一个非常非常重要的超参数&#xff0c;这个参数呢&#xff0c;面对不同规模、不同batch-size、不同优化方式、不同数据集&#xff0c;其最合适的值都是不确定的&#xff0c;我们无法光凭经验来准确地确定lr的值&#xff0c;我们唯一可以做的&#xff0c;就…

从零开始配置vim(30)——DAP的其他配置

很抱歉这么久才来更新这一系列&#xff0c;主要是来新公司还在试用期&#xff0c;我希望在试用期干出点事来&#xff0c;所以摸鱼的时间就少了。加上前面自己阳了休息了一段时间。在想起来更新就过去一个多月了。废话不多说了&#xff0c;让我们开始进入正题。 在前一章&#…

JUC 并发进阶学习(一)

该学习笔记是本人依据相关的学习视频整体汇总&#xff0c;相关的视频学习可以自己去搜看看。 【狂神说Java】JUC并发编程最新版通俗易懂_哔哩哔哩_bilibili 一、什么是JUC 从中就可以看出JUC&#xff0c;实质就是三个包&#xff0c;后面晖详细说明三个包下各个类功能。 java.…

程序员的测试课

git项目地址&#xff1a;GitHub - dreamhead/geektime-todo: Geektime Todo is a demo todo project for Geektime column. 1、实现一个Todo应用 设计规范 1、对于输入参数的检测&#xff0c;由入口部分代码进行处理。如空字符串。 2、Repository 的问题以运行时异常 的形式抛…