1. 題目
求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。
2. 解題思路
詳情見 面試題64. 求 1 + 2 + … + n(邏輯符短路,清晰圖解)
1~n的加和,這很明顯可以用高斯求和公式,sum = n * (n+1) / 2。
因爲不能用這些語句,所以迭代、動態規劃、遞歸都不能用。
關鍵是如何計算 n * (n+1), n*(n+1) = n2 + n,所以只要能求出n 2 即可。
2.1 使用庫函數
使用python中的庫函數math.pow(),計算n2 ,用>>1 來計算除以2。
2.2 邏輯符短路
使用邏輯符短路來替代遞歸的基線條件,實現終止遞歸。
在python中,A and B和A or B 這兩個邏輯表達式的值不爲True或者False,而是A或者B的值。
python中的與(and)、或(or)、非(not)與java和c的不同之處在於
A and B:若A爲假(如:False, 0, [], {}, ""等),則短路(不用再判斷B是否爲真,整個邏輯表達式已經爲False了),表達式的值爲A的值。
若A爲真,則繼續判斷B的值,但是不管邏輯表達式是真還是假,表達式的值都爲B的值,而不是True或者False。
A or B:
若A爲假(如:False, 0, [], {}, ""等),則繼續判斷B的值,不管最後邏輯表達式是真還是假,表達式的值都B的值。
若A爲真,則短路(不用在判斷B的值是真還是假了,整個邏輯表達式已經爲True了),表達式的值爲A的值。
3. 代碼實現
3.1 使用庫函數
import math
class Solution:
def sumNums(self, n: int) -> int:
"""
(n * (n+1)) // 2, n 和 n+1一定有一個是偶數,能夠被2除盡的
--> (n*(n+1))>>1
"""
# 使用庫函數,但是本質是否仍然用了乘除或者條件判斷語句??
return (n + int(math.pow(n, 2))) >> 1
3.2 邏輯符短路
class Solution:
def __init__(self):
self.res = 0
def sumNums(self, n: int) -> int:
n > 1 and self.sumNums(n - 1)
self.res += n
return self.res
3.3 優化
class Solution:
def sumNums(self, n: int) -> int:
"""
python中的與(and)、或(or)、非(not)與java和c的不同之處在於
A and B: 若A爲False或其他空值(如:0, [], {}, ""等),則短路(不用再判斷B是否爲真,整個邏輯表達式已經爲False了)
A or B:
"""
return n and (n + self.sumNums(n-1))
4. 總結
邏輯運算符短路原則,有學到新東西了。而且還能如此將邏輯運算符與遞歸相結合,真是非常巧妙的思想。
5. 參考文獻
[1] 劍指offer叢書
[2] 劍指Offer——名企面試官精講典型編程題