算法通关手册 刷题笔记1 数组基础
Posted 临风而眠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法通关手册 刷题笔记1 数组基础相关的知识,希望对你有一定的参考价值。
算法通关手册 刷题笔记1 数组基础
持续更新中
文章目录
数组操作题目
题号 | 标题 | 题解 | 标签 | 难度 |
---|---|---|---|---|
0189 | 轮转数组 | Python | 数组 | 中等 |
0066 | 加一 | Python | 数组 | 简单 |
0724 | 寻找数组的中心下标 | Python | 数组 | 简单 |
0485 | 最大连续 1 的个数 | Python | 数组 | 简单 |
0238 | 除自身以外数组的乘积 | Python | 数组 | 中等 |
0189 轮转数组
AC
自己的解法
-
一开始犯了错误:注意python中数组的赋值
-
两个列表list1和list2,直接用等号赋值,list2修改后,list1也会被修改
- 想要不改变原列表,使用
[:]
或者.copy()
- 想要不改变原列表,使用
-
一开始的错误代码
def rotate2( nums, k): """ :type nums: List[int] :type k: int :rtype: None Do not return anything, modify nums in-place instead. """ nums2 = nums for i in range(len(nums)): nums2[i] = nums[(i+k+1)%len(nums)] return nums2 rotate2([1,2,3,4,5,6,7],3)
[5, 6, 7, 5, 6, 7, 5]
来分析一下: nums2[0] = nums[4] , 这时候 nums2[0]和nums[0]都变成了5 ,所以nums2[3] = nums[0] = 5…
-
-
改了改,以为自己做对了,但是没AC
def rotate(nums, k): """ :type nums: List[int] :type k: int :rtype: None Do not return anything, modify nums in-place instead. """ # nums2 = num nums2 = [] for i in range(len(nums)): nums2.append(0) for i in range(len(nums)): #下面这俩应该都可以 ** nums2[i] = nums[(i+k+1) % len(nums)] # nums2[(i+k)%len(nums)] = nums[i]** return nums2 rotate([1,2,3,4,5,6,7],3)
[5, 6, 7, 1, 2, 3, 4]
难绷,审题! 去掉return就行了
其他解法
-
算法通关手册上的python解法
class Solution: def rotate(self, nums: List[int], k: int) -> None: """ Do not return anything, modify nums in-place instead. """ n = len(nums) k = k % n self.reverse(nums, 0, n-1) self.reverse(nums, 0, k-1) self.reverse(nums, k, n-1) def reverse(self, nums: List[int], left: int , right: int) -> None: while left < right: tmp = nums[left] nums[left] = nums[right] nums[right] = tmp left += 1 right -=1
-
力扣题解区上面看到切片的解法,感觉very smart
class Solution: def rotate(self, nums: List[int], k: int) -> None: """ Do not return anything, modify nums in-place instead. """ k = k % len(nums) nums[:] = nums[-k:] + nums[:-k]
知识点查漏补缺
关于python中的数组赋值
- https://www.geeksforgeeks.org/array-copying-in-python/
- https://www.runoob.com/w3cnote/python-understanding-dict-copy-shallow-or-deep.html
python中对象的引用
-
试了下整数变量会不会和那个数组也是一样的情况,不是的
-
于是去查了查
0066 加一
AC
自己的解法
-
一开始写的代码
class Solution: def plusOne(self, digits: List[int]) -> List[int]: k = len(digits) sum = 0 m = 1 while k >= 1: sum += m*digits[k-1] m *= 10 k -= 1 newlis = [] sum += 1 j = 0 while sum > 0: # newlis.append(sum % 10) newlis.insert(j, sum % 10) sum //=10 return newlis
其他解法
-
看《算法通关手册》的题解
-
感觉思路很清晰
有可能有进位,先在前面放个0,末位加个1,啥时候会有进位呢,那个位置上的数字为10的时候,如果低位都没碰到10,那么高位肯定不会碰到10,直接break,返回原来的列表,即现在的digits[1:]
哪一位有进位,就把那一位变成0,然后它的前一位+1
如果会一直进位到最高位,那么就返回digits
def plusOne(self, digits: List[int]) -> List[int]: digits = [0] + digits digits[len(digits)-1] += 1 for i in range(len(digits)-1,0,-1): if digits[i] != 10: break else: digits[i] = 0 digits[i-1] += 1 if digits[0] == 0: return digits[1:] else: return digits
-
注意 [0] + digits的顺序是有影响的
-
-
力扣官方题解 妙啊
-
思路
- 找出最长的后缀9
- 如果 $\\textitdigits $的末尾没有 999,例如 [1,2,3],那么我们直接将末尾的数加一,得到 [1, 2, 4]并返回;
- 如果 digits \\textitdigits digits 的末尾有若干个 9,例如 [1,2,3,9,9]那么我们只需要找出从末尾开始的第一个不为 999的元素,即 333,将该元素加一,得到 [1,2,4,9,9]]。随后将末尾的 999 全部置零,得到 [1,2,4,0,0]并返回。
- 如果 digits \\textitdigits digits 的所有元素都是 999,例如 [9,9,9,9,9],那么答案为 [ 1 , 0 , 0 , 0 , 0 , 0 ] [1, 0, 0, 0, 0, 0] [1,0,0,0,0,0]。我们只需要构造一个长度比 digits \\textitdigits digits多 111 的新数组,将首元素置为 111,其余元素置为 000 即可。
- 找出最长的后缀9
-
算法
-
只需要对数组 digits \\textitdigits digits进行一次逆序遍历,找出第一个不为 999 的元素,将其加一并将后续所有元素置零即可。如果 digits \\textitdigits digits中所有的元素均为 999,那么对应着「思路」部分的第三种情况,我们需要返回一个新的数组。
class Solution: def plusOne(self, digits: List[int]) -> List[int]: n = len(digits) for i in range(n -1, -1, -1): if digits[i] != 9: digits[i] += 1 for j in range(i + 1, n): digits[j] = 0 return digits return [1] + [0] * n
-
-
知识点查漏补缺
-
在前面自己的解法那个代码里面
-
放到vscode里面会有这个问题
- 需要
from typing import List
- 需要
-
那一步用append顺序会反 双边队列里面才有appendleft
-
用insert比较好
-
另外别记混了 那个appendleft是双边队列才有的 之前在头歌学过👇
-
不过这题确实可以试试双边队列
-
-
python里面的
//
和/
两种除法的区别//是向下取整
-
0724 寻找数组的中心下标
AC
自己的解法
-
一开始的错误代码
- 一开始的代码 class Solution: def pivotIndex(self, nums: List[int]) -> int: suml = 0 # 从左往右的和 sumr = 0 # 从右往左的和 # l = len(nums) lisl = [] lisr = [] for i in range(len(nums)): suml += nums[i] lisl.append(suml) for i in range(len(nums)-1,-1,-1): sumr += nums[i] lisr.append(sumr) # flag = 0 if lisl[0] == lisl[len(nums)-1]: return 0 elif lisr[0] == lisr[len(nums)-1]: return len(nums)-1 else: for j in range(len(nums)): if lisl[j] == lisr[j]: return j return -1
lisl=[1,8,11,17,22,28]
lisr=[6,11,17,20,21,28]
返回5是不正确的,突然发现自己这个代码只适合中心点两边元素个数相等的情况…
按照那个思路,在左和数组and 右和数组相同位置的话,那只能是元素个数相同了
-
改了改,还是有问题
class Solution: def pivotIndex(self, nums: List[int]) -> int: suml = 0 # 从左往右的和 sumr = 0 # 从右往左的和 # l = len(nums) lisl = [] lisr = [] for i in range(len(nums)): suml += nums[i] lisl.append(suml) for i in range(len(nums)-1,-1,-1): sumr += nums[i] lisr.append(sumr) # flag = 0 if lisl[0] == lisl[len(nums)-1]: return 0 elif lisr[0] == lisr[len(nums)-1]: return len(nums)-1 else: for j in range(len(nums)): if lisl[j] == lisr[len(nums)-1-j]: return j return -1
一开始感觉自己把两种特殊情况提出来很聪明,结果发现好像题目中这个条件的限制
如果数组有多个中心下标,应该返回 最靠近左边 的那一个
那么当左边的和为0的话,右边如果很多0,就会返回最右边的0
-
AC了
-
总结一下自己的思路
- 设立一个数组,每一位依次存储原数组nums从左到右的和
-
再设立一个数组,每一位一次存储原数组nums从右到左的和
- 然后由于题目要求返回靠左的中心点,那下标就从0到 len(nums)-1 从小到大遍历
-
遇到相等的就返回j
-
-
代码如下
class Solution: def pivotIndex(self, nums: List[int]) -> int: suml = 0 # 从左往右的和 sumr = 0 # 从右往左的和 # l = len(nums) lisl = [] lisr = [] for i in range(len(nums)): suml += nums[i] lisl.append(suml) for i in range(len(nums)-1,-1,-1): sumr += nums[i] for j in range(len(nums)): if lisl[j] == lisr[len(nums)-1-j]: return j return -1
但时空复杂度大了些
其他做法
-
官方题解:前缀和
- 思路
- 记数组的和为 t o t a l total total,当遍历到第 i i i个元素时,左侧元素之和为 s u m sum sum,那么右侧元素的和为 t o t a l − n u m s i − s u m total-nums_i-sum total−numsi−sum,左右侧元素相等即为 s u m = t o t a l − n u m s i − s u m sum=total-nums_i-sum sum=total−numsi−sum,即 2 × s u m + n u m s i = t o t a l 2\\times sum + nums_i=total 2×sum+numsi=total
- 当中心索引左侧或右侧没有元素时,即为零个项相加,这在数学上称作「空和」( empty sum \\textempty sum empty sum)。在程序设计中我们约定「空和是零」
- 思路
-
题解没给python的,自己AC
-
对着题解的文字解释,自己写了一个…但是不全对
class Solution: def pivotIndex(self, nums: List[int]) -> int: total = 0 sum = 0 for i in range(len(nums)): total += nums[i] for i in range(1,len(nums)): sum +=nums[i-1] if 2[AI助力] 算法通关手册 刷题笔记2 数组排序之冒泡排序选择排序
-