leetcode 每日刷題記錄:easy 題

刷力扣,不得不說每個簡單的題下面,騷操作都不少 ;簡直把時間&空間複雜度和代碼簡潔性玩到了極致;導致有些代碼對於我這菜雞太難讀懂了。

所以我在記錄自己的愚蠢的代碼同時,考慮了自己的理解能力,和力扣題目的評論區精華,選擇了而我能看得懂的較簡潔的代碼來記錄下。畢竟刷一邊是不可能記住的,但是可以基於自己的理解力,不停地理解更好的做法。

 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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章