1.Python内置列表函数和方法
列表创建和操作
-
list(): 创建一个空列表或将可迭代对象转换为列表。
-
append(x): 在列表末尾添加一个元素x。
-
extend(iterable): 通过添加iterable中的所有元素来扩展列表。
-
insert(i, x): 在指定位置i插入元素x。
-
remove(x): 移除列表中值为x的第一个元素。
-
pop([i]): 移除并返回列表中指定位置i的元素,若不指定则移除并返回最后一个元素。
-
clear(): 移除列表中的所有元素。
-
index(x,[start[,end]]): 返回列表中第一个值为x的元素的索引。
-
count(x): 返回列表中值为x的元素数量。
-
sort(key=None, reverse=False): 对列表中的元素就地排序。
-
reverse(): 反转列表中的元素。
-
copy(): 返回列表的浅拷贝。
-
[expression for item in iterable]: 使用列表综合生成新列表。
2.算法题
2.1 删除排序数组中的重复项(双指针)
题目
给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:
更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。
示例
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
双指针解法
class Solution(object):
def removeDuplicates(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
slow=0
for i in range(1,len(nums)):
if nums[i] != nums[slow]:
slow+=1
nums[slow] = nums[i]
return slow+1
分析
- 时间复杂度:利用双指针,一次遍历即可去重,时间复杂度为O(n)
- 空间复杂度:不使用任何与输入大小成比例的额外空间,空间复杂度为O(1)
2.2 买卖股票的最佳时机 II
题目
给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
示例
输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3。
最大总利润为 4 + 3 = 7 。
解法
class Solution(object):
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
if len(prices)<=1:
return 0
count=0
for i in range(1,len(prices)):
if prices[i]>prices[i-1]:
count+=prices[i]-prices[i-1]
return count
分析
- 时间复杂度:循环时间复杂度为O(n),条件判断和累加时间复杂度为O(1),综合,时间复杂度为O(n)。
- 空间复杂度:算法使用的额外空间是常数,不随输入规模增长,故空间复杂度为O(1)。
2.3 旋转数组
题目
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解法1
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
k = k % len(nums)
tmp = nums[:len(nums)-k]
nums[:k] = nums[len(nums)-k:]
nums[k:] = tmp
分析
- 时间复杂度:O(n)
- 空间复杂度:O(n)
解法2
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
k = k % len(nums)
nums[:] = nums[len(nums)-k:] + nums[:len(nums)-k]
分析
- 时间复杂度:O(n),遍历整个列表
- 空间复杂度:O(n),因为创建了新的切片
解法3
在这里插入代码片
2.4 只出现一次的数字
题目
给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
示例
输入:nums = [2,2,1]
输出:1
解法
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
res = 0
for i in range(len(nums)):
res = res^nums[i]
return res
分析
异或运算,相异为真,相同为假,所以a^ a =0,0^a = a
因为异或运算 满足交换律所以数组经过异或运算,单独的值就剩下了
- 时间复杂度:O(N)
- 空间复杂度:O(1)
2.5 两个数组的交集 II
题目
给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
示例
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
解法1 (字典)
class Solution(object):
def intersect(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
dict1 = dict(Counter(nums1))
dict2 = dict(Counter(nums2))
dict3 = {}
list = []
for key in dict1:
if key in dict2:
dict3[key]=min(dict1[key],dict2[key])
for key,count in dict3.items():
list.extend([key]*count)
return list
解法2 (双指针)
class Solution(object):
def intersect(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
p1,p2=0,0
res=[]
nums1 = sorted(nums1)
nums2 = sorted(nums2)
while p1<len(nums1) and p2<len(nums2):
if nums1[p1]==nums2[p2]:
res.append(nums1[p1])
p1+=1
p2+=1
elif nums1[p1]<nums2[p2]:
p1+=1
else:
p2+=1
return res
2.6 加一
题目
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
示例
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。
解法
class Solution(object):
def plusOne(self, digits):
"""
:type digits: List[int]
:rtype: List[int]
"""
s = ''.join([str(d) for d in digits])
sd = int(s)+1
digits = [int(d) for d in str(sd)]
return digits
分析
- 时间复杂度:O(N)
- 空间复杂度:O(N)
2.7 移动零
题目
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
解法1
class Solution(object):
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
for i in range(len(nums)-1,-1,-1):
if nums[i]==0:
del nums[i]
nums.append(0)
分析
- 时间复杂度:O(N²),因为删除nums[i]最差需要O(N)时间
- 空间复杂度:O(1)
解法2
class Solution(object):
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
p=0
for i in range(len(nums)):
if nums[i]!=0:
nums[p]=nums[i]
p+=1
for i in range(p,len(nums)):
nums[i]=0
分析
- 时间复杂度:O(N)
- 空间复杂度:O(1)
2.8 两数之和
题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案
示例
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
解法
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
d = {}
for i in range(len(nums)):
if target-nums[i] in d:
return [d[target-nums[i]],i]
else:
d[nums[i]]=i
分析
- 时间复杂度:O(N)
- 空间复杂度:O(N)
2.9 有效的数独
题目
请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
注意:
一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
空白格用 '.' 表示。
示例
输入:board =
[[“5”,“3”,“.”,“.”,“7”,“.”,“.”,“.”,“.”]
,[“6”,“.”,“.”,“1”,“9”,“5”,“.”,“.”,“.”]
,[“.”,“9”,“8”,“.”,“.”,“.”,“.”,“6”,“.”]
,[“8”,“.”,“.”,“.”,“6”,“.”,“.”,“.”,“3”]
,[“4”,“.”,“.”,“8”,“.”,“3”,“.”,“.”,“1”]
,[“7”,“.”,“.”,“.”,“2”,“.”,“.”,“.”,“6”]
,[“.”,“6”,“.”,“.”,“.”,“.”,“2”,“8”,“.”]
,[“.”,“.”,“.”,“4”,“1”,“9”,“.”,“.”,“5”]
,[“.”,“.”,“.”,“.”,“8”,“.”,“.”,“7”,“9”]]
输出:true
解法
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
a = [[0]*9 for _ in range(9)]
b = [[0]*9 for _ in range(9)]
c = [[0]*9 for _ in range(9)]
for i in range(9):
for j in range(9):
if board[i][j] != '.':
num=int(board[i][j]) - 1
n = i//3+(j//3)*3
if a[i][num]==1 or b[j][num]==1 or c[n][num]==1:
return False
else:
a[i][num]=1
b[j][num]=1
c[n][num]=1
return True
2.10 旋转图像
题目
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]
解法
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
n = len(matrix)
tmp = [[0]*n for _ in range(n)]
for i in range(n):
for j in range(n):
tmp[i][j] = matrix[n-1-j][i]
matrix[:]=tmp
分析
- 时间复杂度:O(N²)
- 空间复杂度:O(N²)