Leetcode-递归&分治
Posted chaojunwang-ml
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode-递归&分治相关的知识,希望对你有一定的参考价值。
50. Pow(x, n) https://leetcode-cn.com/problems/powx-n/
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。
解:
直接调库函数,不过面试中肯定不可以。
暴力,写个循环直接乘,O(N)。
分治,y = x**(n/2)。 n是偶数,两部分一样只计算一边即可,res = y*y。n为奇数,res = y*x*y。一直这样算到x**1 或 x**0。时间复杂度为O(logN)。
递归实现
class Solution: def myPow(self, x: float, n: int) -> float: if not n: return 1 if n < 0: return 1 / self.myPow(x, -n) if n % 2: return x * self.myPow(x, n-1) # n为奇数,通过n-1次方去做 return self.myPow(x*x, n/2) # n为偶数
迭代实现,分治的最小计算乘子为x。 例如,x**(7) = x * x**(6) = x * (x**2)**(3) = x * (x**2) * ((x**2)**2)**1
class Solution: def myPow(self, x: float, n: int) -> float: if not n: return 1 if n < 0: # n小于0的话就转化成n大于0的形式,把x变为1/x即可 x = 1/x n = -n res = 1 while n: # 分治的最小单位是1次方 if n & 1: # n 为奇数,先乘多出来的一个x res *= x x *= x # 基本乘子从x变为x**2 n >>= 1 # n = floor(n/2) return res
169. 求众数 https://leetcode-cn.com/problems/majority-element/
给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋
的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。
解:
暴力,两层嵌套循环,枚举所有x,针对某一个x去数组里面计数。O(N2)
直接排序后取中间元素,肯定是众数。O(NlogN)
class Solution: def majorityElement(self, nums: List[int]) -> int: nums.sort() n = len(nums) return nums[int((n-1)/2)]
遍历一次,用hashmap存元素计数,最后再去map里面看一下计数最大的元素是哪个。O(N)
class Solution: def majorityElement(self, nums: List[int]) -> int: count = dict() for x in nums: if x in count: count[x] += 1 else: count[x] = 1
max_count = 0 for key, value in count.items(): if value > max_count: max_count = value res = key return res # 或者直接利用字典的get函数,一行就可以 return max(count, key=count.get)
分治递归求解,直到所有的子问题都是长度为 1 的数组。由于传输子数组需要额外的时间和空间,所以我们实际上只传输子区间的左右指针 low 和 high 表示相应区间的左右下标。
长度为 1 的子数组中唯一的数显然是众数,直接返回即可。
如果回溯后某区间的长度大于 1 ,必须将左右子区间的值合并。如果它们的众数相同,那么显然这一段区间的众数是它们相同的值。否则,需要比较两个众数在整个区间内出现的次数来决定该区间的众数。
原问题的答案就是下标为 0 和 n 之间的众数这一子问题。
时间复杂度为O(NlogN)
class Solution: def majorityElement(self, nums: List[int]) -> int: return self.helper(nums, 0, len(nums)-1) def helper(self, nums, low, high): if low == high: # 长度为1的子数组,众数就是那唯一的元素 return nums[low] # 子数组长度大于1,递归的去找左右数组的众数 mid = low + (high - low) // 2 left = self.helper(nums, low, mid) right = self.helper(nums, mid+1, high) if left == right: # 判断左右两个众数的关系,如果左右众数相同,那一定是左右总体的众数 return left # 如果不相同,总体上count大的那个是整体的众数 left_count, right_count = 0, 0 for i in range(low, high+1): if nums[i] == left: left_count += 1 elif nums[i] == right: right_count += 1 return left if left_count > right_count else right
以上是关于Leetcode-递归&分治的主要内容,如果未能解决你的问题,请参考以下文章