leetcode刷题笔记Day5
结果我就不继续放了,因为我发现,这个结果每次运行都不一样,没有参考价值
文章目录
1、合并两个有序数组
题目描述:
给你两个按 非递减顺序 排列的整数数组
nums1
和nums2
,另有两个整数m
和n
,分别表示nums1
和nums2
中的元素数目。请你 合并
nums2
到nums1
中,使合并后的数组同样按 非递减顺序 排列。**注意:**最终,合并后数组不应由函数返回,而是存储在数组
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)