Python实现 Leecodet

https://blog.csdn.net/qq_42364307/article/details/119257678

打算把LeetCode上面的题都实现一遍,每日两题
LeetCode目录
1. 两数之和
2. 两数相加
11. 盛最多水的容器
15.三数之和
33.搜索旋转排序数组
34. 在排序数组中查找元素的第一个和最后一个位置
35.搜索插入位置
53.最大子数组和
64. 最小路径和
70.爬楼梯
74.搜索二维矩阵
82. 删除排序链表中的重复元素 II
88. 合并两个有序数组
153. 寻找旋转排序数组中的最小值
162. 寻找峰值
167. 两数之和 II - 输入有序数组
189.轮转数组
217.存在重复元素
278.第一个错误的版本
283. 移动零
344. 反转字符串
557. 反转字符串中的单词 III
704. 二分查找
844. 比较含退格的字符串
977. 有序数组的平方
986. 区间列表的交集
剑指 Offer 05. 替换空格
剑指 Offer 06. 从尾到头打印链表
剑指 Offer 09.用两个栈实现队列
剑指 Offer 24. 反转链表
剑指 Offer 30.包含min函数的栈
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
1
2
3
4
5
6
7
思路
使用双指针 注意!我们每次只要移动高度小的一边,因为移动小的那一边可能会增大,但是移动大的一边一定会减小
代码

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
1
2
3
4
5
6
7
8
9
10
11
12
13
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]
输出:[]
1
2
3
4
5
6
7
8
9
思路
可以使用双指针,先排序(时间复杂度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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
1
2
3
4
5
6
7
8
9
思路
二分查找题,先用二分查找找到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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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]
1
2
3
4
5
6
7
8
9
思路
两分查找,先找开始的位置,在找结束的位置。
代码

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
思路

代码

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
1
2
3
4
5
6
7
8
9
10
11
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
1
2
3
4
5
6
7
8
9
10
思路
可以使用动态规划的方法,如下代码,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
1
2
3
4
5
6
7
8
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]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
70.爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。

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

示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1 阶 + 1 阶 + 1 阶
2.  1 阶 + 2 阶
3.  2 阶 + 1 阶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
思路

代码

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])
1
2
3
4
5
6
7
8
9
10
11
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
思路
我们巧用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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 次得到输入数组。
1
2
3
4
5
6
7
8
9
10
11
12
思路
查找旋转次数就好了
代码

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]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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]
输出:1 或 5 
解释:你的函数可以返回索引 1,其峰值元素为 2;
     或者返回索引 5, 其峰值元素为 6。
1
2
3
4
5
6
7
8
9
思路
二分法,只需要判断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
1
2
3
4
5
6
7
8
9
10
11
12
167. 两数之和 II - 输入有序数组
给定一个已按照 非递减顺序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

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

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

示例 3:
输入:numbers = [-1,0], target = -1
输出:[1,2]
1
2
3
4
5
6
7
8
9
10
11
12
思路

代码

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]
1
2
3
4
5
6
7
8
9
10
11
12
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]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
思路

代码

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)]
1
2
3
4
5
6
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

1
2
3
4
5
6
7
8
9
10
思路
利用集合的唯一性来做。(暴力穷举算法复杂度太大了O ( n 2 ) O(n^2)O(n 
2
 ))
代码

class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        numsset = set(nums)
        if(len(nums) == len(numsset)):
            return False
        else:
            return True
1
2
3
4
5
6
7
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
1
2
3
4
5
6
7
8
9
10
11
12
思路

代码

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
283. 移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

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

代码

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        nums.sort(key=bool, reverse=True)
1
2
3
4
5
6
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"]
1
2
3
4
5
6
7
思路

代码

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
1
2
3
4
5
6
7
8
9
10
11
12
13
一行实现

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        s.reverse()
1
2
3
4
5
6
557. 反转字符串中的单词 III
给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例:
输入:"Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"
1
2
3
思路

代码
一行代码

class Solution:
    def reverseWords(self, s: str) -> str:
        return ' '.join([w[::-1] for w in s.split()])
1
2
3
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
1
2
3
4
5
6
7
8
9
思路

代码

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
1
2
3
4
5
6
7
8
9
10
11
12
13
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"。
1
2
3
4
5
6
7
8
9
10
11
12
思路
如果暴力的话肯定不行的,要占用新的内存,且要比较。我们可以使用双指针,从后往前读,比较每一个字符。有不符号返回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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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) 的算法解决本问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
思路

代码

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        B = sorted([num*num for num in nums])
        return B
1
2
3
4
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]]
1
2
3
4
5
6
7
8
9
10
11
12
思路
使用双指针,一个指向其中一个数组,对每一个内部数组进行比较。
代码

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
剑指 Offer 05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

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

代码

class Solution:
    def replaceSpace(self, s: str) -> str:
       return s.replace(" ","%20")
1
2
3
剑指 Offer 06. 从尾到头打印链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

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

代码

# 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]
1
2
3
4
5
6
7
8
9
10
11
12
13
剑指 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
剑指 Offer 24. 反转链表
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

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

代码

# 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
剑指 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()
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值