题目
在排好序的数组中,统计数k出现的次数
思路
思路一
使用二分查找,如果在中间出现,循环判断前一个数是否一样,后一个数是否一样,直到找到不一样的为止
思路二
先找到第一个k,再找最后一个k,下标相减得到计数
都使用二分查找,第一个k,如果k和中间值相等,那么要判断k是不是第一个,
前一个值是否是k,如果不是,那中间值就是第一个k;如果是k,那么去前半段找第一个k
最后一个同理
注意
二分查找中间值为(start+end) // 2,相加,不是相减
在循环中,要向前向后访问数组的值,记得先判断会不会越界。
代码
def GetNumberOfK(data, k):
num = len(data)
i = 0
j = num - 1
middle = num // 2
count = 0
while j-i >= 0:
if data[middle] == k:
count += 1
n = middle - 1
while n >=0 and data[n] == k:
n -= 1
count +=1
m = middle + 1
while m < num and data[m] == k:
m +=1
count +=1
break
elif data[middle] > k:
j = middle - 1
elif data[middle] < k:
i = middle + 1
middle = i + (j - i ) // 2
return count
# 改进思路
def getfirstk(data,k):
num = len(data)
i = 0
j = num - 1
middle = num // 2
while j-i >= 0:
if data[middle] == k:
if middle-1 >= 0 and data[middle-1] == k: # 向后向前遍历时,注意判断边界能不能取到
j = middle -1
else:
return middle
elif data[middle] > k:
j = middle - 1
elif data[middle] < k:
i = middle + 1
middle = (j + i ) // 2 # i + (j - i ) // 2
return -1
def getlastk(data,k):
num = len(data)
i = 0
j = num - 1
middle = num // 2
while j-i >= 0:
if data[middle] == k:
if middle+1 < num and data[middle+1] == k:
i = middle + 1
else:
return middle
elif data[middle] > k:
j = middle - 1
elif data[middle] < k:
i = middle + 1
middle = (j + i ) // 2 # i + (j - i ) // 2
return -1
if __name__ == "__main__":
data = [1,2,2,3,3,3,5,6,8,9]
k = 1
#print(GetNumberOfK(data,k))
print(getlastk(data,k)-getfirstk(data,k)+1)