LeetCode详解python版

打算把LeetCode上面的题都实现一遍,每日两题

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案

示例
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

输入:nums = [3,2,4], target = 6
输出:[1,2]

输入:nums = [3,3], target = 6
输出:[0,1]

思路
巧用字典结构

代码

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        dist={}
        for d,ind in enumerate(nums):
            dist[ind] = d
        for i, j in enumerate(nums):
            f = dist.get(target - j)
            if f is not None and f != i:
                return [i, f]

2. 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
在这里插入图片描述
思路

代码

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        re = ListNode(0)
        r=re
        carry=0
        while(l1 or l2):
            x= l1.val if l1 else 0
            y= l2.val if l2 else 0
            s=carry+x+y
            carry=s//10
            r.next=ListNode(s%10)
            r=r.next
            if(l1!=None):l1=l1.next
            if(l2!=None):l2=l2.next
        if(carry>0):
            r.next=ListNode(1)
        return re.next

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。

示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1]
输出:1

思路
使用双指针 注意!我们每次只要移动高度小的一边,因为移动小的那一边可能会增大,但是移动大的一边一定会减小
代码

class Solution:
    def maxArea(self, height: List[int]) -> int:
        i = 0
        j = len(height) - 1
        res = 0
        while(i < j):
            if(height[i] < height[j]):
                res = max(res,height[i]*(j-i))
                i += 1
            else:
                res = max(res,height[j]*(j-i))
                j -= 1
        return res

15.三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。

示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]

思路
可以使用双指针,先排序(时间复杂度nlogn),然后令L = i+1 ,R = n - 1,我们遍历i,如果值大了我们就R–,小了就L++
代码

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
       
        n=len(nums)
        res=[]
        if(not nums or n<3):
            return []
        nums.sort()
        res=[]
        for i in range(n):
            if(nums[i]>0):
                return res
            if(i>0 and nums[i]==nums[i-1]):
                continue
            L=i+1
            R=n-1
            while(L<R):
                if(nums[i]+nums[L]+nums[R]==0):
                    res.append([nums[i],nums[L],nums[R]])
                    while(L<R and nums[L]==nums[L+1]):
                        L=L+1
                    while(L<R and nums[R]==nums[R-1]):
                        R=R-1
                    L=L+1
                    R=R-1
                elif(nums[i]+nums[L]+nums[R]>0):
                    R=R-1
                else:
                    L=L+1
        return res

33.搜索旋转排序数组

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1
示例 3:
输入:nums = [1], target = 0
输出:-1

思路
二分查找题,先用二分查找找到k,然后找到目标值
代码

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if(len(nums) == 0):
            return -1
        n = len(nums)
        r = n-1
        l = 0
        # find k
        while(l<r):
            m = int(l + (r -l)/2)
            if(nums[m] < nums[r]):
                r = m
            else:
                l = m+1
        k = l
        l = 0
        r = k-1
        while(l<r):
            m = int(l + (r -l)/2)
            if(nums[m] >= target):
                r = m
            else:
                l = m+1
        if(nums[l]==target):
            return l
        l = k
        r = n -1
        while(l<r):
            m = int(l + (r -l)/2)
            if(nums[m] >= target):
                r = m
            else:
                l = m+1
        if(nums[l]==target):
            return l
        else:
            return -1

34. 在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:
你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0
输出:[-1,-1]

思路
两分查找,先找开始的位置,在找结束的位置。
代码

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        res = [-1,-1]
        if(len(nums) == 0):
            return res
        n = len(nums)
        l = 0
        r = n-1
        while(l < r):
            m = int(l + (r - l)/2)
            if(nums[m] >= target):
                r = m
            else:
                l = m+1
        if(nums[l] != target):
            return res
        res[0] = l
        r = n
        while(l < r):
            m = int(l + (r - l)/2)
            if(nums[m] <= target):
                l = m+1
            else:
                r = m
        res[1] = l-1
        return res

35.搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。

示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4

示例 4:
输入: nums = [1,3,5,6], target = 0
输出: 0

示例 5:
输入: nums = [1], target = 0
输出: 0

思路

代码

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        left = 0
        right = len(nums) - 1
        while(left <= right):
            mid = int(left + (right - left )/ 2)
            if nums[mid] < target:
                left = mid + 1
            else:
                right = mid - 1
        return left

53.最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。

示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
示例 3:
输入:nums = [5,4,-1,7,8]
输出:23

思路
可以使用动态规划的方法,如下代码,f_n表示前n个之和最大值
代码

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        res = -10000
        f_n = -1
        for i in range(len(nums)):
            f_n = max(nums[i],f_n + nums[i])
            res = max(f_n,res)
        return res

64. 最小路径和

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
在这里插入图片描述
思路

代码

class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])
        if(m<=0 or n<=0):
            return 0
        dp = []
        for i in range(m):
            dp.append([])
            for j in range(n):
                dp[i].append(0)
        dp[0][0] = grid[0][0]
        for i in range(1,m):
            dp[i][0] = grid[i][0] + dp[i-1][0]
        for i in range(1,n):
            dp[0][i] = grid[0][i] + dp[0][i-1]
        for i in range(1,m):
            for j in range(1,n):
                dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + grid[i][j]
        return dp[m-1][n-1]

70.爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。

示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1+ 12.  2 阶

示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1+ 1+ 12.  1+ 23.  2+ 1

思路

代码

class Solution:
    def climbStairs(self, n: int) -> int:
        A = []
        if(n<=2):
            return n
        A.append(0)
        A.append(1)
        A.append(2)
        for i in range(3,n+1):
            A.append(A[i-1] + A[i-2])
        return int(A[i])

74.搜索二维矩阵

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
在这里插入图片描述
思路
将二维排序成一维来做,继续用二分查找
代码

class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        n = len(matrix)
        m = len(matrix[0])
        l = 0
        r = n*m-1
        while(l<r):
            mid = int(l + (r - l)/2)
            mid1 = mid/m
            mid2 = mid%m
            if(matrix[mid1][mid2] >= target):
                r = mid
            else:
                l = mid + 1
        ma1 = l/m
        ma2 = l%m
        if(matrix[ma1][ma2] == target):
            return True
        else:
            return False

82. 删除排序链表中的重复元素 II

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
在这里插入图片描述
思路
很容易的题,主要是第一个值的话怎么删,我们可以新建一个next 为列表的头head
代码

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if(not head):
            return head
        tem = ListNode(0,head)
        cur = tem
        while(cur.next and cur.next.next):
            if(cur.next.val == cur.next.next.val):
                x = cur.next.val
                while(cur.next and cur.next.val == x):
                    cur.next = cur.next.next
            else:
                cur = cur.next
        
        return tem.next

88. 合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3][2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1][] 。
合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [][1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

思路
我们巧用nums1的结构,把从大到小排序放进去
代码

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        p1, p2 = m - 1, n - 1
        tail = len(nums1) - 1
        while p2 >= 0:
            if p1 < 0 or nums1[p1] <= nums2[p2]:
                nums1[tail] = nums2[p2]
                p2 -= 1
                tail -= 1
            else:
                nums1[tail] = nums1[p1]
                p1 -= 1
                tail -= 1

153. 寻找旋转排序数组中的最小值

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

示例 1:
输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
示例 2:
输入:nums = [4,5,6,7,0,1,2]
输出:0
解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。
示例 3:
输入:nums = [11,13,15,17]
输出:11
解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。

思路
查找旋转次数就好了
代码

class Solution:
    def findMin(self, nums: List[int]) -> int:
        if(len(nums) == 0):
            return -1
        n = len(nums)
        r = n-1
        l = 0
        # find k
        while(l<r):
            m = int(l + (r -l)/2)
            if(nums[m] < nums[r]):
                r = m
            else:
                l = m+1
        return nums[l]

162. 寻找峰值

峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞ 。
你必须实现时间复杂度为 O(log n) 的算法来解决此问题。

示例 1:
输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入:nums = [1,2,1,3,5,6,4]
输出:15 
解释:你的函数可以返回索引 1,其峰值元素为 2;
     或者返回索引 5, 其峰值元素为 6

思路
二分法,只需要判断nums[m] > nums[m+1],因为大的值一定有解
代码

class Solution:
    def findPeakElement(self, nums: List[int]) -> int:
        n = len(nums)
        l = 0
        r = n - 1
        while(l < r):
            mid = int(l + (r - l)/2)
            if(nums[mid] > nums[mid + 1]):
                r = mid
            else:
                l = mid + 1
        return l

167. 两数之和 II - 输入有序数组

给定一个已按照 非递减顺序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

示例 1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:27 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

示例 2:
输入:numbers = [2,3,4], target = 6
输出:[1,3]

示例 3:
输入:numbers = [-1,0], target = -1
输出:[1,2]

思路

代码

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        l = 0
        r = len(numbers)-1
        while(l<r):
            if(numbers[l]+numbers[r]>target):
                r= r - 1
            elif(numbers[l]+numbers[r]<target):
                l= l + 1
            else:
                return [l+1,r+1]
        return [l+1,r+1]

189.轮转数组

给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1: [7,1,2,3,4,5,6]
向右轮转 2: [6,7,1,2,3,4,5]
向右轮转 3: [5,6,7,1,2,3,4]

示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1: [99,-1,-100,3]
向右轮转 2: [3,99,-1,-100]

思路

代码

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        nums[: ] = nums[-k % len(nums) :] + nums[: -k % len(nums)]

217.存在重复元素

给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

示例 1:
输入:nums = [1,2,3,1]
输出:true
示例 2:
输入:nums = [1,2,3,4]
输出:false
示例 3:
输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true

思路
利用集合的唯一性来做。(暴力穷举算法复杂度太大了 O ( n 2 ) O(n^2) O(n2)
代码

class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        numsset = set(nums)
        if(len(nums) == len(numsset)):
            return False
        else:
            return True

278.第一个错误的版本

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

示例 1:
输入:n = 5, bad = 4
输出:4
解释:
调用 isBadVersion(3) -> false 
调用 isBadVersion(5) -> true 
调用 isBadVersion(4) -> true
所以,4 是第一个错误的版本。

示例 2:
输入:n = 1, bad = 1
输出:1

思路

代码

class Solution:
    def firstBadVersion(self, n):
        """
        :type n: int
        :rtype: int
        """
        left = 1
        right = n
        while(left<right):
            mid = int(left + (right - left)/2)
            if(isBadVersion(mid)):
                right = mid
            else:
                left = mid + 1
        return left

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

思路

代码

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        nums.sort(key=bool, reverse=True)

344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

示例 1:
输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]

示例 2:
输入:s = ["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]

思路

代码

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        r = len(s)
        l = r
        for i in range(int(r/2)):
            l = l - 1
            tmp = s[i]
            s[i] = s[l]
            s[l] = tmp
        return s

一行实现

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        s.reverse()

557. 反转字符串中的单词 III

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例:
输入:"Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"

思路

代码
一行代码

class Solution:
    def reverseWords(self, s: str) -> str:
        return ' '.join([w[::-1] for w in s.split()])

704. 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

思路

代码

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        right = len(nums)-1
        left = 0
        while(left <= right):
            mid = int(left + (right - left)/2)
            if(target < nums[mid]):
                right = mid - 1
            elif(target > nums[mid]):
                left = mid + 1
            else:
                return mid
        return -1

844. 比较含退格的字符串

给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。

示例 1:
输入:s = "ab#c", t = "ad#c"
输出:true
解释:s 和 t 都会变成 "ac"。
示例 2:
输入:s = "ab##", t = "c#d#"
输出:true
解释:s 和 t 都会变成 ""。
示例 3:
输入:s = "a#c", t = "b"
输出:false
解释:s 会变成 "c",但 t 仍然是 "b"

思路
如果暴力的话肯定不行的,要占用新的内存,且要比较。我们可以使用双指针,从后往前读,比较每一个字符。有不符号返回flase
代码

class Solution:
    def backspaceCompare(self, s: str, t: str) -> bool:
        i = len(s) - 1
        j = len(t) - 1
        skipi = 0
        skipj = 0
        while(i >= 0 or j >= 0):
            while(i >= 0):
                if(s[i] == '#'):
                    skipi += 1
                    i -= 1
                elif(skipi > 0):
                    skipi -= 1
                    i -= 1
                else:
                    break
            while(j >= 0):
                if(t[j] == '#'):
                    skipj += 1
                    j -= 1
                elif(skipj > 0):
                    skipj -= 1
                    j -= 1
                else:
                    break
            if(i >= 0 and j >= 0):
                if(s[i] != t[j]):
                    return False
            elif(i >= 0 or j >= 0):
                return False
            i -= 1
            j -= 1
        return True

977. 有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回每个数字的平方 组成的新数组,要求也按非递减顺序排序。

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 已按 非递减顺序 排序

进阶:
请你设计时间复杂度为 O(n) 的算法解决本问题

思路

代码

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        B = sorted([num*num for num in nums])
        return B

986. 区间列表的交集

给定两个由一些 闭区间 组成的列表,firstList 和 secondList ,其中 firstList[i] = [starti, endi] 而 secondList[j] = [startj, endj] 。每个区间列表都是成对 不相交 的,并且 已经排序 。
返回这 两个区间列表的交集 。
形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b 。
两个闭区间的 交集 是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3] 。

示例 1:
输入:firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]]
输出:[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]
示例 2:
输入:firstList = [[1,3],[5,9]], secondList = []
输出:[]
示例 3:
输入:firstList = [], secondList = [[4,8],[10,12]]
输出:[]
示例 4:
输入:firstList = [[1,7]], secondList = [[3,10]]
输出:[[3,7]]

思路
使用双指针,一个指向其中一个数组,对每一个内部数组进行比较。
代码

class Solution:
    def intervalIntersection(self, firstList: List[List[int]], secondList: List[List[int]]) -> List[List[int]]:
        res = []
        i = 0
        j = 0
        while(i < len(firstList) and j<len(secondList)):
            start = max(firstList[i][0],secondList[j][0])
            end = min(firstList[i][1],secondList[j][1])
            if(start <= end):
                res.append([start,end])
            if(firstList[i][1]<secondList[j][1]):
                i += 1
            else:
                j += 1
        return res

剑指 Offer 05. 替换空格

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

示例 1:
输入:s = "We are happy."
输出:"We%20are%20happy."

思路

代码

class Solution:
    def replaceSpace(self, s: str) -> str:
       return s.replace(" ","%20")

剑指 Offer 06. 从尾到头打印链表

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

示例 1:
输入:head = [1,3,2]
输出:[2,3,1]

思路

代码

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

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        A = []
        while(head):
            A.append(head.val)
            head = head.next
        return A[::-1]

剑指 Offer 09.用两个栈实现队列

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
思路

代码

class CQueue:

    def __init__(self):
        self.s1 = []
        self.s2 = []
    def appendTail(self, value: int) -> None:
        self.s1.append(value)

    def deleteHead(self) -> int:
        if(len(self.s1)==0 and len(self.s2) == 0):
            return -1
        if(len(self.s1)!=0 and len(self.s2) == 0):
            while(len(self.s1)!=0):
                self.s2.append(self.s1.pop())
            return self.s2.pop()
        if(len(self.s2) != 0):
            return self.s2.pop()
        return -1

剑指 Offer 24. 反转链表

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

思路

代码

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

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        preNode = None
        currNode = head
        while(currNode):
            nextNode = currNode.next
            currNode.next = preNode
            preNode = currNode
            currNode = nextNode
        return preNode

剑指 Offer 30.包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
思路

代码

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.MS = []
        self.Min = inf
    def push(self, x: int) -> None:
        self.MS.append(self.Min)
        if(x<self.Min):
            self.Min = x
        self.MS.append(x)

    def pop(self) -> None:
        self.MS.pop(-1)
        self.Min = self.MS.pop(-1)
        

    def top(self) -> int:
        return self.MS[-1]

    def min(self) -> int:
        return self.Min


# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.min()
  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值