编程小白用Python刷LeetCode学习笔记——前100题

编程小白用Python刷LeetCode学习笔记

编程小白刚学完Python的基本语法,开始试着用Python刷LeetCode,连最简单的题目都是看答案的,很心酸,不过不管能不能提高编程能力,至少可以学点算法知识吧,希望能坚持。记录一下答案。

1.两数之和
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解:

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        d = {}
        for i, n in enumerate(nums):
            m = target - n
            if m in d:
                return [d[m], i]
            else:
                d[n] = i

7.反转整数
给定一个 32 位有符号整数,将整数中的数字进行反转。

示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21

注意:
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。根据这个假设,如果反转后的整数溢出,则返回 0。

解:

class Solution:
    def reverse(self, x):
        """
        :type x: int
        :rtype: int
        """
        tmp=abs(x)
        sum=0
        while tmp>0:
            sum=sum*10+tmp%10
            tmp=tmp//10
        if x<0:
            sum=-sum
        if sum<2**31 and sum>-2**31:
            return sum
        else:
            return 0
            

9.回文数
这道题自己尝试写了一下,把数字转换成字符串放在列表里再比较反转前后两个列表是否相同,提交后速度确实不快,只击败33%左右的答案,看了下别人写的最优解,速度一下子就提高了很多。非常弱了,但是至少自己尝试着写出一个解了,菜鸟暗自开心一下下,虽然题目真的超简单,其实本科学C的时候就写过了,然而并没有记住。
自己写的解:

class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        strs=list(str(x))
        tmp=[]
        for value in strs:
            tmp.insert(0,value)
        return strs==tmp

偷偷看的最优解:

class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        if x<0:
            return False
        high=1
        while x/high>=10:
            high*=10
        while x//high==x%10:
            x=x%high//10
            high=high/100
            if high<1:
                return True
        return False
        

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

13.罗马数字转整数

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

示例 1:

输入: “III”
输出: 3

示例 2:

输入: “IV”
输出: 4

示例 3:

输入: “IX”
输出: 9

示例 4:

输入: “LVIII”
输出: 58
解释: L = 50, V= 5, III = 3.

示例 5:

输入: “MCMXCIV”
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
解法一:

class Solution:
    def romanToInt(self, s):
        """
        :type s: str
        :rtype: int
        """
        rom_map={'I':1,
            'V':5,
            'X':10,
            'L':50,
            'C':100,
            'D':500,
            'M':1000}
        last_num=None
        result=0
        for char in s:
            curent_num=rom_map[char]
            if last_num is None or last_num>=curent_num:
                result+=curent_num
            elif last_num<curent_num:
                result+=curent_num-2*last_num
            last_num=curent_num
        return result

解法二:

class Solution(object):
    def romanToInt(self, s):
        """
        :type s: str
        :rtype: int
        """
        sum=0
        convert={'M': 1000,'D': 500 ,'C': 100,'L': 50,'X': 10,'V': 5,'I': 1} 
        for i in range(len(s)-1):
            #if (s[i]=='I' or s[i]=='X' or s[i]=='C') and convert[s[i]]<convert[s[i+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]]

14.最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。

示例 1:

输入: [“flower”,“flow”,“flight”]
输出: “fl”

示例 2:

输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。

说明:

所有输入只包含小写字母 a-z 。

解:

class Solution(object):
    def longestCommonPrefix(self, strs):
        """
        :type strs: List[str]
        :rtype: str
        """

        if not strs: 
            return ''
        s1 = min(strs)
        s2 = max(strs)
        for i,c in enumerate(s1):
            if c != s2[i]:
                    return s1[:i]
        return s1


20.有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

注意空字符串可被认为是有效字符串。

示例 1:

输入: “()”
输出: true

示例 2:

输入: “()[]{}”
输出: true

示例 3:

输入: “(]”
输出: false

示例 4:

输入: “([)]”
输出: false

示例 5:

输入: “{[]}”
输出: true

解:

class Solution:
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        top_element=''
        stack=[]
        mapping={')':'(',']':'[','}':'{'}
        for char in s:
            if char in mapping:
                if stack:
                    top_element=stack.pop()
                else:
                    '#'
                if mapping[char]!=top_element:
                    return False
            else:
                stack.append(char)
        return not stack
        

21.合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

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

class Solution:
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        if l1==None:
            return l2
        if l2==None:
            return l1
        if l1.val<=l2.val:
            ret=l1
            ret.next = self.mergeTwoLists(l1.next, l2)
        else:
            ret=l2
            ret.next = self.mergeTwoLists(l1, l2.next)
        return ret
            

26.删除排序数组中的重复项
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定数组 nums = [1,1,2],

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。

你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}

解:

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        pos=0
        this_num=None
        for num in nums:
            if num!=this_num:
                nums[pos]=num
                this_num=num
                pos+=1
        return pos

35.搜索插入位置
我自己写的穷举法:

class Solution:
    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if nums[0]>target:
            return 0
        if nums[-1]<target:
            return len(nums)
        for i in range(len(nums)):
            if nums[i]==target:
                return i
            elif nums[i]<target and nums[i+1]>target:
                return i+1

一般遇到有序数组都应该想到用二分法,下面是一个用二分法的递归函数:

class Solution:
    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        def bs(numlsit, l, r):
            while l <= r:
                mid = int((l + r) / 2)
                if numlsit[mid] == target:
                    return mid
                elif numlsit[mid] < target:
                    return bs(numlsit, mid+1, r)
                else:
                    return bs(numlsit, l, mid-1)
            return l
        
        return bs(nums, 0, len(nums)-1)

53.最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

解:

class Solution:
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        sums=0
        maxsum=nums[0]
        for value in nums:
            sums=sums+value
            if maxsum<sums:
                maxsum=sums
            if sums<0:
                sums=0
        return maxsum

解法二:

class Solution:
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        length=len(nums)
        for i in range(1,length):
            #当前值的大小与前面的值之和比较,若当前值更大,则取当前值,舍弃前面的值之和
            subMaxSum=max(nums[i]+nums[i-1],nums[i])
            nums[i]=subMaxSum#将当前和最大的赋给nums[i],新的nums存储的为和值
        return max(nums)

58.最后一个单词长度
给定一个仅包含大小写字母和空格 ’ ’ 的字符串,返回其最后一个单词的长度。

如果不存在最后一个单词,请返回 0 。

说明:一个单词是指由字母组成,但不包含任何空格的字符串。
解:

class Solution:
    def lengthOfLastWord(self, s):
        """
        :type s: str
        :rtype: int
        """
        str = ''
        count = 0
        for i in s[::-1]:
            if str != '' and i==' ':
                return count
            if i != ' ':
                count = count+ 1
                str = str + i
        return count

66.加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。
示例 2:

输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。
我自己写的解法:先把列表还原成数然后加一再换回列表

class Solution:
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        num=0
        for value in digits:
            num=num*10+value
        num=num+1
        new_list=[None]*len(str(num))
        i=len(str(num))-1
        while num>0:
            new_list[i]=num%10
            num=num//10
            i-=1
        return new_list

别人的直接解法:

class Solution(object):
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        carry = 1
        for i in reversed(range(0, len(digits))):
            digit = (digits[i] + carry) % 10
            carry = 1 if digit < digits[i] else 0
            digits[i] = digit
        if carry == 1:
            return [1] + digits
        return digits

69.x的平方根

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 1:

输入: 4
输出: 2
示例 2:

输入: 8
输出: 2
说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去。
解法一:
我的想法是用牛顿迭代法求:

class Solution:
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        y=1
        lasty=2
        while y-lasty>=1 or lasty-y>=1:
            lasty=y
            y=(lasty+x/lasty)/2
        return int(y)
            

解法二:二分法

class Solution:
    def mySqrt(self, x):
        left=0;right=x
        while left<right:
            mid=int((left+right)/2)
            if x<mid**2:
                right=mid
            else:
                left=mid+1
        if left>1:
            return left-1
        else:
            return left

70.爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶
    示例 2:

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
3. 1 阶 + 1 阶 + 1 阶
4. 1 阶 + 2 阶
5. 2 阶 + 1 阶
**注意:**此时相当于求斐波那契数列的第n个数

class Solution(object):
    def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n<=2:
            return n
        a=[0]*(n+1)
        a[1]=1
        a[2]=2
        for i in range(3,n+1):
            a[i]=a[i-1]+a[i-2]
        return a[n]

88.合并两个有序数组
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。

说明:

初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3

输出: [1,2,2,3,5,6]
我的解法:

class Solution:
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: void Do not return anything, modify nums1 in-place instead.
        """
        num=nums1[:m]+nums2
        for i in range(m+n):
            value=min(num)
            nums1[i]=value
            num.remove(value)

别人的解法,我真是想不到。。。

class Solution:
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: void Do not return anything, modify nums1 in-place instead.
        """
        while m>0 and n>0:
            if nums1[m-1]>=nums2[n-1]:
                nums1[m+n-1]=nums1[m-1]
                m-=1
            else:
                nums1[m+n-1]=nums2[n-1]
                n-=1
        if n>0:
            nums1[:n]=nums2[:n]

猜你喜欢

转载自blog.csdn.net/weixin_40848065/article/details/82955406