遇到零时划分数组
Posted
技术标签:
【中文标题】遇到零时划分数组【英文标题】:divide array when encountering zeroes 【发布时间】:2021-03-11 19:14:22 【问题描述】:我想将一个数组分成多个(或一个,可能是零个)数组,如下例所示:
array = [0 1 1 2 3 4 0 3 0 3 3 0 5 6 7] -> array1 = [1 1 2 3 4] array2 = [3] array3 = [3 3] array4 = [5 6 7 ]
我的幼稚方法是首先从左右删除零,然后继续使用两个迭代器来查找每个子数组的开始和结束,并使用向量构造函数构建子数组并将它们传递给函数。但我知道我的方法是幼稚且低效的,因此我希望能就如何更有效地解决这一问题提出一些建议。
非常感谢大家!
这也是我的方法的代码(a 是母数组):
for(int i = 0; i < a.size(); i++)
if(a[i] != 0)
break;
a.erase(a.begin() + i);
for(int i = a.size() - 1; i >= 0; i--)
if(a[i] != 0)
break;
a.erase(a.begin() + i);
auto begin = a.begin();
auto end = a.begin() + 1;
for (int i = 0; i < a.size(); i++)
if(a[i] == 0)
vector<int> temp(begin, end);
color(temp);
begin = end + 1;
end = begin + 1;
else end++;
【问题讨论】:
请添加语言标签 您可以创建一个std::vector<std::vector<int>> result;
并(多次)使用像std::find
这样的算法,如果您允许这样做,无需从来源。
【参考方案1】:
解决此问题的方法之一是创建一个包含所有零元素索引的辅助数组(在实现中使用const_iterator
而不是索引)。这个问题可以在不创建辅助数组的情况下解决,但这样做的好处是可以提前知道要创建多少个子数组。做法如下,
迭代输入数组并将零元素的索引放入辅助数组中,
InputArray = [0, 1, 1, 2, 3, 4, 0, 3, 0, 3, 3, 0, 5, 6, 7]
数组包含零个元素索引 = [0, 6, 8, 11]
正如您在上面看到的,有四个分隔符(零索引条目)将输入数组划分为 3
子数组,最后一个零位于索引 11
处,这不是输入数组的最后一个元素,这就是为什么多了一个子数组将创建数组,因此总子数组 = 4
其他详细信息请参阅代码,
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using std::cout;
std::vector<std::vector<int>> splitAtZero(const std::vector<int>& arr)
std::vector<std::vector<int>::const_iterator> divider;
divider.reserve(std::max<std::size_t>(arr.size() / 4, 2));
for(std::vector<int>::const_iterator it = arr.cbegin(), endIt = arr.cend(); endIt != it; ++it)
if(0 == *it)
divider.push_back(it);
if(divider.empty())
return arr;
if(arr.size() == divider.size())
return ;
std::size_t numOfSubArray = (divider.size() - 1) + (arr.cbegin() != divider.front() ? 1 : 0) +
(arr.cend() != divider.back() ? 1 : 0);
std::vector<std::vector<int>> subArr;
subArr.reserve(numOfSubArray);
std::vector<int>::const_iterator it = arr.cbegin();
for(std::vector<int>::const_iterator divderIt : divider)
if(divderIt - it > 0)
subArr.emplace_back(it, divderIt);
it = divderIt + 1;
if(arr.cend() != it)
subArr.emplace_back(it, arr.cend());
return subArr;
int main()
std::string comma("");
for(std::vector<int>& subArr : splitAtZero(0, 1, 1, 2, 3, 4, 0, 3, 0, 3, 3, 0, 5, 6, 7))
cout<< comma<< "[";
std::copy(subArr.cbegin(), subArr.cbegin() + (subArr.size() - 1), std::ostream_iterator<int>(cout, ", "));
cout<< subArr.back()<< "]";
comma = ", ";
cout<< '\n';
输出:[1, 1, 2, 3, 4], [3], [3, 3], [5, 6, 7]
【讨论】:
【参考方案2】:在我建议的以下方法中,您可以通过单次顺序扫描检索子数组,而无需在开头或结尾排除零:
std::vector<std::vector<int>> arrays;
std::vector<int> currentArray;
for (int i = 0; i < a.size; i++)
if (a[i] == 0 || i == a.size - 1)
if (currentArray.size() != 0)
arrays.push_back(currentArray);
currentArray.clear();
else
currentArray.push_back(a[i]);
【讨论】:
您可能希望将最后一个currentArray
推送到 arrays
以上是关于遇到零时划分数组的主要内容,如果未能解决你的问题,请参考以下文章