每日一練——整數反轉、括號生成
整數反轉:
要求:
給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。
假設我們的環境只能儲存得下 32 位的有符號整數,則其數值範圍為 [−231, 231 − 1]。請根據這個假設,如果反轉後整數溢位那麼就返回 0。
方法很簡單,但是要注意不要忽略負數的輸入。
法一:python取巧的寫法,將整形轉換成字串,利用字串切片操作輕鬆實現反向。
def reverse(self, x: int) -> int:
str_x = str(abs(x))
res = int(str_x[ ::-1])
if x < 0:
res = -res
return res if -(1 << 31) < res < (1 << 31) - 1 else 0
其中涉及位的操作:
法二:
對結果賦值為0,對x進行取餘運算,每次除以10,餘數加到結果後。當商與餘數都為0時,說明x以全部轉換完畢。
具體實現如下:
def reverse(self, x: int) -> int:
flag = 1 if x >= 0 else - 1 # 記錄下當前x的符號
x = abs(x)
ans = 0
quotient,remainder = divmod(x,10) #此處的divmod等價於quotient = x //10 ,remainder = x % 10
while quotient > 0 or remainder > 0:
ans = ans * 10 + remainder
quotient, remainder = divmod(quotient, 10)
ans *= flag
return ans if -(1<< 31) < ans < (1<<31)-1 else 0
括號生成:
數字 n 代表生成括號的對數,請你設計一個函式,用於能夠生成所有可能的並且 有效的 括號組合。
例:
法1:每次加入整個括號
我們可以在已有括號序列的每個間隔中加入同時帶有左括號與右括號的一個完整括號。每個括號序列的間隔數等於其長度加一。
具體實現如下:
def generateParenthesis(self, n: int) -> List[str]:
if n <= 0:
return []
res = set() #用集合儲存結果,可去重
for _ in range(n): # 需要新增n個括號,所以迴圈n次
if len(res) == 0:
res.add("()")
else:
tmp = set() #設定一個暫時的集合來儲存新生成的括號序列
for x in res: #遍歷res,x為每一個不同的括號序列
for i in range(len(x) + 1): #在每一個間隔中加入()並將新生成的序列存入tmp
tmp.add(x[:i] + "()" + x[i:])
res = tmp
return list(res)
簡化後可得以下程式碼
def generateParenthesis(self, n: int) -> List[str]:
if n <= 0:
return []
res = {"()",}
for _ in (range(n - 1)):
res = {x[:i] + "()" + x[i:] for x in res for i in range(len(x) + 1)}
return list(res)
執行結果:
法二: 每次加入半個括號,利用dfs的思想
可以模擬每次只加半個括號的過程,第一個必須新增左括號,則得到“(”,下一個可以繼續加入左括號,也可以加入右括號。如果下一個加入的是左括號,則得到“((”接下來可以連續加入兩個右括號。以此類推可得到規律:
當左括號個數小於n時,可繼續新增左括號,當右括號小於左括號數時,可繼續新增右括號。
既然利用dfs,則就要考慮遞迴的basecase,很明顯,此題的最終結束條件為遞迴深度等於2n。
遞迴的重要特性就是本層只管本層的事。遞迴的每一層只需要做一件事,:加左括號或者加右括號。
遞迴時需要輸入的引數有:現有的括號序列,左括號數,右括號數,需生成括號數,遞迴深度。
最終程式碼如下:
def generate_parentheses(n):
res = []
sample = ""
def generate_parentheses_helper(sample, depth, n, left_num, right_num):
if depth == 2 * n: # basecase
res.append(sample)
return
if left_num < n:
generate_parentheses_helper(sample + "(", depth + 1, n, left_num + 1, right_num)
if right_num < left_num:
generate_parentheses_helper(sample + ")", depth + 1, n, left_num, right_num + 1)
if n != 0:
generate_parentheses_helper(sample, 0, n, 0, 0)
return res
執行結果:
很明顯,法1簡單快捷,時間複雜度低。但法二可以鍛鍊寫遞迴,寫dfs的能力。