数组篇
26. 从排序数组中删除重复项
给定一个有序数组,你需要原地删除其中的重复内容,使每个元素只出现一次,并返回新的长度。
不要另外定义一个数组,您必须通过用 O(1) 额外内存原地修改输入的数组来做到这一点。
示例:
给定数组: nums = [1,1,2], 你的函数应该返回新长度 2, 并且原数组nums的前两个元素必须是1和2 不需要理会新的数组长度后面的元素
Given a sorted array, remove the duplicates in-place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example:
Given nums = [1,1,2], Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. It doesn't matter what you leave beyond the new length.
class Solution:
def removeDuplicates(self, nums):
"""
:type nums: List[int]
:rtype: int
前提是已排序
判断nums[j]与nums[i-1]元素,相等j+1继续判断下一元素;不相等,nums[j]赋值给nums[i],
返回i与size的最小值(size为0时返回size,没有不相同的时候 size==i,有相同的i
122.买卖股票的最佳时机 II—— best time to buy and shell stock II
假设有一个数组,它的第 i 个元素是一个给定的股票在第 i 天的价格。设计一个算法来找到最大的利润。你可以完成尽可能多的交易(多次买卖股票)。然而,你不能同时参与多个交易(你必须在再次购买前出售股票)。
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
total = 0
#当len(prices)==0时,不进行for循环,直接ruturn total
for i in range(1,len(prices)):
total += max(0,prices[i]-prices[i-1])
return total
189. 旋转数组rotate array
将包含 n 个元素的数组向右旋转 k 步。
例如,如果 n = 7 , k = 3,给定数组 [1,2,3,4,5,6,7]
,向右旋转后的结果为 [5,6,7,1,2,3,4]
。
class Solution:
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: void Do not return anything, modify nums in-place instead.
"""
if k%len(nums)!=0:#整除则旋转一轮不变
l=len(nums)
k=k%l#取余知旋转几次
nums[:k],nums[k:]=nums[l-k:],nums[:l-k]
217. 存在重复
给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数应该返回 true。如果每个元素都不相同,则返回 false。
class Solution:
def containsDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
#>>> s = set([1, 1, 2, 2, 3, 3])
#>>> s
#{1, 2, 3} 在se()中没有重复的key
return len(nums) != len(set(nums))
"""利用hash table,别忘了判断空数组的情况.其实更麻烦"""
class Solution(object):
def containsDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
if not nums:
return False
dic = dict() #用list(),append添加会超时
for num in nums:
if num in dic:
return True
dic[num] = 1
return False
136. 只出现一次的数字
给定一个整数数组,除了某个元素外其余元素均出现两次。请找出这个只出现一次的元素。
备注:
你的算法应该是一个线性时间复杂度。 你可以不用额外空间来实现它吗?
class Solution:
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
#由于整数数组只有一个元素出现一次,利用异或(两个相同的数的异或为0)运算所有数组元素
#出现两次的元素不管顺序如何最后都会异或为0,最后只会剩下出现一次的某元素
a = 0
for i in nums:
a ^= i
return a
350. 两个数组的交集 II
给定两个数组,写一个方法来计算它们的交集。
例如:
给定 nums1 = [1, 2, 2, 1]
, nums2 = [2, 2]
, 返回 [2, 2]
.
注意:
跟进:
class Solution:
def intersect(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
#遍历nums1,用字典对应元素及出现次数
dic = dict()
for num in nums1:
if num in dic:
dic[num] += 1
else:
dic[num] = 1
#遍历nums2,判断是否在字典中,存在value-1,并加入到list中
n = list()
for num in nums2:
if num in dic.keys() and dic[num] != 0:
dic[num] -= 1
n.append(num)
return n
"""但是python内置了Counter类型数组,可以方便实现计数功能"""
class Solution(object):
def intersect(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
from collections import Counter
c1 = Counter(nums1)
c2 = Counter(nums2)
return list((c1&c2).elements())
66. 加一
给定一个非负整数组成的非空数组,在该数的基础上加一,返回一个新的数组。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
可以假设整数不包含任何前导零,除了数字0本身。
示例 1:
输入: [1,2,3] 输出: [1,2,4] 解释: 输入数组表示数字 123。
示例 2:
输入: [4,3,2,1] 输出: [4,3,2,2] 解释: 输入数组表示数字 4321。
class Solution:
def plusOne(self, digits):
"""
:type digits: List[int]
:rtype: List[int]
"""
#str和int的相互转换
sum = 0
for i in digits:
sum = sum * 10 + i
return [int(x) for x in str(sum+1)]
class Solution:
def plusOne(self, digits):
"""
:type digits: List[int]
:rtype: List[int]
"""
n = len(digits)
i = n-1
while i > -1:#从列表末尾开始加1计算,并判断是否进位,循环至最高位
if digits[i] != 9:#第i个元素不为9,元素直接+1,并返回列表,首轮判定的是列表末尾元素
digits[i] = digits[i] + 1
return digits
elif i > 0: #如果为9,且不是最高位元素,该位元素=0,i-1(上一位元素要进位加1,重新判断i-1位的元素是否为9)
digits[i] = 0
i = i - 1
continue
else:#如果为9,且i=0(此时为最高位,如999+1=1000,第0位元素=0,在列表首位添加数字元素1)
digits[i] = 0
digits =[1] + digits
i = i - 1#跳出循环条件
return digits
283. 移动零
给定一个数组 nums
, 编写一个函数将所有 0
移动到它的末尾,同时保持非零元素的相对顺序。
例如, 定义 nums = [0, 1, 0, 3, 12]
,调用函数之后, nums
应为 [1, 3, 12, 0, 0]
。
注意事项:
class Solution:
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
m = len(nums)
i = 0
while i
1
.
两数之和
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
dic = dict()
for index,value in enumerate(nums):
sub = target - value
if sub in dic:
return [dic[sub],index]
else:
dic[value] = index
36. 有效的数独
判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。
1-9
在每一行只能出现一次。1-9
在每一列只能出现一次。1-9
在每一个以粗实线分隔的 3x3
宫内只能出现一次。上图是一个部分填充的有效的数独。
数独部分空格内已填入了数字,空白格用 '.'
表示。
示例 1:
输入: [ ["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
示例 2:
输入: [ ["8","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"] ] 输出: false 解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
说明:
1-9
和字符 '.'
。9x9
形式的。class Solution:
# @param board, a 9x9 2D array
# @return a boolean
def valid(self,x,y,tmp,board):
#tem元素位于x行,y列
for i in range(9): #判断第y列元素是否有等于tmp元素的
if board[i][y]==tmp:
return False
for j in range(9): #判断第x行元素是否有等于tmp元素的
if board[x][j]==tmp:
return False
for i in range(3): #判断3*3宫内是否有等于tmp元素的
for j in range(3):
if board[(x//3)*3+i][(y//3)*3+j]==tmp: #根据x,y计算出3*3宫的元素下标范围,x//3得到的是整数部分
return False
return True
def isValidSudoku(self, board):
for i in range(9): #遍历 行
for j in range(9): #在行不变的情况下,遍历一整列
if board[i][j]=='.': #在为时'.',继续遍历
continue
tmp=board[i][j] #当为数字时,赋值给tmp
board[i][j]='D' #将该位元素修改为不相关元素
if self.valid(i,j,tmp,board)==False: #判断tmp与数组所有元素(包括board[i][j],所以修改了board[i][j])是否相同
return False
else: #不相同则将board[i][j]修改回来
board[i][j]=tmp
return True
class Solution:
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
return (self.is_row_valid(board) and
self.is_col_valid(board) and
self.is_square_valid(board))
def is_row_valid(self, board):
for row in board:#遍历每一行
if not self.is_unit_valid(row): #is_unit_valid(row)返回的是False,说明行中有相同元素,则return False
return False
return True
'''
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b) # 打包为元组的列表
[(1, 4), (2, 5), (3, 6)]
>>> zip(a,c) # 元素个数与最短的列表一致
[(1, 4), (2, 5), (3, 6)]
>>> zip(*zipped) # 与 zip 相反,可理解为解压,返回二维矩阵式
[(1, 2, 3), (4, 5, 6)]
'''
def is_col_valid(self, board):
for col in zip(*board):#zip(*board)将board中对应列的元素以列表形式打包成一个个元祖
if not self.is_unit_valid(col):#判断是否有相同元素
return False
return True
def is_square_valid(self, board):
for i in (0, 3, 6):
for j in (0, 3, 6):
square = [board[x][y] for x in range(i, i + 3) for y in range(j, j + 3)] #将3*3宫的元素以列表形式存储在square中
if not self.is_unit_valid(square):
return False
return True
def is_unit_valid(self, unit):
unit = [i for i in unit if i != '.'] #遍历参数unit将不为.的元素以列表形式存储到变量unit
return len(set(unit)) == len(unit) #利用set的性质,如果有重复元素则两边不相等,返回False
48
.
旋转图像
给定一个 n × n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例 1:
给定 matrix = [ [1,2,3], [4,5,6], [7,8,9] ], 原地旋转输入矩阵,使其变为: [ [7,4,1], [8,5,2], [9,6,3] ]
示例 2:
给定 matrix = [ [ 5, 1, 9,11], [ 2, 4, 8,10], [13, 3, 6, 7], [15,14,12,16] ], 原地旋转输入矩阵,使其变为: [ [15,13, 2, 5], [14, 3, 4, 1], [12, 6, 8, 9], [16, 7,10,11] ]
class Solution:
def rotate(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: void Do not return anything, modify matrix in-place instead.
"""
"""使用两次旋转
The idea was firstly transpose the matrix and then flip it symmetrically. For instance,
1 2 3
4 5 6
7 8 9
after transpose, it will be swap(matrix[i][j], matrix[j][i])
1 4 7
2 5 8
3 6 9
Then flip the matrix horizontally. (swap(matrix[i][j], matrix[i][matrix.length-1-j])
7 4 1
8 5 2
9 6 3
"""
n = len(matrix)
#对角线元素交换
for i in range(n):
for j in range(i):
matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j]
#同一行前后对应位置的元素互换
left = 0
right = n - 1
while left < right:
for i in range(n):
matrix[i][left],matrix[i][right] = matrix[i][right],matrix[i][left]
left = left + 1
right = right - 1