01 字符串相加
class Solution(object):
def addStrings(self, num1, num2):
"""
:type num1: str
:type num2: str
:rtype: str
"""
# 方法1:可以使用int的话直接str->int相加再str
return str(int(num1)+int(num2))
# 方法2:不可以使用int则使用ascii减去‘0’得到数字,方法是chr(cur+ord('0'))
res = ''
carry = 0
i = len(num1) - 1
j = len(num2) - 1
while i>=0 or j>=0:
n1 = num1[i] if i>=0 else '0'
n2 = num2[j] if j>=0 else '0'
temp = ord(n1) + ord(n2) - 2*ord('0') + carry
cur = temp % 10
carry = temp // 10
res = chr(cur+ord('0')) + res
i -= 1
j -= 1
return '1'+res if carry!=0 else res
- 时间复杂度 O ( m a x ( M , N ) ) O(max(M,N)) O(max(M,N)):其中 M,N 为两数字长度,按位遍历一遍数字(以较长的数字为准)
- 空间复杂度 O ( 1 ) O(1) O(1):指针与变量使用常数大小空间。
03 数组中重复的数字
长度n的数组nums元素范围0~n-1,找到任意一个重复的数字。
class Solution(object):
def findRepeatNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 方法1:哈希表。set()不重复数组 添加元素使用.add
repeat = -1
tmp = set()
for i in range(len(nums)):
tmp.add(nums[i])
if len(tmp)<i+1:
repeat = nums[i]
break # break 跳出循环
return repeat
# PS:遇到另外一种写法非常简洁
dic = set()
for num in nums:
if num in dic: return num
dic.add(num)
return -1
# 方法2:排序法。sort()排序后前后相邻两个元素相同代表重复
nums.sort()
for i in range(len(nums)-1):
if nums[i] == nums[i+1]:
return nums[i]
# 方法3:原地置换。有个细节就是数组n,元素范围到n-1,所以可以把数字放到其索引的位置,如果原索引位置和它相同说明出现了重复。
i = 0
while i < len(nums):
if nums[i] == i:
i += 1
continue
if nums[nums[i]] == nums[i]:
return nums[i]
nums[nums[i]], nums[i] == nums[i], nums[nums[i]] # python互换很直接
return -1
遍历数组的时间复杂度是 O ( N ) O(N) O(N),因为跟数组的长度有关。但是交换操作的时间复杂度是 O ( 1 ) O(1) O(1),HashSet添加与查找元素也是 O ( 1 ) O(1) O(1)。 HashSet占用的空间复杂度是 O ( N ) O(N) O(N),因为不是一次性开辟了一个新的常数大小的空间,而是随着时间往里放。
04 二维数组元素查找
在从左到右和从上到下都是递增的二维数组中查找某个整数是否存在
class Solution(object):
def findNumberIn2DArray(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
# 法1:暴力查找,不考虑排好序问题,时间超过10%,内存超过10%
flag = False
for i in range(len(matrix)):
for j in range(len(matrix[0])):
if target == matrix[i][j]:
flag = True
break
return flag
# 别人的二维数组元素引用非常简洁,而且return代替了break
for row in matrix:
for column in row:
if column==target:
return True
return False
# 法2:线性查找,考虑排序,从右上角开始,时间超过97%,内存超过97%
if len(matrix)==0 or len(matrix[0])==0:
return False # 针对[]和[[]]这种特殊情况,直接结束
i = 0
j = len(matrix[0]) -1
while i < len(matrix) and j > -1:
cur = matrix[i][j]
if cur == target:
return True
elif cur < target:
i += 1
else:
j -= 1
return False
暴力方法是遍历所有元素,所以时间复杂度是 O ( M N ) O(MN) O(MN),但是排序的方法最多一整行和一整列,因此时间复杂度是 O ( M + N ) O(M+N) O(M+N)。
05 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
考虑:发现一个变成三个,提前设定一个三倍长的空的往里面填,python添加元素使用+即可
PS:python中可以直接替换函数
class Solution(object):
def replaceSpace(self, s):
"""
:type s: str
:rtype: str
"""
# 时间击败57% 内存击败91%
lst = s.split(' ')
return '%20'.join(lst)
# 时间击败80%,内存击败30%
return s.replace(' ','%20')
# 时间击败80%,内存击败80%
ss = ''
for i in range(len(s)):
if s[i] == ' ':
ss = ss + '%20'
else:
ss = ss + s[i]
return ss
06 倒序打印链表
链表只能从头到尾访问节点,而题目要求倒序打印,则需要使用栈辅助,将节点从前向后输入栈,再弹出到列表中。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reversePrint(self, head):
"""
:type head: ListNode
:rtype: List[int]
"""
# 时间超过11% 内存超过11%
# head.val回溯当前节点值,head.next递归
return self.reversePrint(head.next) + [head.val] if head else []
# 时间超过70% 内存超过40%
# 栈可以后入先出,解决链表只能从前往后
stack = []
while head:
stack.append(head.val)
head = head.next
return stack[::-1]
head.val 当前节点 val.next 往后一个节点 循环时考虑head是否为[]代表是否到最右
列表的添加使用append() 列表的倒序使用[::-1]
832 翻转图像
python可以直接交换 a,b = b,a
A[~i]与A[i]是对称的哦,翻转的话直接^1
xrange 比 range 省空间 不过目前是差不多的
class Solution(object):
def flipAndInvertImage(self, A):
"""
:type A: List[List[int]]
:rtype: List[List[int]]
"""
for row in A:
for i in xrange((len(row)+1)/2):
row[i], row[~i] = row[~i]^1, row[i]^1
return A
面试题 17.10 主要元素
超过50%的元素为主要元素。给定数组,找主要元素,没有返回-1。要求时间复杂度O(N),空间复杂度O(1)。
class Solution:
def majorityElement(self, nums:List[int]) -> int:
nums = sorted(nums)
element = nums[len(nums) // 2]
count = 0
for ele in nums:
if ele == element:
count += 1
return element if count > len(nums)/2 else -1
时间复杂度O(nlogn),空间复杂度O(n)。
class Solution:
def majorElement(self, nums:List[int]) -> int:
ele_dict = {}
for ele in nums:
if ele in ele_dict.keys():
ele_dict[ele] += 1
else:
ele_dict[ele] = 1
for key in ele_dict.keys():
if ele_dict[keys] > len(nums)/2:
return keys
return -1
832 翻转图像
python可以直接交换 a,b = b,a
A[~i]与A[i]是对称的哦,翻转的话直接^1
xrange 比 range 省空间 不过目前是差不多的
class Solution(object):
def flipAndInvertImage(self, A):
"""
:type A: List[List[int]]
:rtype: List[List[int]]
"""
for row in A:
for i in xrange((len(row)+1)/2):
row[i], row[~i] = row[~i]^1, row[i]^1
return A
1233 删除子文件夹
比较字符串是否在前者基础上增加可以:先排序 然后b.startswith(‘a/’)判断
class Solution(object):
def removeSubfolders(self, folder):
"""
:type folder: List[str]
:rtype: List[str]
"""
new = ['0']
for f in sorted(folder):
if not f.startswith(new[-1]+'/'):
new.append(f)
return new[1:]
969 煎饼排序
就是输入:[3,2,4,1] 输出:[4,2,4,3],输出不一定是最短序列
技巧就是找到最大的放到第一个然后丢到最后去
注意序列会变化,所以也要对arr进行改变(debug点)
列表的倒序可以使用a[::-1]表示
class Solution(object):
def pancakeSort(self, arr):
"""
:type arr: List[int]
:rtype: List[int]
"""
ans = []
N = len(arr)
for i in range(len(arr)):
for j in range(N):
if arr[j] == N:
ans.append(j+1)
arr = arr[:j+1][::-1]+arr[j+1:]
ans.append(N)
arr = arr[:N][::-1]+arr[N:]
N -= 1
return ans
64 最小路径和
之前算法课听过
class Solution(object):
def minPathSum(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
rows, columns = len(grid), len(grid[0])
dp = [[0] * columns for _ in range(rows)]
dp[0][0]=grid[0][0]
for i in range(1, rows):
dp[i][0] = dp[i-1][0] + grid[i][0]
for j in range(1, columns):
dp[0][j] = dp[0][j-1] + grid[0][j]
for i in range(1,rows):
for j in range(1, columns):
dp[i][j] = min(dp[i-1][j],dp[i][j-1])+grid[i][j]
return dp[rows-1][columns-1]
78 子集
输入[1, 2, 3]输出子集,就是输出一个[[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]列表,元素也是列表,所以创建新空间是[[]]。
这个列表元素添加的时候,直接用+就可以了。
+和append的区别是,对原来的序列操作是一样的,但是append是对原来序列操作,而+是产生了新序列。
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
n = len(nums)
res = [[]]
for num in nums:
res += [current + [num] for current in res]
return res
42 接雨水
其实就是,找到左右两边最高的,中间低就可以接到水。
要注意分别从两边查询,是双指针方法。
class Solution(object):
def trap(self, height):
"""
:type height: List[int]
:rtype: int
"""
sum = 0
left = 0
right = len(height) - 1
left_max = right_max =0
while left<=right:
if left_max < right_max:
sum += max(0, left_max - height[left])
left_max = max(left_max, height[left])
left += 1
else:
sum += max(0, right_max - height[right])
right_max = max(right_max, height[right])
right -= 1
return sum