1.主要思想:
将问题递归的分成若干个小问题,直至满足边界条件返回结果,最后将结果合并。
2.使用场景:
各子问题之间相互独立。
3.Leetcode题解:
-
题目
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于[n/2]的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。 -
思路
- 边界条件:子数组中最少有一个元素
- 拆分数据:将数组左右二分为两个子数组
- 合并结果:子数组中只有一个元素时,该元素即为多数元素;左子数组的多数元素left和右子数组的多数元素right相等时,left即为所求;不等时则需要比较right和left在nums中的出现次数获得最终结果
-
代码
class Solution: def majorityElement(self, nums: List[int]) -> int: # 先设置边界条件 if nums is None: return None if len(nums) ==1: return nums[0] # 拆分成小问题 left = self.majorityElement(nums[:len(nums)//2]) right = self.majorityElement(nums[len(nums)//2:]) # 合并结果 if left == right: return left else: if nums.count(left) > nums.count(right): return left else: return right
-
扩展
摩尔投票法,前提条件所求元素在数组中出现次数过半
class Solution: def majorityElement(self, nums: List[int]) -> int: res_num = nums[0] count = 1 for num in nums[1:]: if num == res_num: count += 1 elif count == 0: count = 1 res_num = num else: count -= 1 return res_num
耗时最短的做法
class Solution: def majorityElement(self, nums: List[int]) -> int: nums.sort() return nums[len(nums)//2]
-
题目
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
-
思路
- 边界条件:子数组中最少有一个元素
- 拆分数据:将数组左右二分为两个子数组
- 合并结果:子数组中只有一个元素时,该元素即为所求结果;左子数组的结果left,右子数组的结果right和(从右到左计算左边的最大子序和+从左到右计算右边的最大子序和)中最大值即为所求
-
代码
class Solution: def maxSubArray(self, nums: List[int]) -> int: if nums is None: return None nums_len = len(nums) if nums_len ==1: return nums[0] left = self.maxSubArray(nums[:nums_len//2]) right = self.maxSubArray(nums[nums_len//2:]) # 从右至左计算左边子数组的最大子序和 max_l = nums[nums_len//2-1] temp = 0 for left_i in range(nums_len//2-1,-1,-1): temp += nums[left_i] max_l = max(temp,max_l) # 从左至右计算右边子数组的最大子序和 max_r = nums[nums_len//2] temp = 0 for right_i in range(nums_len//2,nums_len): temp += nums[right_i] max_r = max(temp,max_r) return max(left,right,max_l+max_r)
-
扩展
因为负数相加,总和会越来越小,所以当子序列和小于等于0时,重新寻找新的连续子序列
class Solution: def maxSubArray(self, nums: List[int]) -> int: max_sum = nums[0] mysum = 0 for i in nums: if mysum > 0: mysum += i else: mysum = i max_sum = max(mysum, max_sum) return max_sum
-
题目
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
-
思路
- 边界条件:n 最后为0时返回1
- 拆分数据:n除以2的余数为1时 n=n-1;否则n=n/2且x = x*x
- 合并结果:n除以2的余数为1时计算结果并返回,为0时,更新x值,即将(x^2)带入myPow函数中
-
代码
class Solution: def myPow(self, x: float, n: int) -> float: if n < 0: x = 1/x n = -n if n == 0: return 1 if n%2 == 1: return x * self.myPow(x,n-1) return self.myPow(x*x,n/2)
-
扩展
快速幂(二进制角度):通过增加底数减少幂运算次数,从而降低时间复杂度O(n)为O(logn)
eg:Pow(2,10) 10的二进制写法是1010
(2^{10} = 2^0 * 2^2 * 2^0 * 2^8 = 2^{2^1}*2^{2^3})class Solution: def myPow(self, x: float, n: int) -> float: if n < 0: x,n = 1/x,-n if n==0: return 1 res = 1 while n > 0: # 判断最低位是否是1 if n&1: res *= x # 右移一位,相当于除以2 n=n>>1 x *= x return res