繁体   English   中英

找到重复数字序列的索引中点的最有效算法是什么?

[英]What is the most efficient algorithm to find the midpoint of the index of a repeated sequence of numbers?

a=[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 -1, -1, -1, -1,-1, 0, 0, 0, 0, 0]

我希望能够获得重复点索引的中点,即

output_vector = [2, 8,  13, 19]

即output_vector [0]是第一序列的中点的索引0, 0, 0, 0, 0

output_vector [1]是中点的第二重复序列的1, 1, 1, 1, 1, 1, 1

output_vector [2]是第二个重复序列-1, -1, -1, -1,-1中点

一种方法是使用itertools.groupby查找组并计算其中点:

from itertools import groupby

a = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,-1, 0, 0, 0, 0, 0]

groups = [list(g) for _, g in groupby(a)]    
output_vector = [sum(1 for x in groups[:i] for _ in x) + len(x) // 2 for i, x in enumerate(groups)]
# [2, 8, 14, 19]

itertools方法可能更好,更清洁。 尽管如此,这是一种使用mathstatistics的方法,它会查找每组数字的起始索引和终止索引的中值。

import math
import statistics as stat

a = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0]

lastNum = None
startIdx = 0
midpts = []
for idx, x in enumerate(a):
    if lastNum is not None and lastNum != x or idx == len(a) - 1:
        midpts.append(math.floor(stat.median([startIdx, idx])))
        startIdx = idx
    lastNum = x

print(midpts)
# [2, 8, 14, 19]

另一个基于itertools的解决方案,但效率更高。

from itertools import groupby

a = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,-1, 0, 0, 0, 0, 0]

output = []
psum = 0 
for glen in (sum(1 for i in g) for k, g in groupby(a)):
    output.append(psum + glen // 2)
    psum += glen

print(output)

@Matt M答案的基于C ++的实现

  template<typename T>
    std::vector<size_t> getPeaks(std::vector<T>& input_vector) {
        std::vector<size_t> output;
        T lastNum = 10000;
        size_t startIdx = 0;
        for (size_t i = 0; i < input_vector.size(); ++i) {
            if ((lastNum != 10000 and lastNum != input_vector[i]) || (i == input_vector.size() - 1)) {
                auto medianIdx = findMedian(startIdx, i);
                output.emplace_back(medianIdx);
                startIdx = i;

            }
            lastNum = input_vector[i];
        }
        return output;

}

 size_t findMedian(size_t start, size_t end) {
    return start + (end - start) / 2;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM