50 Pow(x, n) (Facebook 在半年内面试常考)
Base Case: n == 0
Function: F(x ^ n) = F(x ^ (n // 2)) * F(x ^ (n // 2))
不论我们返回时候如何,我们执行第一步,先设立Base Case:
if n == 0: return 1
完了以后,我们要对大问题进行拆分,也就是不断的对b的值折半
拆分:
half = self.myPow(x, n // 2)
当拆分到了最小的问题,满足base case n == 0 的时候,我们则进行返回,返回时候有三种可能
Function的三种可能性:
时间复杂度 = 一叉树里面每层的时间复杂度 * 层数 = 1 * log(b) = log(b)
空间复杂度 = O(h) 也就是一叉树的层数 = log(b)
Solution:
def myPow(self, x, n):
if n == 0:
return 1
if n < 0:
return 1.0 / self.myPow(x, -n)
half = self.myPow(x, n // 2)
if n % 2 == 0:
return half * half
return half * half * x
78 子集(Facebook、字节跳动、亚马逊在半年内面试中考过)
# 方法1:调用库函数
from itertools import combinations
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
return [s for n in range(len(nums) + 1) for s in combinations(nums,n)]
因为本题求解的是不重复的子集得问题,所以可以每次把新的元素放在之前已经拿出来的元素的位置,并且保留之前拿出来的结果,
# 简化的写法
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = [[]]
for i in nums:
res += [[i] + num for num in res]
return res
169 多数元素 (亚马逊、字节跳动、Facebook 在半年内面试中考过)
时间复杂度是 O(M*N)的
from collections import Counter
class Solution:
def majorityElement(self, nums: List[int]) -> int:
counter = Counter(nums)
return [k for k, v in counter.items() if v > len(nums) // 2][0]
时间复杂度是:O(n)
参考
动画演示
class Solution:
def majorityElement(self, nums: List[int]) -> int:
major = 0
count = 0
for num in nums:
if count == 0:
major = num
if num == major:
count += 1
else:
count -= 1
return major
class Solution:
def majorityElement(self, nums: List[int]) -> int:
if not nums:return 0
if len(nums) == 1:return nums[0]
mid = len(nums) // 2
a = self.majorityElement(nums[:mid])
b = self.majorityElement(nums[mid:])
if a == b:
return a
return [a,b][nums.count(b) > mid]
17 电话号码的字母组合(亚马逊在半年内面试常考)
采用分治的思想
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
mapping = {'2':'abc','3':'def','4':'ghi','5':'jkl','6':'mno',
'7':'pqrs','8':'tuv','9':'wxyz'}
if not digits:return []
if len(digits) == 1:
return list(mapping[digits[0]])
pre = self.letterCombinations(digits[:-1])
additional = mapping[digits[-1]]
return [s + c for s in pre for c in additional]
51 N 皇后(字节跳动、苹果、谷歌在半年内面试中考过)
这个题需要用到一点平面几何的知识,来进行左右对角线路径的判断,如下图所示:
def solveNQueens(self, n):
# queue 存着每一行的皇后的位置,即他的每一行的元素的位置在哪里
# xy_dif 的意思是 x-y ,代表一条对角线
# xy_sum 的意思是x + y,代表另一条对角线
def DFS(queens, xy_dif, xy_sum):
p = len(queens)
# 下面是递归终止条件
if p==n: # 说明已经将每一列的皇后已经加满了,
result.append(queens)
return None
# 遍历当前一行所在的所有列
for q in range(n):
# 判断列是否在之前的列里面,是不是在和之前的这些左对角线和右对角线相冲突,
# 如果没有冲突的话,就把它加到下一行
if q not in queens and p-q not in xy_dif and p+q not in xy_sum:
DFS(queens+[q], xy_dif+[p-q], xy_sum+[p+q])
result = []
DFS([],[],[])
# 为了按照题目的要求输出一个二维数组
return [ ["."*i + "Q" + "."*(n-i-1) for i in sol] for sol in result]