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 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 6 - 寻找右区间 -> 正文阅读

[数据结构与算法]6 - 寻找右区间

题目:给你一个区间数组 intervals ,其中 intervals[i] = [starti, endi] ,且每个 starti不同

区间 i 的右侧区间可以记作区间 j ,并满足 startj >= endi ,且 startj 最小化

返回一个由每个区间 i 的右侧区间在 intervals 中对应下标组成的数组。如果某个区间 i 不存在对应的右侧区间 ,则下标 i 处的值设为 -1 。

在这里插入图片描述
解法:

  1. 一开始的思路是在最外层遍历每个区间的右端点intervals[i][1]记为right,里面一层遍历每个区间的左端点intervals[j][0]记为left,如果left>=right,这里要分两种情况:
  • 如果right还没有找到右侧区间则直接将left的索引放入容器的对应位置,
  • 如果right已经找到右侧区间,此时就需要将这两个left作比较,将最小的left的索引放入容器的对应位置。

时间复杂度是O(n^2),空间复杂度是O(1)。这种方法运行会超时。

class Solution {
public:
	vector<int> findRightInterval(vector<vector<int>>& intervals) {
	    vector<int> v;
	    for (int i = 0; i < intervals.size(); i++)
	    {
	        int right = intervals[i][1];
	        int j = 0;
	        for (; j < intervals.size(); j++)
	        {
	            int left = intervals[j][0];
	            if (left >= right)
	            {
	                if (i != v.size() - 1)
	                {
	                    v.push_back(j);
	                }
	                else
	                {
	                    if (v.back() > left)
	                    {
	                        v.pop_back();
	                        v.push_back(j);
	                    }
	                }
	            }
	        }
	        if (i != v.size() - 1)
	        {
	            v.push_back(-1);
	        }
	    }
	    return v;
	}
};
  1. 排序+二分查找
    首先将每个区间的起始位置和索引放入map中,即{intervals[i][0],i},map的key值有序,所以无需再进行排序。然后再遍历每个区间的右端点intervals[i][1],利用二分查找map大于等于intervals[i][1]中的最小值val(这个查找可以用库函数lower_bound来完成),此时i对应的右侧区间为val对应的索引。
class Solution {
public:
	 vector<int> findRightInterval(vector<vector<int>>& intervals) {
        int n = intervals.size();
        vector<int> v(n,-1);
        map<int,int> m;
        for(int i = 0; i < n; i++)
        {
            m[intervals[i][0]] = i;
        }
        for(int i = 0; i < n; i++)
        {
            auto it = m.lower_bound(intervals[i][1]);
            if(it != m.end())
            {
                v[i] = it->second; 
            }
        }
        return v;
    }
};

时间复杂度为O(nlogn),其中n为区间数组的长度,logn为二分查找。
空间复杂度为O(n),map一共存储了n个元素。

lower_bound库函数介绍: lower_bound()、upper_bound()、equal_range() 以及 binary_search() 这 4 个查找函数,它们的底层实现采用的都是二分查找的方式。

lower_bound() 函数用于在指定区域内查找不小于目标值的第一个元素,返回的是迭代器。如果是线性容器,如vector和string,则lower_bound(vector.begin(),vector.end(),key);如果map或者list,则有自己的内置函数直接map.lower_bound(key)

  1. 排序+双指针
    startmap存储所有区间的起始点并从小到大排序;endmap存储所有区间的终止点并从小到大排序。 我们从endmap数组中取出第i 个区间,就可以从左到右扫描 startmap 数组中的区间起点来找到满足右区间条件的区间。设endmap数组中第i 个元素的右区间为 startmap数组中的第j个元素,此时可以知道 startmap[j?1][0]<endmap[i][1],startmap[j][0]≥endmap[i][1]。当我们遍历 endmap数组中第i+1个元素时,我们不需要从第一个索引开始扫描 startmap数组,可以直接从第j 个元素开始扫描 startmap数组。由于数组中所有的元素都是已排序,因此可以知道 startmap[j?1][0]<endmap[i][1]≤endmap[i+1][1],所以数组 startmap的前j?1的元素的起始点都小于 endmap[i+1][1],因此可以直接跳过前j?1个元素,只需要从j 开始搜索即可。
class Solution {
public:
    vector<int> findRightInterval(vector<vector<int>>& intervals) {
        int n = intervals.size();
        vector<int> result(n,-1);
        vector<pair<int,int>> startmap;
        vector<pair<int,int>> endmap;
        for(int i = 0; i < intervals.size(); i++)
        {
            startmap.emplace_back(intervals[i][0],i);
            endmap.emplace_back(intervals[i][1],i);
        }
        sort(startmap.begin(),startmap.end());
        sort(endmap.begin(),endmap.end());
        for(int i = 0,j = 0; i < n && j < n; i++)
        {
            while(j < n && endmap[i].first > startmap[j].first)
            {
                j++;
            }
            if(j < n)
            {
                result[endmap[i].second] = startmap[j].second;
            }
        }
        return result;
    }
};

时间复杂度为O(nlogn),n是数组区间长度,两个数组的排序时间为O(nlogn),查找每个区间的右侧区间的时间复杂度为O(logn),所以时间复杂度为O(nlogn)。
空间复杂度为O(n),n为区间数组的长度。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-24 18:28:41  更:2022-05-24 18:30:35 
 
开发: 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年12日历 -2024/12/30 1:32:18-

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