leetcode刷题笔记Day5

leetcode刷题笔记Day5

结果我就不继续放了,因为我发现,这个结果每次运行都不一样,没有参考价值

1、合并两个有序数组

题目描述:

给你两个按 非递减顺序 排列的整数数组 nums1nums2,另有两个整数 mn ,分别表示 nums1nums2 中的元素数目。

请你 合并 nums2nums1 中,使合并后的数组同样按 非递减顺序 排列。

**注意:**最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n

示例:

输入: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 中的元素。

解法一:直接法

思路:

1、先将nums2直接加入到nums1中,则nums1[m:m+n] = nums2[0:n];

2、在nums1中排序(类似插入排序):

  • i in range(n)
  • 将nums1[m+i]即nums2[i]与其前面元素比较,若前面元素比当前元素大,则将前面元素到当前元素之间的元素全部后移(因为nums1前面已经是非递减序列),当前元素前移,i 指针后移;
  • 但是当nums2中前面的元素在nums1中找到自己的位置之后,由于nums2也是非递减序列,所以,nums1[m+i]即nums2[i]比较范围不应该是其前面所有元素,而是上一个确定好的位置(nums2[i-1]的位置)到nums1[m+i];
  • 我们可以另外设置一个指针t,指向nums2元素真正插入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.
        """
        # 如果nums2为空,则nums1其实不用做改变
        if nums2:# 如果nums2非空
            for i in range(n):# 先直接将nums2加入到nums1中
                nums1[m+i] = nums2[i]
            t = 0# 指向nums2中元素实际在nums1中的位置
            for i in range(n):
                for j in range(t, m+i):# 比较范围是上一个nums2元素到当前比较元素之间
                    if nums1[j]>nums2[i]:# 前面元素比当前元素大,则后移
                        for t in range(m+i,j,-1):# 将前面元素之后的元素全部后移
                            nums1[t] = nums1[t-1]
                        nums1[j] = nums2[i]# 将当前元素插入合适位置
                        t=j+1# 更新t指针
                        break

解法二、sort函数

思路:

1、先将nums2直接加入到nums1中,则nums1[m:m+n] = nums2[0:n];

2、python的列表中有内置的排序函数sort,快排,直接利用排序函数即可

代码:

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.
        """
        if nums2:
            nums1[m:] = nums2
            nums1.sort()

解法三、双指针(从前往后)

思路:

1、创建新数组,对比nums1和nums2数组,将小的移入新数组中

代码:

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.
        """
        if nums2:
            nums = []
            p1 = 0
            p2 = 0
            while p1<m or p2<n:
                if p2 == n:# nums2已经全部插入新数组,那么直接将nums1剩余数字加入nums即可
                    nums.append(nums1[p1])
                    p1 += 1
                elif p1 == m:# nums1已经全部插入新数组,那么直接将nums2剩余数字加入nums即可
                    nums.append(nums2[p2])
                    p2 += 1
                elif nums1[p1] > nums2[p2]:
                    nums.append(nums2[p2])
                    p2 += 1
                else:
                    nums.append(nums1[p1])
                    p1 += 1
            nums1[:] = nums

注意:

nums1=nums

运行时,报错,nums1并没有改变,所以在列表赋值时,尽量不要直接使用=。

解法四、双指针(从后向前)

思路:

1、解法三创建了额外的列表,占用了额外的空间;

2、如果直接在buns1中从前往后遍历,就会覆盖掉一些元素,因此我们可以从后向前遍历,选择较大的插入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.
        """
        if nums2:
            p1 = m-1
            p2 = n-1
            p = m+n-1
            while p1 >= 0 or p2 >= 0:
                if p1 < 0:# nums1已经全部插完,将nums2剩余插入nums1即可
                    nums1[p] = nums2[p2]
                    p2 -= 1
                    p -= 1
                elif p2 < 0:# nums2已经全部插完,将nums1剩余插入nums1即可
                    nums1[p] = nums1[p1]
                    p1 -= 1
                    p -= 1
                elif nums1[p1] >= nums2[p2]:
                    nums1[p] = nums1[p1]
                    p1 -= 1
                    p -= 1
                else:
                    nums1[p] = nums2[p2]
                    p2 -= 1
                    p -= 1

相关知识介绍

列表内建函数
方法描述
append()在列表的末尾添加一个元素
clear()删除列表中的所有元素
copy()返回列表的副本
count()返回具有指定值的元素数量。
extend()将列表元素(或任何可迭代的元素)添加到当前列表的末尾
index()返回具有指定值的第一个元素的索引
insert()在指定位置添加元素
pop()删除指定位置的元素
remove()删除具有指定值的项目
reverse()颠倒列表的顺序
sort()对列表进行排序

2、将有序数组转换为二叉搜索树

题目描述:

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

示例:

输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:

解法一、直接法

思路:

1、数组nums是升序数组,转化为平衡二叉搜索树,而二叉查找树中序遍历就是升序;

2、题目就相当于将中序遍历逆转换为二叉树,将一个元素作为根节点,该节点左侧为左子树,右侧为右子树;

3、考虑平衡二叉树,就需要左右子树高度最多差一,直观上看,就是选择数组中间的数字作为根节点,采用递归的思想,构造二叉树。

代码:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        def create(left,right):
            if left>right:
                return None
            mid = (left + right)//2
            root = TreeNode(nums[mid])
            root.left = create(left,mid-1)
            root.right = create(mid+1,right)
            return root

        return create(0, len(nums) - 1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值