1.圆圈中最后剩下的数

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
 
如果没有小朋友,请返回-1
解:
用数组模拟循环链表即可。
 1 class Solution:
2 def LastRemaining_Solution(self, n, m):
3 # write code here
4 if not n:
5 return -1
6 cycle = list(range(n))
7 start = 0
8 while len(cycle) > 1:
9 toremove = (start + m - 1) % len(cycle)
10 cycle.pop(toremove)
11 start = toremove
12 return cycle[0]

2. 数组中重复的数字

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

解:

用 hashset 做。

 1 class Solution:
2 # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
3 # 函数返回True/False
4 def duplicate(self, numbers, duplication):
5 # write code here
6 if not numbers:
7 return False
8 hashset = set()
9 for num in numbers:
10 if num in hashset:
11 duplication[0] = num
12 return True
13 hashset.add(num)
14 return False

不用辅助空间,比较巧妙。因为要返回的是任意一个重复的数字,把当前序列当成是一个下标和下标对应值是相同的数组;

遍历数组,判断当前位 i 的值和下标是否相等:

  1. 若相等,则遍历下一位;

  2. 若不等,则将当前位置i上的元素和a[i]位置上的元素比较:若它们相等,则成功!若不等,则将它们两交换。换完之后a[i]位置上的值和它的下标是对应的,但i位置上的元素和下标并不一定对应;重复2.的操作直到当前位置i的值也为i

  3. 将i向后移一位,再重复2.

注意,这样找到的并不是一定是第一个重复的数字

 1 class Solution:
2 # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
3 # 函数返回True/False
4 def duplicate(self, numbers, duplication):
5 # write code here
6 if not numbers:
7 return False
8 # 判断数组元素是否都在0~n-1
9 n = len(numbers)
10 for i in range(n):
11 if numbers[i] < 0 or numbers[i] > n-1:
12 return False
13
14 for i in range(n):
15 while i != numbers[i]:
16 if numbers[i] == numbers[numbers[i]]:
17 duplication[0] = numbers[i]
18 return True
19 tmp = numbers[i]
20 numbers[i] = numbers[numbers[i]]
21 numbers[tmp] = tmp
22 return False

 

3. 构建乘积数组

给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。

解:

这题思路还是比较巧妙的,看个图就懂了。先算下三角的连乘,然后倒过来把剩下那部分也乘进去。

 1 class Solution:
2 def multiply(self, A):
3 if not A:
4 return []
5 n = len(A)
6 B_left = [1]*n
7 B_right = [1]*n
8 for i in range(1, n):
9 B_left[i] = B_left[i-1]*A[i-1]
10 B_right[-i-1] = B_right[-i]*A[-i]
11 for i in range(n):
12 B_left[i] *= B_right[i]
13 return B_left

4. 二维数组中的查找

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

解:

第一种思路,能保证每一行都是有序的,按行二分查找。

 1 class Solution:
2 # array 二维列表
3 def Find(self, target, array):
4 # write code here
5 if not array:
6 return False
7 m, n = len(array), len(array[0])
8
9 def binarySearch(target, nums):
10 if not nums:
11 return False
12 left, right = 0, len(nums)-1
13 while left <= right:
14 mid = left + (right-left)//2
15 if nums[mid] == target:
16 return True
17 elif nums[mid] > target:
18 right = mid - 1
19 else:
20 left = mid + 1
21 return False
22
23 for i in range(m):
24 if binarySearch(target, array[i]):
25 return True
26 return False

  

另一种思路,考虑到左下角的元素,往右更大,往上更小。以左下角为起点搜索,如果比target大就向上,如果比target小就向右

 1 class Solution:
2 # array 二维列表
3 def Find(self, target, array):
4 # write code here
5 if not array:
6 return False
7 m, n = len(array), len(array[0])
8 i, j = m-1, 0
9 while i >= 0 and j < n:
10 if array[i][j] == target:
11 return True
12 elif array[i][j] > target:
13 i -= 1
14 else:
15 j += 1
16 return False

  

5. 连续子数组的最大和

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

解:

这题其实是个基础的dp问题,定义dp[i]表示以a[i]结尾的连续子向量最大和,那么显然dp[i] = max(dp[i-1] + array[i], array[i]),即如果以a[i-1]结尾的连续子向量最大和为正就保留,否则没有在做正贡献,直接从a[i]重新开始。

最后要求的是最大连续子序列的和,可能是以数组中任意位置元素结尾的,所以返回max(dp)

 1 class Solution:
2 def FindGreatestSumOfSubArray(self, array):
3 if array is None or len(array)==0:
4 return
5 n = len(array)
6 dp = [0]*n
7 dp[0] = array[0]
8 for i in range(1, n):
9 dp[i] = max(dp[i-1] + array[i], array[i])
10 return max(dp)

  

把空间效率再优化下

 1 class Solution:
2 def FindGreatestSumOfSubArray(self, array):
3 if not array:
4 return 0
5 res = float('-inf')
6 n = len(array)
7 sum_ = array[0]
8 for i in range(1, n):
9 if sum_ > 0:
10 sum_ += array[i]
11 else:
12 sum_ = array[i]
13 res = max(res, sum_)
14 return res

6. 最小的k个数

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

解:

直接快排然后取前k个,O(NlogN)。但是N很大k很小的情况下这样很不划算。

1 class Solution:
2 def GetLeastNumbers_Solution(self, tinput, k):
3 # write code here
4 if not tinput or k > len(tinput):
5 return []
6 tinput.sort()
7 return tinput[:k]

  

用小顶堆实现始终维护最小的K个数,O(NlogK)

 1 import heapq
2
3 class Solution:
4 def GetLeastNumbers_Solution(self, tinput, k):
5 # write code here
6 if not tinput or k > len(tinput):
7 return []
8 n = len(tinput)
9 heap =[]
10 for i in range(n):
11 heapq.heappush(heap, -tinput[i])
12 if i >= k:
13 heapq.heappop(heap)
14 res = list(map(lambda x: -x, list(heap)))
15 res.sort() # 输出要求
16 return res

7. 和为 S 的连续正整数序列

小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!

输出描述:

输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序

解:

这题思路还比较巧妙,双指针维护动态窗口,窗口内的和可以用等差数列通项公式计算。如果窗口内数字之和小于目标值,右游标右移(想让窗口和变大);小于目标值,左游标右移(拿掉一个窗口中最小的数)。如果找到一组解,左游标

 1 class Solution:
2 def FindContinuousSequence(self, tsum):
3 # write code here
4 if tsum < 3:
5 return []
6 res = []
7 l, r = 1, 2
8 target = 2 * tsum
9 while l < r:
10 window = (l+r)*(r-l+1)
11 if window == target:
12 res.append(list(range(l, r+1)))
13 l += 1
14 elif window < target:
15 r += 1
16 else:
17 l += 1
18 return res

  

8. 数字在排序数组中出现的次数

统计一个数字在排序数组中出现的次数。

解:

二分查找 target 的左侧边界,再二分查找右侧边界,求区间长度即可

 1 class Solution:
2 def GetNumberOfK(self, data, k):
3 # write code here
4 start = self.search(data, k)
5 if start == -1:
6 return 0
7 end = self.searchEnd(data, k)
8 return end - start +1
9
10 def search(self, nums, target):
11 if nums == None or len(nums) == 0:
12 return -1
13 low = 0
14 high = len(nums)
15 while low < high:
16 mid = (low + high) // 2
17 if nums[mid] == target:
18 high = mid
19 elif nums[mid] > target:
20 high = mid
21 elif nums[mid] < target:
22 low = mid + 1
23 if low == len(nums):
24 return -1
25 return low if nums[low] == target else -1
26
27 def searchEnd(self, nums, target):
28 if nums == None or len(nums) == 0:
29 return -1
30 low = 0
31 high = len(nums)
32 while low < high:
33 mid = (low + high) // 2
34 if nums[mid] == target:
35 low = mid + 1
36 elif nums[mid] > target:
37 high = mid
38 elif nums[mid] < target:
39 low = mid + 1
40 if low == len(nums)+1:
41 return -1
42 return low-1 if nums[low-1] == target else -1

  

9. 数组中只出现一次的数字

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

解:

用哈希表统计出现次数

 1 class Solution:
2 # 返回[a,b] 其中ab是出现一次的两个数字
3 def FindNumsAppearOnce(self, array):
4 # write code here
5 hashmap = dict()
6 for num in array:
7 hashmap[num] = hashmap.get(num, 0) + 1
8
9 res = []
10 for key, value in hashmap.items():
11 if value == 1:
12 res.append(key)
13 return res

  

假设只出现一次的两个数是A 和 B全部异或一次,结果就是 A、B的异或。找到A和B不同的位数,并以此为基准把原数组分成两部分,各自异或就行了

 1 class Solution:
2 # 返回[a,b] 其中ab是出现一次的两个数字
3 def FindNumsAppearOnce(self, array):
4 # write code here
5 if not array:
6 return []
7 resXor = 0
8 for num in array:
9 resXor ^= num
10
11 indicator = resXor & (-resXor)
12
13 num1, num2 = 0, 0
14 for num in array:
15 if num & indicator == 0:
16 num1 ^= num
17 else:
18 num2 ^= num
19 return [num1, num2]

10. 顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字

例如,如果输入如下4 X 4矩阵:

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16

则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

解:

每一圈都是一样的,只要搞清楚每一圈的起点就行了。首先需要判断每一步开始是的坐标点是否满足小于行数的一半且小于列数的一半,在最后一圈中,可能出现仅能向右走一行,仅能向右走一行向下走一列,向右走一行向下走一列向左走一行,能走完整一圈,一共四种情况。其中只有能向右走一行必然发生,不必判断,剩余的都需要判断发生条件。

 1 class Solution:
2 # matrix类型为二维列表,需要返回列表
3 def printMatrix(self, matrix):
4 # write code here
5 if not matrix:
6 return []
7 rows, cols = len(matrix), len(matrix[0])
8 start = 0
9 res = []
10 while 2*start < rows and 2*start < cols:
11 res += self.printCycle(matrix, rows, cols, start)
12 start += 1
13 return res
14 def printCycle(self, matrix, rows, cols, start):
15 endx = cols - 1 - start
16 endy = rows - 1 - start
17 res = []
18 # 从左到右
19 for i in range(start, endx+1):
20 res.append(matrix[start][i])
21 # 从上到下
22 if start < endy:
23 for i in range(start+1, endy+1):
24 res.append(matrix[i][endx])
25 # 从右到左
26 if start < endx and start < endy:
27 for i in range(endx-1, start-1, -1):
28 res.append(matrix[endy][i])
29 # 从下到上
30 if start < endx and start < endy-1:
31 for i in range(endy-1, start, -1):
32 res.append(matrix[i][start])
33 return res

  

11. 滑动窗口最大值

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

解:

用双端队列维护一个单调队列,window保存当前窗口中数的下标,window新的头总是当前窗口中最大的那个数。处理前 k 个元素,初始化window。遍历整个数组。在每一步清理双向队列:

  只保留当前滑动窗口中有的元素的索引(因为滑动出去一个,要看一下window中的索引是不是都在i-k到i);

  移除比当前元素小的所有元素,它们不可能是最大的;

  将当前元素添加到双向队列中;

  将 deque[0] 添加到输出中。

 1 class Solution:
2 def maxInWindows(self, num, size):
3 # write code here
4 if not num or not size:
5 return []
6 res = []
7 n = len(num)
8 window = [] # 存窗口元素的索引
9 for i in range(n):
10 if i >= size and window[0] <= i-size:
11 window.pop(0)
12 while window and num[window[-1]] <= num[i]:
13 window.pop()
14 window.append(i)
15 if i >= size-1:
16 res.append(num[window[0]])
17 return res

动态规划,将n个数据分成大小为k的块,定义left[i]为i所处的块的开始位置到i位置的最大值,right[j]为j所处的块的结束位置到j的最大值。那么滑动窗口就两种情况,要么没有跨越两个块,要么跨越了两个块。不管哪种情况,窗口从i到j,窗口最大值为max( right[i], left[j] )

 1 class Solution:
2 def maxInWindows(self, num, size):
3 # write code here
4 if not num or not size:
5 return []
6 n = len(num)
7 left, right = [0]*n, [0]*n
8 left[0], right[-1] = num[0], num[-1]
9 for i in range(1, n):
10 if i%size == 0:
11 left[i] = num[i]
12 else:
13 left[i] = max(left[i-1], num[i])
14
15 j = n - 1 - i
16 if (j+1)%size == 0:
17 right[j] = num[j]
18 else:
19 right[j] = max(right[j+1], num[j])
20 dp = []
21 for i in range(n-size+1):
22 dp.append(max(right[i], left[i+size-1]))
23 return dp

12. 旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

解:

类二分的方法,不断的收缩两端边界。当然要先判断是否旋转了。

 1 class Solution:
2 def minNumberInRotateArray(self, rotateArray):
3 # write code here
4 if not rotateArray:
5 return 0
6 if len(rotateArray)==1 or rotateArray[0] < rotateArray[-1]:
7 return rotateArray[0]
8
9 n = len(rotateArray)
10 left, right = 0, n-1
11 while left < right:
12 mid = left + (right-left)//2
13 if rotateArray[mid] > rotateArray[right]: # 最小数字一定在mid右边
14 left = mid + 1 # 左闭右开
15 elif rotateArray[mid] < rotateArray[right]: # 最小数字一定在mid左边
16 right = mid
17 else: # 不好判断是在mid左边还是右边,一个一个试
18 right -= 1
19 return rotateArray[right]

13.丑数

把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

解:

一个丑数一定由另一个丑数乘以2或者乘以3或者乘以5得到,从1开始乘以2,3,5,就得到2,3,5三个丑数,在从这三个丑数出发乘以2,3,5就得到4,6,10, 6,9,15, 10,15,25九个丑数,这种方法会得到重复的丑数,而且题目要求第N个丑数,这样的方法得到的丑数也是无序的。那么我们可以维护三个队列:
(1)丑数数组: 1
乘以2的队列:2
乘以3的队列:3
乘以5的队列:5
选择三个队列头最小的数2加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(2)丑数数组:1,2
乘以2的队列:4
乘以3的队列:3,6
乘以5的队列:5,10
选择三个队列头最小的数3加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(3)丑数数组:1,2,3
乘以2的队列:4,6
乘以3的队列:6,9
乘以5的队列:5,10,15
选择三个队列头里最小的数4加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(4)丑数数组:1,2,3,4
乘以2的队列:6,8
乘以3的队列:6,9,12
乘以5的队列:5,10,15,20
选择三个队列头里最小的数5加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(5)丑数数组:1,2,3,4,5
乘以2的队列:6,8,10,
乘以3的队列:6,9,12,15
乘以5的队列:10,15,20,25
选择三个队列头里最小的数6加入丑数数组,但发现有两个队列头都为6,所以弹出两个队列头,同时将12,18,30放入三个队列;
……
实现的时候,没有必要维护三个队列,只需要维护三个队列头(更新指针)即可。
 1 class Solution:
2 def GetUglyNumber_Solution(self, index):
3 # write code here
4 if index < 7:
5 return index
6 p2, p3, p5 = 0, 0, 0
7 arr = [0]*index
8 arr[0] = 1
9 for i in range(1, index):
10 arr[i] = min(arr[p2]*2, arr[p3]*3, arr[p5]*5)
11 # 三个if可能进入一个或多个
12 if arr[i] == arr[p2]*2: # 如果选了乘以2的队列,更新队头指针
13 p2 += 1
14 if arr[i] == arr[p3]*3:
15 p3 += 1
16 if arr[i] == arr[p5]*5:
17 p5 += 1
18 return arr[index-1]

维护一个堆,每次都把三个可能的丑数push进堆,但取出第i个丑数的时候,要保证取出之后堆顶是更大的丑数

 1 import heapq
2 class Solution:
3 def GetUglyNumber_Solution(self, index):
4 # write code here
5 if index < 7:
6 return index
7 heap = [1]
8 for _ in range(index):
9 res = heapq.heappop(heap)
10 while heap and res == heap[0]:
11 res = heapq.heappop(heap)
12 q2, q3, q5 = res*2, res*3, res*5
13 for num in [q2, q3, q5]:
14 heapq.heappush(heap, num)
15 return res
 
14. 两个链表的第一个公共节点
输入两个链表,找出它们的第一个公共结点。
解:
用哈希表保存一个链表的节点,然后遍历第二个链表即可。 
 1 # class ListNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.next = None
5 class Solution:
6 def FindFirstCommonNode(self, pHead1, pHead2):
7 # write code here
8 if not pHead1 or not pHead2:
9 return None
10 linkedList1Nodes = set()
11 p = pHead1
12 while p:
13 linkedList1Nodes.add(p)
14 p = p.next
15
16 p = pHead2
17 while p:
18 if p in linkedList1Nodes:
19 return p
20 p = p.next
21 return None

如果两个链表有公共节点,那么肯定会各自在某个节点处开始链向同一个节点。假设链表1长度为a+n,链表2长度为b+n,同时出发,p1到达链表1尾部的时候p2走到链表2的a+n处。这时p1再从链表2头部开始,当p2到达尾部时,p1处在链表2的b-a处。将p2从链表1头部开始,如果有公共节点,那么都再走a步就到达公共节点,否则都走a+n步到尾部。

代码及其简洁

 1 # class ListNode:
2 # def __init__(self, x):
3 # self.val = x
4 # self.next = None
5 class Solution:
6 def FindFirstCommonNode(self, pHead1, pHead2):
7 # write code here
8 if not pHead1 or not pHead2:
9 return None
10 p1, p2 = pHead1, pHead2
11 while p1 != p2:
12 p1 = p1.next if p1 else pHead2
13 p2 = p2.next if p2 else pHead1
14 return p1

15. 数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

解:

归并排序的变式。先分成最低单位,考虑比较相邻的数字,再合并。合并过程中,出现前面的数组值array[i]大于后面数组值array[j]时;则前面数组array[i]~array[mid]都是大于array[j]的,count += mid+1 - i。例如5大于4, 那么5,7都会大于4,逆序对个数增加2

 1 class Solution:
2 def __init__(self):
3 self.count = 0
4
5 def InversePairs(self, data):
6 # write code here
7 if not data:
8 return 0%1000000007
9 self.mergeSort(data)
10 return self.count%1000000007
11
12 def mergeSort(self, array):
13 if len(array) <= 1:
14 return array
15 num = len(array) // 2
16 left = self.mergeSort(array[:num])
17 right = self.mergeSort(array[num:])
18 # merge
19 l, r = 0, 0
20 result = []
21 while l<len(left) and r<len(right):
22 if left[l] < right[r]:
23 result.append(left[l])
24 l += 1
25 else:
26 result.append(right[r])
27 r += 1
28 # 前面的array[i]大于后面的array[j]时,array[i]~array[mid]都比array[j]大,统计逆序对
29 self.count += len(left) - l
30 if l < len(left):
31 result += left[l:]
32 elif r < len(right):
33 result += right[r:]
34 return result

16.数组中出现次数超过一半的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

解:

快排取中间位置的数,再遍历一遍统计个数判断,O(NlogN)

哈希表统计,线性复杂度,但需要额外空间

 1 from collections import Counter
2 class Solution:
3 def MoreThanHalfNum_Solution(self, numbers):
4 # write code here
5 if not numbers:
6 return 0
7 n = len(numbers)
8 count = Counter(numbers)
9 for k, v in count.items():
10 if v > n//2:
11 return k
12 return 0
如果有符合条件的数字,则它出现的次数比其他所有数字出现的次数和还要多,对数组同时去掉两个不同的数字,到最后剩下的一个数就是该数字。。在遍历数组时保存两个值:一是数组中一个数字,一是次数。遍历下一个数字时,若它与之前保存的数字相同,则次数加1,否则次数减1;若次数为0,则保存下一个数字,并将次数置为1。遍历结束后,所保存的数字即为所求。然后再判断它是否符合条件即可。
 1 class Solution:
2 def MoreThanHalfNum_Solution(self, numbers):
3 # write code here
4 if not numbers:
5 return 0
6 n = len(numbers)
7 res = numbers[0]
8 count = 1
9 for i in range(n):
10 if count == 0:
11 res = numbers[i] # 更新res为当前元素(新取两个数,看看是否相同)
12 count = 1
13 elif numbers[i] == res:
14 count += 1 # 相同则计数+1
15 else:
16 count -= 1 # 不同则计数-1(去掉两个不同的数)
17
18 count = 0
19 for i in range(n):
20 if numbers[i] == res:
21 count += 1
22 return res if count > n//2 else 0

剑指offer-链表&数组的更多相关文章

  1. 剑指Offer:数组中出现次数超过一半的数字【39】

    剑指Offer:数组中出现次数超过一半的数字[39] 题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如,输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于这 ...

  2. 《剑指offer》数组中只出现一次的数字

    本题来自<剑指offer> 数组中只出现一次的数字 题目: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 思路: 思路一:在<剑指of ...

  3. 剑指 Offer 51. 数组中的逆序对 + 归并排序 + 树状数组

    剑指 Offer 51. 数组中的逆序对 Offer_51 题目描述 方法一:暴力法(双层循环,超时) package com.walegarrett.offer; /** * @Author Wal ...

  4. 剑指 Offer 39. 数组中出现次数超过一半的数字 + 摩尔投票法

    剑指 Offer 39. 数组中出现次数超过一半的数字 Offer_39 题目描述 方法一:使用map存储数字出现的次数 public class Offer_39 { public int majo ...

  5. 剑指 Offer 03. 数组中重复的数字

    剑指 Offer 03. 数组中重复的数字 找出数组中重复的数字. 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知 ...

  6. 菜鸟刷题路:剑指 Offer 03. 数组中重复的数字

    剑指 Offer 03. 数组中重复的数字 哈希表/set class Solution { public int findRepeatNumber(int[] nums) { HashSet< ...

  7. 剑指 Offer 39. 数组中出现次数超过一半的数字

    剑指 Offer 39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 你可以假设数组是非空的,并且给定的数组总是存在多数元素. 示例 1: 输入: [ ...

  8. 5.1 剑指 Offer 03. 数组中重复的数字

    类型题:剑指 Offer 03. 数组中重复的数字 找出数组中重复的数字.在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了, ...

  9. 力扣 - 剑指 Offer 39. 数组中出现次数超过一半的数字

    题目 剑指 Offer 39. 数组中出现次数超过一半的数字 思路1(排序) 因为题目说一定会存在超过数组长度一半的一个数字,所以我们将数组排序后,位于length/2位置的一定是众数 代码 clas ...

  10. 【剑指Offer】数组中只出现一次的数字 解题报告(Python)

    [剑指Offer]数组中只出现一次的数字 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-intervie ...

随机推荐

  1. 如何发挥微博客在seo营销中的作用

    http://www.wocaoseo.com/thread-158-1-1.html 我们知道,现在微博客已经发展的相当成熟,普通一个人,只要会上网,就能开通属于自己的博客,进而可以时时地通过微博客 ...

  2. vs使用fscanf和fprintf错误警告处理

    严重性代码说明项目文件行 禁止显示状态错误 C4996 fopen('fscanf'.strcmp):This function or variable may be unsafe. 最全解决办法(转 ...

  3. React State

    React 里只需要更新组件的state,然后根据新的 state 重新徐娜然用户界面(不要操作DOM). class Clock extends React.Component { construc ...

  4. eclipse 设置默认编码为Utf-8 详细教程。

    需要设置的几处地方为: Window->Preferences->General ->Content Type->Text->JSP 最下面设置为UTF-8 Window ...

  5. [BUUOJ记录] [GYCTF]EasyThinking

    主要考察ThinkPHP6.0的一个任意文件写入的CVE以及突破disable_function的方法. ThinkPHP6.0.0任意文件操作漏洞 理论分析 进入题目是一个简单的操作页面,dirma ...

  6. es6使用箭头函数需要注意的问题

    this问题 箭头函数没有它自己的this值,箭头函数内的this值继承自外围作用域,谁定义的函数,this指向谁 箭头函数要实现类似纯函数的效果,必须剔除外部状态.所以箭头函数不具备普通函数里常见的 ...

  7. 轻轻松松学CSS:媒体查询

    轻轻松松学CSS:利用媒体查询创建响应式布局 媒体查询,针对不同的媒体类型定制不同的样式规则.在网站开发中,可以创建响应式布局. 一.初步认识媒体查询在响应式布局中的应用 下面实例在屏幕可视窗口尺寸大 ...

  8. ORA-00119: ORA-00132: 解决办法 -九五小庞

    问题描述: 1. em打开中提示 https://localhost:1158/em/console/database/instance/repDown?target=orclweng&typ ...

  9. mysql jdbc连接时的小问题java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)

    这次重新修改老程序时出现了上面的错误,排查过后最终找到问题所在:root帐户默认不开放远程访问权限,所以需要修改一下相关权限. 打开MySQL目录下的my.ini文件(win10默认安装在C:\Pro ...

  10. SMBMS

    SMBMS(Supermarket Billing Management System ) 目录 SMBMS(Supermarket Billing Management System ) 1. 项目 ...