微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

找出间隔中数字的频率

如何解决找出间隔中数字的频率

在非重叠间隔中查找元素频率/计数的最有效方法是什么?例如:

limits = [0,25,40,60]
data = [15,5,2,56,45,23,6,59,33,18]

对于上面的列表,我想找到数据中两个相邻限制内的元素数。因此,对于上述内容,计数将类似于:

0-25:6; 25-40:1; 40-60: 3;

我能想到的只有 O(n^2) 时间。有没有更好的方法

解决方法

不需要 Counter 来计数,因为 bin 的数量是已知的,将 dict 交换到数组访问以进行 binning..

from bisect import bisect_right

def bin_it(limits,data):
    "Bin data according to (ascending) limits."
    bins = [0] * (len(limits) + 1)      # adds under/over range bins too

    for d in data:
        bins[bisect_right(limits,d)] += 1

    return bins

if __name__ == "__main__":
    limits = [0,25,40,60]
    data = [15,5,2,56,45,23,6,59,33,18]

    bins = bin_it(limits,data)

    print(f"         < {limits[0]:2} :",bins[0])
    for lo,hi,count in zip(limits,limits[1:],bins[1:]):
        print(f">= {lo:2} .. < {hi:2} :",count)
    print(f">= {limits[-1]:2} ...     :",bins[-1])

"""
SAMPLE OUTPUT:

         <  0 : 0
>=  0 .. < 25 : 6
>= 25 .. < 40 : 1
>= 40 .. < 60 : 3
>= 60 ...     : 0

"""
,

我向您推荐这种方法,它按照 O(nlogn)

的顺序实现您想要的
limits = [0,60] # m
data = [15,18] # n
data += limits # O(n+m)
data.sort() # O((n+m)log(n+m)) = O(nlogn)

result=dict() # O(1)
cnt = 0 # O(1)
aux ='' # O(1)
i = 0 # O(1)
for el in data: # O(n+m)
  if el == limits[i]:
    i+=1
    if cnt > 0:
      aux+='-'+str(el)
      result[aux] = cnt # average = O(1)
      cnt = 0
      aux = str(el)
    else:
      aux = str(el)
  else:
    cnt+=1

print(result)
# {'0-25': 6,'25-40': 1,'40-60': 3}

我展示了每个重要行的时间复杂度来计算代码的总时间复杂度。代码的总时间复杂度等于 O((n+m)log(n+m)),可以表示为 O(nlogn)

改进

如果您对输入有一些假设,则可以改进它。如果您有关于 limitsdata 范围的信息,那么您可以将排序算法更改为 counting sort。计数排序的时间复杂度为O(n),代码的总时间复杂度为O(n)

,

这是一个简单的 O(NlogN) 方法。对数据进行排序,然后使用双指针方法将每个元素放置在正确的间隔中。

limits = [0,60]
data = [15,18]
data.sort()

n,m = len(data),len(limits)
count = [0]*(m-1)
# count[i] represents count between limits[i] and limits[i+1]

low = 0  # lower index of interval we are currently checking
ptr = 0

while ptr < n:
    i = data[ptr]
    if i >= limits[low] and i <= limits[low+1]:
        count[low] += 1
        ptr += 1
    elif i>=limits[low]:
        if low == len(limits)-1:
            break
        low += 1

print(count)
,
limits = [0,60,80]
data = [15,18,85]
dict_data = {}
i = 0
count = 1
while i < len(limits)-1:
    for j in data:
        if j in range(limits[i],limits[i+1]):
            if '{}-{}'.format(limits[i],limits[i+1]) in dict_data:
                dict_data['{}-{}'.format(limits[i],limits[i+1])] +=count
            else:
                dict_data['{}-{}'.format(limits[i],limits[i+1])] = count
        
    i+=1
print(dict_data)
,

您可以使用计数器(来自集合)来管理计数和平分以进行分类:

from collections import Counter
from bisect import bisect_left

limits = [0,80]
data   = [15,18]

r = Counter(limits[bisect_left(limits,d)-1] for d in data)

print(r)
Counter({0: 6,40: 3,25: 1})

这具有 O(NLogM) 的时间复杂度,其中 M 是限制中断的数量,N 是数据项的数量

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?