實現 pow(x, n) ,即計算 x 的 n 次冪函數。python
示例 1:數組
輸入: 2.00000, 10
輸出: 1024.00000
示例 2:函數
輸入: 2.10000, 3
輸出: 9.26100
示例 3:code
輸入: 2.00000, -2
輸出: 0.25000
解釋: 2-2 = 1/22 = 1/4 = 0.25
說明:排序
-100.0 < x < 100.0
n 是 32 位有符號整數,其數值範圍是 [−231, 231 − 1] 。
題目難度: Midium遞歸
思路1: 二分 + 遞歸element
首先看到題目,最直觀的想法就是一次遍歷,每次都乘上x
。時間複雜度爲$O(n)$, 空間複雜度爲$O(1)$.
$f(n)=f(n-1)*x$leetcode
一般而言,最暴力的方法不會是效率最高的方法, 這題也不例外。好比get
$$\begin{align}2^4=2^2*2^2 \\ 2^5=2^3*2^2\end{align}$$it
咱們其實並不須要計算$2^1$一直到$2^n$. 所以能夠獲得一個更高效的計算公式
$$x^n=\begin{cases} x^{\frac{n+1}{2}}*x^{\frac{n-1}{2}}, if(n\%2!=0)\\ x^{\frac{n}{2}}*x^{\frac{n}{2}}, if(n\%2==0)\end{cases}$$
def myPow(x -> float, n -> int) -> float: if n == 0: return 1 flag = 1 if n > 0 else -1 n = abs(n) def helper(x, n): if n == 0: return 1 # 若是是奇數 if n % 2: res = helper(x, (n-1) // 2) return res * res * x # 若是是偶數 res = helper(x, n // 2) return res * res return helper(x, n) if flag > 0 else 1. / helper(x, n)
時間複雜度: $O(log(n))$, 空間複雜度:$O(log(n))$.
思路2
二分 + 迭代
def myPow(x -> float, n -> int) -> float: if n == 0: return 1 flag = 1 if n > 0 else -1 n = abs(n) res = 1. ans = x while n > 0: if n % 2: res *= ans ans *= ans n //= 2 return res if flag > 0 else 1. / res
時間複雜度爲$O(log(n))$, 空間複雜度爲$O(1)$
相比於第二種思路, 我的以爲第一種思路更容易理解, 但須要額外的空間複雜度。 方法二, 想了好久仍是不能徹底理解。
給定一個整數數組 nums ,找到一個具備最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
示例:
輸入: [-2,1,-3,4,-1,2,1,-5,4]
輸出: 6
解釋: 連續子數組 [4,-1,2,1] 的和最大,爲 6。
進階:
若是你已經實現複雜度爲 O(n) 的解法,嘗試使用更爲精妙的分治法求解。
這道題是一個比較典型的動態規劃問題, 既然是動態規劃問題, 那就須要明確選擇和狀態
狀態: $f(n)$表示以nums[n-1]結束的最大子序列和.
選擇: 是否選擇元素做爲最大和的連續子數組的元素。
狀態轉移方程:
$$ f(n) =\begin{cases} f(n-1) + nums[n-1], &if (f(n-1) + nums[n-1]>nums[n-1])\\ nums[n-1],&else\end{cases} $$
通俗一點來理解就是,若是當前的元素不能使最大子序和變大,則將已有的子序列捨棄。
基於狀態轉移方程, 能夠寫出以下代碼
def maxSubArray(nums): if not nums: return n = len(nums) b = nums[0] res = b for i in range(1, n): b = max(b+nums[i], nums[i]) res = max(res, b) return res
思路2
分治法
最大子序和能夠有3種狀況
最後的最大值爲左半部分的最大值
, 右半部分的最大值
, 跨越左半部分和右半部分的最大值
之間的最大值
def maxSubArray(nums): if not nums: return n = len(nums) if n == 1: return nums[0] # 左半部分的最大值 max_left = maxSubArray(nums[:n//2]) # 右半部分的最大值 max_right = maxSubArray(nums[n//2:]) # 計算中間的最大子序和 # 從右到左計算左邊的最大子序和 max_l = nums[len(nums) // 2 - 1] tmp = 0 for i in range(len(nums) // 2 - 1, -1, -1): tmp += nums[i] max_l = max(tmp, max_l) # 從左到右計算右邊的最大子序和 max_r = nums[len(nums) // 2] tmp = 0 for i in range(len(nums) // 2, len(nums)): tmp += nums[i] max_r = max(tmp, max_r) #返回三個中的最大值 return max(max_right,max_left,max_l+max_r)
時間複雜度爲$nlog(n)$, 空間複雜度爲$O(log(n))$
給定一個大小爲 n 的數組,找到其中的多數元素。多數元素是指在數組中出現次數大於 ⌊ n/2 ⌋ 的元素。
你能夠假設數組是非空的,而且給定的數組老是存在多數元素。
示例 1:
輸入: [3,2,3] 輸出: 3
示例 2:
輸入: [2,2,1,1,1,2,2] 輸出: 2
最簡單, 最直接的想法就是排序, 去最中間的數便可, 對應的複雜度就是排序的複雜度。時間複雜度爲$O(nlog(n))$, 空間複雜度爲$log(n)$
思路1
分治
根據題目對衆數的定義, 若是將數組劃分爲左右兩部分,那麼數組的衆數必然是其中一個部分的衆數。
def majorityElement(nums): if not nums: return def helper(low, high): if low == high: return nums[low] mid = (low + high) // 2 left = helper(low, mid) right = helper(mid, high) if left == right: return left # 統計左半部分的衆數出現次數 cnt_left = sum([1 for i in range(low, high+1) if nums[i] == left]) # 統計右半部分的衆數出現次數 cnt_right = sum([1 for i in range(low, high+1) if nums[i] == right]) # return left if cnt_left > cnt_right else riht return helper(0, len(nums)-1)
時間複雜度爲$O(nlog(n))$, 空間複雜度爲$O(log(n))$
思路2
投票
維護一個衆數得分, 只有噹噹前衆數的得分等於0時, 修改衆數
def majorityElement(nums): if not nums: return score = 1 candidate = nums[0] for n in nums[1:]: if score == 0: candidate = n if n == candidate: score += 1 else: score -= 1 return candidate
時間複雜度爲$O(n)$, 空間複雜度爲$O(1)$