刷力扣,不得不說每個簡單的題下面,騷操作都不少 ;簡直把時間&空間複雜度和代碼簡潔性玩到了極致;導致有些代碼對於我這菜雞太難讀懂了。
所以我在記錄自己的愚蠢的代碼同時,考慮了自己的理解能力,和力扣題目的評論區精華,選擇了而我能看得懂的較簡潔的代碼來記錄下。畢竟刷一邊是不可能記住的,但是可以基於自己的理解力,不停地理解更好的做法。
1. 整數反轉
題目描述: 給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。見 力扣:整數反轉
輸入:123 -123 120
輸出: 321 -321 21
我的解法:代碼不夠簡潔,沒有考慮數字的範圍
def reverse(x: int) -> int:
st = [a for a in str(x)]
new_st = ['0']*len(st)
if st.__contains__('-'):
new_st[0] = '-'
for i in range(1,len(st)):
new_st[i] = st[len(st ) -i ]
else:
for i in range(len(st)):
new_st[i] = st[len(st)-i -1]
if new_st[0] == '0' :
new_st = new_st[1:]
elif new_st[0] == '-' and new_st[1] == '0':
new_st = new_st.pop(1)
return int(''.join(new_st))
正確的解法之一: 對於數字的反轉用數組的切片輕易地實現了:
str_x[len(str_x)-1::-1].lstrip("0").rstrip("-")
def reverse(x: int) -> int:
if x == 0:
return 0
str_x = str(x)
x = ''
if str_x[0] == '-':
x += '-'
# 明顯這個代碼更簡潔
x += str_x[len(str_x)-1::-1].lstrip("0").rstrip("-")
x = int(x)
if -2 ** 31 < x < 2 ** 31 - 1:
return x
return 0
2. 判斷一個整數是否是迴文數。
迴文數是指正序(從左向右)和倒序(從右向左)讀都是一樣的整數。 見 力扣: 迴文數
輸入:121 -121 10
輸出: true false false
我的解答:在數組遍歷是,只取前一半的對比:
def isPalindrome( x: int) -> bool:
import math
st = [a for a in str(x)]
#直接用range(floor(len(st)//2)) 也可以
for i in range(math.floor(len(st) // 2)):
if st[i] != st[len(st)-i-1]:
return False
return True
3. 把羅馬字轉爲阿拉伯數字
def romanToanns(s: str) -> int:
Rome = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}
anns = 0
for idx in range(len(s) - 1):
if Rome[s[idx]] < Rome[s[idx + 1]]:
anns -= Rome[s[idx]]
else:
anns += Rome[s[idx]]
return anns + Rome[s[-1]]
4. 有效的括號 題目描述見 【力扣: 有效的括號】
# 我的錯誤的解答,只考慮了括號符號 的對稱性,答案完全不對!!!留待以後改進思路
def isValid(s: str) -> bool:
import math
if s == '':
return True
# st = [a for a in str(s)]
# 直接用range(floor(len(st)//2)) 也可以
dct = {'(': 12, ')': 21, '{': 13, '}': 31, '[': 14, ']': 41}
st = [dct[a] for a in str(s)]
print('st: ', st)
for i in range(math.floor(len(st) // 2)):
if st[i] != st[len(st) - i - 1]:
return False
return True
if __name__ == '__main__':
xx = ["()", "()[]{}", "(]", "([)]", "{[]}"]
for x in xx:
print(x, isValid(x))
精選的正確的解答 用棧+ 字典實現
算法原理 棧先入後出特點恰好與本題括號排序特點一致, 即若遇到左括號入棧,遇到右括號時將對應棧頂左括號出棧,則遍歷完所有括號後 stack 仍然爲空; 建立哈希表 dic 構建左右括號對應關係:key左括號,value 右括號; 這樣查詢 2 個括號是否對應只需 O(1) 時間複雜度; 建立棧 stack,遍歷字符串 s 並按照算法流程一一判斷。 算法流程 如果 c 是左括號,則入棧 push; 否則通過哈希表判斷括號對應關係,若 stack 棧頂出棧括號 stack.pop() 與當前遍歷括號 c 不對應,則提前返回 falsefalsefalse。 提前返回 false 優點: 在迭代過程中,提前發現不符合的括號並且返回,提升算法效率。 解決邊界問題: 棧 stack 爲空: 此時 stack.pop() 操作會報錯; 因此,我們採用一個取巧方法,給 stack 賦初值 ? ,並在哈希表 dic 中建立 key:′?′,value:′?′ 的對應關係予以配合。 此時當 stack 爲空且 c 爲右括號時,可以正常提前返回 false; 字符串 s 以左括號結尾: 此情況下可以正常遍歷完整個 s,但 stack 中遺留未出棧的左括號; 因此,最後需返回 len(stack) == 1,以判斷是否是有效的括號組合。 複雜度分析 時間複雜度 O(N):正確的括號組合需要遍歷 111 遍 s; 空間複雜度 O(N):哈希表和棧使用線性的空間大小。
def isValid(s: str) -> bool:
dic = {'{': '}', '[': ']', '(': ')', '?': '?'}
stack = ['?'] # 棧的初始長度,避免棧爲空而報錯
for c in s:
if c in dic:
stack.append(c)
elif dic[stack.pop()] != c: # stack中的最後一個元素,它對應的value 不等於右括號
return False
return len(stack) == 1