第2章 面试需要的基础知识
第3章 高质量的代码
第4章 解决面试题的思路
面试题27:二叉树的镜像
面试题29:顺时针打印矩阵
面试题30 :包含min函数的栈
面试题31:栈的压入、弹出序列
面试题32:上往下打印二叉树
面试题33: 二叉搜索树的后序遍历序列
面试题34: 二叉树中和为某一值的路径
面试题35:复杂链表的复制
面试题36:二叉搜索树与双向链表
面试题38:字符串的排列
第5章 优化时间和空间效率
第6章 面试中的各项能力
第7章 两个面试案例
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
解题思路
牛客网
方法一:
数组中有一个数字出现的次数超过数组长度的一半,所以它出现的次数比其它数出现的次数总和还多。考虑在遍历数组时保存两个值:一个是数组中的一个数字,另一个是次数。
当我们遍历到下一个数字时,如果下一个数字和我们之前保存的数字相同,则次数加1;如果不同,则次数减1。如果次数为零,则需要保存下一个数字,并把次数设为1。这样要找的数字可能是最后一次把次数设为1时对应的数字,还需要统计这个数字在数组中的数量才能确认。
实战
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
length = len(numbers)
i = 0
counts = 0
while i < length:
if counts == 0:
digit = numbers[i]
i += 1
counts = 1
continue
if numbers[i] != digit:
counts -= 1
else:
counts += 1
i += 1
counts = 0
for num in numbers:
if num == digit:
counts += 1
if counts > length >> 1:
return digit
return 0
方法二:
受快速排序启发,有成熟的得到数组中任意第k大数字的算法,且时间复杂度为O(n)。如果数组有一个数其数量超过数组长度一半,那么排序后的数组其中间位置的数一定就是那个次数超过一半的数,所以这道题可以引申为寻找排序数组的中间位置数。
我们先随机选取一个数字,然后调整数组顺序,使得比选中数字大的数在其右边,小的数在其左边。如果选中的数其索引恰好为n/2,则这个数就是中间位置数;如果其索引大于n/2,那么中间位置数在这个数的左边,然后继续去左边数组中查找;否则中间位置数在其右边,继续去右边数组中查找。这是一个典型的递归过程。
实战
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
if not numbers:
return numbers
def recc(begin, end):
if begin >= end:
return numbers[begin]
index = begin
for i in range(begin+1, end+1):
if numbers[index] > numbers[i]:
numbers[index], numbers[i] = numbers[i], numbers[index]
index = i
if index == length >> 1:
return numbers[index]
if index > length >> 1:
num = recc(begin, index-1)
else:
num = recc(index+1, end)
return num
length = len(numbers)
number = recc(0, length-1)
counts = 0
for i in range(length):
if number == numbers[i]:
counts += 1
if counts > length >> 1:
return number
return 0