LeetCode:数组(三)

本组囊括数组相关题目,难度不等:

66.Plus One

题目描述:简单

这道题的思路就是数组末位加一:由于数字是十进制,于是这里考虑的就是逢十进一的情况:(1)末位为9,如149

(2)除了首位外其他多位为9,如199

(1)全为9,如999

解法一:

这里可以看到都是从末位开始判断,于是可以想到逆序遍历数组,如果为9则变为0,直到遇到第一个不为9的数字则加一并返回;再考虑特殊情况,遍历完数组如果都是9,则都变为0后数组最前位置插入一个1即可:

 1 class Solution:
 2     def plusOne(self, digits: List[int]) -> List[int]:
 3         ans = len(digits) -1
 4         # 数组中每个元素只存储单个数字很重要!
 5         # 主要考虑进位的情况,如99,999,149等
 6         # 解法(一):逆序遍历原数组,从数组尾部遍历
 7         # 如果遇到数字不是9就+1,并返回
 8         # 如果是9,则将当前数字置0,并进入下一轮循环
 9         # 循环结束后
10         # 考虑特殊情况:999之类的全为9的数字
11         # 此时需要检查for循环后是否首位数也为0
12         # 即digits[0]是否为0,如果是0,则遇到了特殊情况
13         # 此时需要在数组最前面插入一个1,然后返回即可
14 
15         for i in range(ans, -1, -1):
16             if digits[i] != 9:
17                 digits[i] += 1
18                 return digits
19             else:
20                 digits[i] = 0
21         
22         if digits[0] == 0:
23             digits.insert(0, 1)
24             return digits

 

解法二:

Python的赖皮解法,利用str和List的转换:

这里用Python可以取巧,无论这个数组是什么,都可以把它转换为str再加1,再把这个str转化为数组即可,因为题目中说到数组中每个元素只存储单个数字。

 1 class Solution:
 2     def plusOne(self, digits: List[int]) -> List[int]:
 3         ans = len(digits) -1
 4         # 数组中每个元素只存储单个数字很重要!
 5         # 主要考虑进位的情况,如99,999,199等
 6         # 解法一: Python的赖皮解法,利用str和List的转换
 7         # sum = 0
 8         # for i in range(len(digits)):
 9         #     sum = sum * 10 + digits[i]
10 
11         # return[int(x) for x in str(sum+1)] 
12         
13         # 这种太赖皮了不提倡

 

88.Merge Sorted Array

题目描述:简单

题目涉及归并排序

看到题目直觉是直接合并两个数组再进行快速排序,但是这样时间复杂度太高,并且没有利用两个数组本身有序这个信息。
看到有序,考虑双指针,这道题的解法一是从前往后的双指针遍历方法:

解法一

由于这道题需要合并到nums1中,则必须要先保存下nums1原来的元素,然后将新元素输出到nums1数组中。
具体做法是让p、q两个指针分别指向两个数组的开头,然后每次都比较大小,较小的一方则加入到新数组中且指针+1,遍历完后还需判断是否还有需要加入数组的数字。
时间复杂度 : O(n + m),空间复杂度 : O(m)。因为使用了一个新数组保存原来的nums1。

 1 class Solution:
 2     def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
 3         """
 4         Do not return anything, modify nums1 in-place instead.
 5         """
 6         # 直觉是直接合并两个数组再进行快速排序,但是这样时间复杂度太高,并且没有利用两个数组本身有序这个信息。
 7         # 看到有序,考虑双指针,这道题的解法一是从前往后的双指针遍历方法:由于这道题需要合并到nums1中,则必须要先保存下nums1原来的元素,然后将新元素输出到nums1数组中。
 8         # 具体做法是让p、q两个指针分别指向两个数组的开头,然后每次都比较大小,较小的一方则加入到新数组中且指针+1,遍历完后还需判断是否还有需要加入数组的数字。
 9         #时间复杂度 : O(n + m),空间复杂度 : O(m)。因为使用了一个新数组保存原来的nums1
10         nums1_cp = nums1[:m]
11         nums1[:] = []
12         p = 0
13         q = 0
14         while p < m and q < n:
15             if nums1_cp[p] < nums2[q]:
16                 nums1.append(nums1_cp[p])
17                 p += 1
18             else:
19                 nums1.append(nums2[q])
20                 q += 1
21         # 遍历完如果还有需要增加的数字,即p和q还没有达到本身数组长的地方
22         if p < m:
23             nums1[p+q:] = nums1_cp[p:] # 本身有序,直接把后面的加入新数组
24         if q < n:
25             nums1[p+q:] = nums2[q:]

 

这里还有一个问题可以注意一下,在Python3中使用了这样的代码来保存新数组和生成新的nums1:

nums1_copy = nums1[:m],

nums1[:] = []

我们可能会问,为何要使用 nums1[:],是否可以将 nums1[:] 换为 nums1 ?

我们来看一下题目要求:

对于 python3 语言, 题目要求:Do not return anything, modify nums1 in-place instead.即需要就地修改 nums1 对象,而不能新生成一个对象,并让 nums1 指向这一新对象。

注意到 python3 语言, 对象是一个盒子,有具体的地址,而变量名相当于是 "标签",可以贴在盒子上。

我们需要辨析:nums1 = A 和 nums1[:] = A 的不同之处:

nums1 = A # 更改 nums1 这一变量名所指向的对象。让 nums1 变量指向 A 所指向的对象

nums1[:] = A # 对 nums1 指向的对象赋值。把 A 变量指向的对象的值逐个 copy 到 nums1 指向的对象中并覆盖 nums1 指向的对象的原来值。

nums1[:] 等价于 nums1[0:len(nums1)] 相当于取 nums1 对应的对象的一个视图,通常用这个来改变原对象的某几位值。

比如有时候,我们用 A[:2] = [0,1], 来改变 A 所指向的 list 对象的前两个值。

而如果用 A = [0,1], 则是让 A 这一变量名指向新的 list 对象 [0,1],这不符合题目要求。

posted @ 2020-11-10 10:12  Jesse-jia  阅读(103)  评论(0编辑  收藏  举报