问题:统计一个数字在排序数组中出现的次数,输出统计后的次数。
原理:
一个直观的解法就是扫描序列统计出指定数字的个数,但这个思路并没有用上序列是排序的情况。如果序列是排序的,我们先找出该数字在序列中的区间,那么区间的长度就是数字出现的次数。那么如何找出给定数字在序列中的区间呢?有两种思路:
(1)使用双指针,序列前后同时扫描 (2)使用二分查找,分表找到数字的前后边界
思路一的时间复杂度是O(n),思路二的时间复杂度为O(logn)。
实现:
先实现思路一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def number_of_sequence (sequence, number ): n = len (sequence) i = 0 for item in sequence: if item == number: break i += 1 j = 0 for item in reversed (sequence): if item == number: break j += 1 return n - i - j
实现思路二:
我们先实现找出第一个给定数的索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def get_first_k (sequence, n, k, start, end ): if start > end: return -1 middle_index = (start+end) // 2 middle_number = sequence[middle_index] if middle_number == k: if (middle_index > 0 and sequence[middle_index-1 ] != k) or middle_index == 0 : return middle_index else : end = middle_index - 1 elif middle_number > k: end = middle_index - 1 else : start = middle_index + 1 return get_first_k(sequence, n, k, start, end)
类似地,找出最后一个给定数的索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def get_last_k (sequence, n, k, start, end ): if start > end: return -1 middle_index = (start+end) // 2 middle_number = sequence[middle_index] if middle_number == k: if (middle_index < n - 1 and sequence[middle_index+1 ] != k) or middle_index == n-1 : return middle_index else : start = middle_index + 1 elif middle_number < k: start = middle_index + 1 else : end = middle_index - 1 return get_last_k(sequence, n, k, start, end)
利用上述试下的函数找到给定数字的边界索引,从而确定数字的数量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def get_number_of_k (sequence, k ): if not sequence: return 0 n = len (sequence) first = get_first_k(sequence, n, k, 0 , n-1 ) end = get_last_k(sequence, n, k, 0 , n-1 ) print (first, end) if first > -1 and end > -1 : return end - first + 1 else : return 0 def main (): import random seq = [random.choice(range (100 )) for _ in range (2000 )] seq.sort() print (seq) k = random.choice(seq) n = get_number_of_k(seq, k) print (n) print (seq.count(k))
使用Python中list.count
函数来检验结果。