统一分布一组字符

时间:2015-12-16 21:44:06

标签: algorithm

有一组字符需要在数组中均匀分布。 例如,

a - 1

b - 2

c - 3

d - 4

在这种情况下,有一个a,两个b,三个c和四个d,总共10个字符。

现在我需要将它分布在一个大小为10的数组中,以便所有这些数据均匀分布。它们不必完全均匀分布,任何接近的东西都可以。

对于前。这是一个有效的序列。

d c d b c d a d c b

2 个答案:

答案 0 :(得分:1)

你可以使用类似于bresenham算法的东西来跟踪理想间距和每个组件的最后间距之间的误差:

vals = ['a','b','c','d']
cts  = [1,2,3,4]

sz = sum(cts)
spacing = [float(sz)/(ct+1) for ct in cts]
err = [s for s in spacing]
a=[]
for i in range(sz):
    err = [e-1 for e in err]
    m = min(err)
    i = err.index(m)
    a.append(vals[i])
    err[i]+=spacing[i]
print a

yeilds:['d', 'c', 'b', 'd', 'a', 'c', 'd', 'b', 'c', 'd']

答案 1 :(得分:0)

首先,尝试猜测每个字母实例的位置,一次只考虑一个字母。如果总共有10个和3个,则尝试将As放在索引0,3和7处。计算每个字母的估计值,并将它们放入有序的多集中。

std::multimap<unsigned,char> set;
const unsigned totalcount = ... //for your example this would be 10
for (const auto& letterpair : letters) {
    unsigned lettercount = letterpair.second; //for c this would be 3
    for(unsigned i=0; i<lettercount; ++i) {
        unsigned targetIdx = (2*i*totalcount+1)/lettercount;
        set.insert(std::make_pair(targetIdx, letterpair.first));
    }
}

然后我们可以简单地按顺序遍历集合并将每个事物放在一个索引中。

std::vector<char> result;
for(const auto& p : set)
    result.push_back(p.second); //insert the letters in order

它并不完美,但考虑到速度和简单性,它的效果非常好。

对于您的输入,它会产生bcdadcbdcd:http://coliru.stacked-crooked.com/a/1f83ae4518b7c6ca