将多组集排序为升序子序列,每个可用元素出现一次
Sorting multiset as ascending subsequences with one occurence of each available element
让我们假设给定的多集,例如
A = {1, 1, 1, 2, 2, 3, 3, 3}.
对这样的元素进行排序的最简单方法是什么:
(1, 2, 3, 1, 2, 3, 1, 3),
即由从集合的可用元素构建的升序子序列构建的序列?
如何在C++和Python中实现。有没有这方面的库?如何"手工"完成?
您可以将其实现为计数排序首先计算每个元素出现的次数,元素是数组中的索引,用于存储每个值的出现次数。 然后遍历该数组,直到每个索引的值为零。
这可能不是实现它的最佳(或最有效)方法,但这是首先想到的解决方案。
假设你愿意修改你的原始多集(或处理它的副本),做类似的事情
while(!data.empty()) {
auto x = data.begin();
while( x != data.end()) {
auto value = *x;
cout << value << endl;
data.erase(x); // delete *one* item
x = data.upper_bound(value); // find the next *different* value
}
}
这不是很有效。 如果你有一个庞大的数据集,那么也许你需要考虑你的约束是什么(内存还是时间?
在 Python 中,您可以使用 groupby 从排序列表中获取唯一项目组的矩阵:
from itertools import groupby, izip_longest
A=[1, 1, 1, 2, 2, 3, 3, 3]
groups=[]
for k, g in groupby(sorted(A)):
groups.append(list(g))
print groups
# [[1, 1, 1], [2, 2], [3, 3, 3]]
更简洁地说,您可以使用列表理解来执行相同的操作:
groups=[list(g) for _, g in groupby(sorted(A))]
# [[1, 1, 1], [2, 2], [3, 3, 3]]
或者,您可以展开多集、计数器的 Python 版本,并对键进行排序以获取相同的嵌套列表:
from collections import Counter
c=Counter(A)
groups=[[k]*c[k] for k in sorted(c.keys())]
# [[1, 1, 1], [2, 2], [3, 3, 3]]
groups
嵌套列表后,使用 izip_longest 反转矩阵,展平列表并删除None
值:
print [e for t in izip_longest(*groups) for e in t if e!=None]
指纹
[1, 2, 3, 1, 2, 3, 1, 3]
以下是在没有任何导入库的情况下在python中手动完成的方法:
A = (1, 1, 1, 2, 2, 3, 3, 3)
# create a list out of a set of unique elems in A
a = list(set(A))
a.sort() # sort so they are in ascending order
countList = []
# find how many repeated elems in the list set we just made
for i, elem in enumerate(a, 0):
countList.append(A.count(elem))
# find the what is the lowest repeated number in the orig list
minEntry = min(countList)
# we can multiply the list set by that lowest number
outString = a * minEntry
# add the left over numbers to the outstring
for i in range(len(countList)):
count = abs(countList[i] - minEntry)
if count != 0:
outString.append(a[i]*count)
print outString
这是输出字符串
[1, 2, 3, 1, 2, 3, 1, 3]
如果您可以使用第二个顺序容器,那么在C++中,您可以通过标准算法 std::unique_copy 和 std::set_difference 简单地将原始容器的元素移动到第二个容器中。
def Test(seq):
index = 0
Seq = seq
newlist = []
while len(Seq) != 0:
newlist.append(list(set(Seq).union()))
for Del in newlist[index]:
Seq.remove(Del)
index += 1
return [y for x in newlist for y in x]
在C++中,您可以准备一个迭代器列表,而不是操作数据结构,以达到相等范围的开头,然后依次取消引用/递增这些迭代器:
#include <set>
#include <list>
#include <iostream>
int main()
{
std::multiset<int> A = {1, 1, 1, 2, 2, 3, 3, 3};
// build a list of iterator pairs to each equal range
std::list< std::pair<std::multiset<int>::iterator,
std::multiset<int>::iterator> > iters;
for(auto it=A.begin(); it != A.end(); it = A.upper_bound(*it))
iters.push_back(A.equal_range(*it));
// for each non-empty subrange, show what the first iterator is
// pointing to, then advance it by one position in its subrange
// if the subrange is empty, drop it from the list
while(!iters.empty())
for(auto it = iters.begin(); it != iters.end(); )
if(it->first != it->second)
std::cout << *it++->first++ << ' '; // don't do this at home
else
it = iters.erase(it);
}
相关文章:
- 我是否需要在下一次转移时将所有权*转移回转移队列
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 在C++中一次将矢量值写入多个文件
- 高级选择排序 - 在一次迭代中搜索两个元素
- C++ 查找算法:如何找到元素的最后一次出现?
- 一次加载整个缓存行以避免争用其中的多个元素
- C++ 向量元素被最后一次调用push_back替换
- 打印出现一次的字符串数组的第一个元素
- memmove会移动元素(就像前面的方式相同),还是一次抓住整个内存块
- 使用 std::unique 和 vector.erase 删除除最后一次出现的重复元素之外的所有元素
- 用3x3结构元素进行两次形态扩张,等于用6x6结构元素进行一次形态扩张
- 一次向 C++ 向量添加多个元素
- 将多组集排序为升序子序列,每个可用元素出现一次
- 如何将字符串一次推送到一个元素的堆栈中
- 我需要一个 std 函数来检查有多少元素在向量中恰好出现一次
- STD 向量构造元素一次
- 如何在C++中只从列表中删除一次特定元素
- 一个有效的方法,随机选择std::vector的所有元素正好一次而不重新洗牌
- 如何在c++中删除一对重复出现的列表?(保留只出现一次的元素)
- 数组元素的所有排列在C++中一次获取一定数量的元素