LeetCode-python-自己and大神的解题思路(一)

由于刚开始练习,所以比较菜。python学了感觉跟没学一样,所以想找些题来练习练习。日后将会不断的更新,如果哪位大神有更好的思路可以在评论区留言。

 

1两数之和

 

解题思路:由于刚开始,算法知道的比较少,所以就想来分享一下大神们的思路,20个案例用时40ms。他的思路是这样的:建立一个用来存放检查的字典,用target去逐个减去nums列表里的值,将这些差值存入字典,然后遍历列表nums,如果之后遇到的数字有和字典中的值一样,那么输出字典中之所对应的key(被减数的索引)和当前数的索引。

代码如下

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """

        check={}
        for i in range(len(nums)):
            if nums[i] in check:
                return [check[nums[i]],i]
            else:
                check[target-nums[i]]=i

 

2两数相加

解题思路:之前没有怎么学过链表,对链表不是很懂,在查阅了一些资料之后,稍微有些理解了。如果有说的不对的地方欢迎纠正指导。首先要知道单链表由两部分组成:元素和指针,元素是用来存放数据的,指针是用来存放下一个节点元素的地址。

两数相加就意味着两个链表对应节点的元素值相加。在代码前五行就定义了一个链表,self.val为元素的值,self.next为指针。在写代码的过程中要注意设一个负责进位的变量。具体的代码流程我在代码中加具体的注释。

代码如下

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        #先初始化temp链表,l3链表指向temp的0值地址
        temp = ListNode(0)
        l3 = temp
        a = 0   #进位的数字
        #当l1不为空或者l2不为空或者a不等于0的时候
        while l1 != None or l2 !=None or a != 0:
            if l1 != None:
                #a等于a加上l1当前的值
                a += l1.val
                #l1的指针指向下一个元素,下次调用l1.val就是下一个元素的值
                l1 = l1.next
            if l2 != None:
                a += l2.val      #把l2和l1相应节点的值相加赋给a
                l2 = l2.next
            #temp的下一个的值就是 a%10
            temp.next = ListNode(a%10)   
            temp = temp.next   
            a=a//10
        #l3代替temp来输出链表
        return l3.next

 

另外一种写法的代码

 

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        # 如果有一个链表为空,返回另外一个
        if l1 is None:
            return l2
        if l2 is None:
            return l1
        # tmp是暂存(temporal)
        tmp = ListNode(0)  # 引用ListNode类定义了一个链表节点并赋给tmp
        # res是重置(reset)
        res = tmp  # 赋值
        # flag 标示
        flag = 0  # 初始化
        while l1 or l2:  # l1或l2不为空就持续执行
            tmp_sum = 0  # 链表节点值的和
            if l1:  # 如果l1不为空,把l1的某个节点值的和赋给tmp_sum
                tmp_sum = l1.val  # 把l1的某个节点的值赋给tmp_sum
                l1 = l1.next
            if l2:  # 如果l2不为空,把l2中和l1对应的节点的值加到tmp_sum
                tmp_sum += l2.val
                l2 = l2.next  # 指向下一个节点,为下一次的加和做准备
            tmp_res = ((tmp_sum + flag) % 10)  # 个位数字
            flag = ((tmp_sum + flag) // 10)  # 进位的数
            res.next = ListNode(tmp_res)
            res = res.next  # res后移
            if flag:  # 如果flag不为0,就是对应位置相加后有进位
                res.next = ListNode(1)  # res的下一节点设为1
        res = tmp.next  # 赋值
        del tmp  # 删除tmp变量
        return res  # 返回res链表

 

 

 

7.反转整数

自己的解题思路:首先将输入的有符整数转换为字符串,然后进行判断,正数直接反转,负数去除符号后进行反转,最后将反转后的字符串转换为整数进行输出,在返回的时候加一个判断数字范围的条件。大神的解题思路和我们的差不多,不过他的代码更为简便。

自己代码如下

class Solution:
    def reverse(self, x):
        """
        :type x: int
        :rtype: int
        """
        str_x = str(x)
        if '-' in str_x:
            flip = str_x[1:][::-1]
            result = -int(flip)
        else:
            flip = str_x[::-1]
            result = int(flip)
        return result if -2147483648 < result < 2147483647 else 0

 

大神代码如下

 

class Solution:
    def reverse(self, x):
        """
        :type x: int
        :rtype: int
        """
        flag = 0
        if x > 0:
            flag = 1
        else:
            flag = -1
        s = str(abs(x))[::-1]
        n = int(s) * flag
        return n if n.bit_length() < 32 else 0

 

8字符串转整数 (atoi)

 

这个代码调的我真的要吐了,由于自己的逻辑性不好,所以调了有六七次才通过。希望自己以后在考虑问题的时候逻辑性强一些,考虑问题全一些。

解题思路:按照题目的要求一步一步来,先移除字符串句首的空格,如果句首如果为+或者-,那么就从字符串的第二个字符开始后续工作,如果为空字符就返回0,然后逐位进行遍历判断,是数字就保留,不是数字就截止,最后进行判断,空字符返回0,是数字进行返回并进行范围考虑。

代码如下:

class Solution:
    def myAtoi(self, str):
        """
        :type str: str
        :rtype: int
        """
        str = str.strip()
        if not str:
            return 0
        num = ['0','1','2','3','4','5','6','7','8','9',]
        flag = 1
        if (str[0] == '-'):
            str = str[1:]
            flag= -1
        elif(str[0] == '+'):
            str = str[1:]
        for x in range(len(str)):
            if str[x] not in num:
                str = str[0:x]
                break
        if str == '':
            return 0
        result = int(str)*flag
        if result < -2**31:
            return -2**31
        elif result > 2**31-1:
            return 2**31-1
        else:
            return result

直接上前几名的代码,思路也非常明确。直接从字符串开始一位一位判断,不去转换为整数。

class Solution:
    def myAtoi(self, str):
        """
        :type str: str
        :rtype: int
        """
        if (str == ""):
            return 0
        res = ''
        index = 0
        while index < len(str) and str[index] == ' ':
            index += 1
        if index < len(str) and str[index] in '-+':
            res += str[index]
            index += 1
        while index < len(str) and str[index] in '0123456789':
            res += str[index]
            index += 1
    
        if (res == '' or res == '+' or res == '-'):
            return 0
        if (int(res) > 2**31 - 1):
            return 2**31 - 1
        elif (int(res) < -2**31):
            return -2**31
        else:
            return int(res)

网上还有另外一种思路,就是调用re库 https://www.cnblogs.com/zjltt/p/6955965.html?from=singlemessage&isappinstalled=0 ,这样的话代码用时比较长。他的代码如下:

class Solution:  
    def myAtoi(self, str):  
        """ 
        :type str: str 
        :rtype: int 
        """  
        import re  
        res = re.findall(r"^[\+\-]?\d+",str.strip())  
        print(res)  
        if res !=[]:  
            if int(res[0]) > (2**31-1):  
                return (2**31-1)  
            if int(res[0]) < (-2**31):  
                return (-2**31)  
            return int(res[0])  
        else:  
            return 0 

9回文数

解题思路:这道题有两种解法。1、常规的解法就是将输入的整形数转换为字符串,再将字符串进行反转,之后与原数进行判断。2、第二种方法是采用数学的方法。方法为逐次整除,将余数提取出来带入,重新组建数字,不断乘以10去加上新算出的余数,如果是回文数字,那么新组建的数字就和输入的一样。

注意:python中" / "就表示 浮点数除法,返回浮点结果;" // "表示整数除法

方法一代码如下

class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        x = str(x)
        x1 = x[::-1]
        if x == x1 :
            return True
        else:
            return False

方法二代码

class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        if x > 0:
            n,newed = 0,0
            n = x
            while x > 0:
                newed = newed *10 + x % 10
                x = x//10
            if newed == n:
                return True
            else:
                return False
        elif x == 0:
            return True
        elif x < 0:
            return False

看了第一名的代码不得不佩服是大佬,请欣赏大佬的表演

class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        if x < 0:
            return False
        else:
            return int(str(x)[::-1]) == x

13、罗马数字转整数

解题思路:首先要读懂题目,对于罗马这7个字符要熟悉,应该要想到使用字典去构建这个罗马数字转字符的储存,接着去读懂罗马数字规则,前面这个数字比后面数字大就正常加上这个数字本身值,如果小的话就用后面这个数字减去前面这个数字的值。初步的想法就是去遍历每一个字符,与其后面的字符比较,将结果加入总和中,最后存在一个问题,最后一个数字没有办法加上,在返回值中加入最后一个数字在比如IV这样的案例中会重复计算。所以转换一下想法,在总和的基础上只添加当前这个数字,比后面大的话为+号,比后面小的话为-号。

我的代码如下:

class Solution:
    def romanToInt(self, s):
        """
        :type s: str
        :rtype: int
        """
        sum = 0
        convert = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}
        for i in range(len(s)-1):
            if convert[s[i]] >=  convert[s[i+1]]:
                sum = sum + convert[s[i]] 
                
            else:
                sum = sum - convert[s[i]]
               
        return sum+convert[s[-1]]

这种方法耗时太长,将sum = sum - convert[s[i]]写为sum -= convert[s[i]]会节约一些时间,我看用时比较快的人写法是将可能出现的情况都列入字典中,减少了计算的过程,然后从输入的字符中从前往后遍历。遍历的过程中分为两种情况,一种两个字符,一种一个字符,然后在字典中寻找相应的值相加。代码如下

class Solution:
    def romanToInt(self, s):
        """
        :type s: str
        :rtype: int
        """
        convert = {"I":1,"IV":4,"V":5,"IX":9,"X":10,"XL":40,"L":50,"XC":90,"C":100,"CD":400,"D":500,"CM":900,"M":1000}
        len_n = len(s)
        n = 0
        i = 0
        while(i < len_n):
            key = s[i:i+2]
            if key in convert:
                n+=convert[key]
                i+=2
                continue
            key = s[i]
            if key in convert:
                n+=convert[key]
                i+=1
        return n

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值