【map】【滑动窗口】C++算法:最小区间

简介: 【map】【滑动窗口】C++算法:最小区间

题目 LeetCode:632

你有 k 个 非递减排列 的整数列表。找到一个 最小 区间,使得 k 个列表中的每个列表至少有一个数包含在其中。

我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。

示例 1:

输入:nums = [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]

输出:[20,24]

解释:

列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。

列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。

列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。

示例 2:

输入:nums = [[1,2,3],[1,2,3],[1,2,3]]

输出:[1,1]

提示:

nums.length == k

1 <= k <= 3500

1 <= nums[i].length <= 50

-105 <= nums[i][j] <= 105

nums[i] 按非递减顺序排列

分析

假定区间为[left,right],k个列表在[left,right]中的最小值为m1,最大值为m2。则left=m1,right=m2。

如果left < m1,将left改成m1,仍然符合题意。如果left >m1,则m1不在区间。

如果right < m2 ,则m2不在区间。如果right >m2,将right 改成m2,仍然符合题意。

从小到大枚举left,各列表小于left的数排除,各队列的最小值的最大值就是对应的right。

tmp就是nums 各元素倒值,降序,方便向量出栈。

mValueToIndex记录各队列的最小值和小标。tmp中的值加到mValueToIndex后,就出栈。

mValueToIndex的最小值也是所有队列的最小值,所以排除mValueToIndex的最小值就可以了。

当某个队列nums[i]为空时,程序结束。

代码

核心代码

class Solution {
public:
  vector<int> smallestRange(const vector<vector<int>>& nums) {
    auto tmp = nums;
    std::multimap<int, int> mValueToIndex;
    for (int i = 0 ; i < tmp.size(); i++ )
    {
      auto& v = tmp[i];
      std::reverse(v.begin(), v.end());
      mValueToIndex.emplace(v.back(), i);
      v.pop_back();
    }
    int left = mValueToIndex.begin()->first, right = mValueToIndex.rbegin()->first;
    while (tmp[mValueToIndex.begin()->second].size())
    {
      const int i = mValueToIndex.begin()->second;
      mValueToIndex.erase(mValueToIndex.begin());
      mValueToIndex.emplace(tmp[i].back(),i);
      tmp[i].pop_back();
      int leftCur = mValueToIndex.begin()->first, rightCur = mValueToIndex.rbegin()->first;
      if (rightCur - leftCur < right - left)
      {
        left = leftCur;
        right = rightCur;
      }
    }
    return { left,right };
  }
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{
  assert(t1 == t2);
}
template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
  if (v1.size() != v2.size())
  {
    assert(false);
    return;
  }
  for (int i = 0; i < v1.size(); i++)
  {
    Assert(v1[i], v2[i]);
  }
}
int main()
{
  vector<vector<int>> nums;
  {
    Solution sln;
    nums = { {4,10,15,24,26}, {0,9,12,20}, {5,18,22,30} };
    auto res = sln.smallestRange(nums);
    Assert(vector<int>{20, 24}, res);
  }
  {
    Solution sln;
    nums = { {1,2,3},{1,2,3},{1,2,3} };
    auto res = sln.smallestRange(nums);
    Assert(vector<int>{1, 1}, res);
  }
//CConsole::Out(res);
}

2023年4月版

class Solution {
public:
vector smallestRange(vector& nums) {
std::set setValue;
for (const auto& v : nums)
{
for (const int& i : v)
{
setValue.emplace(i);
}
}
int iRet = INT_MAX;
int iMax = 0;
for (const auto& value : setValue)
{
int iMin = INT_MAX;
bool bSuc = true;
for (const auto& v : nums)
{
auto iNum = std::upper_bound(v.begin(), v.end(), value) - v.begin();
if (0 == iNum)
{
bSuc = false;
break;
}
iMin = min(iMin, v[iNum - 1]);
}
if (bSuc)
{
if (value - iMin + 1 < iRet)
{
iRet = value - iMin + 1;
iMax = value;
}
}
}
return vector{iMax - iRet + 1, iMax};
}
};

2023年8月版

class Solution {
public:
vector smallestRange(vector& nums) {
m_c = nums.size();
vector vPre(m_c);
std::map mValueIndex;
std::multiset setMax;
for (int i = 0 ; i < m_c ; i++)
{
const auto& v = nums[i];
setMax.emplace(v[0]);
vPre[i] = v[0];
for (int j = 1; j < v.size(); j++)
{
mValueIndex[v[j]].emplace_back(i);
}
}
vector vRet = { *setMax.begin(),*setMax.rbegin() };
for (const auto& it : mValueIndex)
{
for (const auto& next : it.second)
{
auto ij = setMax.find(vPre[next]);
setMax.erase(ij);
setMax.emplace(it.first);
vPre[next] = it.first;
}
vector cur = { *setMax.begin(),*setMax.rbegin() };
if ((cur[1]-cur[0]) < (vRet[1]-vRet[0]))
{
cur.swap(vRet);
}
}
return vRet;
}
int m_c;
};


扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。

https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程

https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17

如无特殊说明,本算法C++ 实现。

相关文章
|
1天前
|
算法 Serverless 数据处理
从集思录可转债数据探秘:Python与C++实现的移动平均算法应用
本文探讨了如何利用移动平均算法分析集思录提供的可转债数据,帮助投资者把握价格趋势。通过Python和C++两种编程语言实现简单移动平均(SMA),展示了数据处理的具体方法。Python代码借助`pandas`库轻松计算5日SMA,而C++代码则通过高效的数据处理展示了SMA的计算过程。集思录平台提供了详尽且及时的可转债数据,助力投资者结合算法与社区讨论,做出更明智的投资决策。掌握这些工具和技术,有助于在复杂多变的金融市场中挖掘更多价值。
22 12
|
1天前
|
存储 监控 算法
员工屏幕监控系统之 C++ 图像差分算法
在现代企业管理中,员工屏幕监控系统至关重要。本文探讨了其中常用的图像差分算法,该算法通过比较相邻两帧图像的像素差异,检测屏幕内容变化,如应用程序切换等。文中提供了C++实现代码,并介绍了其在实时监控、异常行为检测和数据压缩等方面的应用,展示了其实现简单、效率高的特点。
27 15
|
1月前
|
负载均衡 算法 安全
探秘:基于 C++ 的局域网电脑控制软件自适应指令分发算法
在现代企业信息化架构中,局域网电脑控制软件如同“指挥官”,通过自适应指令分发算法动态调整指令发送节奏与数据量,确保不同性能的终端设备高效运行。基于C++语言,利用套接字实现稳定连接和线程同步管理,结合实时状态反馈,优化指令分发策略,提升整体管控效率,保障网络稳定,助力数字化办公。
52 19
|
1月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
51 2
|
1月前
|
存储 算法 安全
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
|
2月前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
2月前
|
算法 安全 C++
用 C++ 算法控制员工上网的软件,关键逻辑是啥?来深度解读下
在企业信息化管理中,控制员工上网的软件成为保障网络秩序与提升办公效率的关键工具。该软件基于C++语言,融合红黑树、令牌桶和滑动窗口等算法,实现网址精准过滤、流量均衡分配及异常连接监测。通过高效的数据结构与算法设计,确保企业网络资源优化配置与安全防护升级,同时尊重员工权益,助力企业数字化发展。
65 4
|
2月前
|
算法
|
3月前
|
存储 算法 C++
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
37 5
|
3月前
|
存储 C++ 容器
【C++】map的模拟实现
C++中的`map`是STL中的一种关联容器,存储键值对且键唯一。`map`基于红黑树实现,自动按键排序,支持动态调整、复杂数据类型、丰富的成员函数及双向迭代器。插入、查找等操作保证了对数时间复杂度,适用于需要快速查找和有序存储的场景。
30 3