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

 

你可能感兴趣的:(算法&数据结构)