目录
2. 给定一个二维数组,其每一行从左到右递增排序,从上到下也是递增排序。给定一个数,判断这个数是否在该二维数组中。
5. 第n项斐波那契数列; 矩形覆盖, n 个 2*1 的小矩形无重叠地覆盖一个 2*n 的大矩形,总共有多少种方法?; 跳台阶
6. 复杂版跳台阶,对于n层台阶,一个青蛙可以一次跳1-n步,有多少种跳法?
判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向上下左右移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。
Excel表, A表示第一列, AA表示第27列,AB表示第28列,根据表的字符串索引转换成数字
15. 输入两个整数m,n,判断二进制最少改变多少位能得m->n
如输入 a = '3[ab]acc',则输出'abababacc'
输入[1,2,3],输出[[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
输入'abc',输出['abc', 'acb', 'bac', 'bca', 'cab', 'cba']。
请实现一个函数用来匹配包括 '.' 和 '*' 的正则表达式。模式中的字符 '.' 表示任意一个字符,而 '*' 表示它前面的字符可以出现任意次(包含 0 次)。
28. 火柴拼成的数字,从一个数移动一根给另外一个数(只能移动一次),移动后最大值?
29. 股票可以有一次买入和一次卖出,买入必须在前。求最大收益。
30. 圆圈中最后的小孩,n个小孩,第0个开始数到m,无放回出列,再从下一个开始数,最后小孩是都在时候第几个?
1. 找到数组中重复数字(字符),返回出现频次最多
# 时间复杂度O(N), 空间复杂度O(1)
class Solution(object):
def find_duplicated(self, a):
res = 0
for i in a:
n = 1 << i-0
if (res | n) == res:
return i
else:
res |= n
return res
# 字典方法,时间复杂度O(N), 空间复杂度O(N)
def maxf(x):
a = dict()
max = 0
for i in x:
tem = str(i)
a[tem] = a.get(tem,0) + 1
if max < a[tem]:
max = a[tem]
return max
2. 给定一个二维数组,其每一行从左到右递增排序,从上到下也是递增排序。给定一个数,判断这个数是否在该二维数组中。
class Solution(object):
def find_in_matrix(self, f, a):
row, column = a.shape
for i in range(row):
# 最后一列大于还是小于
if f > a[i,column-1]:
continue
else:
# 不断左移对比
while column-1 >= 0:
if f == a[i, column-1]:
return True
else:
column -= 1
return False
3. 从尾到头打印链表
class Solution(object):
def reverse_print(self, list_node):
res = []
while list_node:
res.append(0, list_node.val)
list_node = list_node.next
return res
4. 用两个栈实现队列
class Solution(object):
def __init__(self):
self.s1 = []
self.s2 = []
def pop(self):
return self.s2.pop()
def push(self, a):
for i in a:
self.s1.append(i)
while len(self.s1):
self.s2.append(self.s1.pop())
5. 第n项斐波那契数列; 矩形覆盖, n 个 2*1 的小矩形无重叠地覆盖一个 2*n 的大矩形,总共有多少种方法?; 跳台阶
# 递归
class Solution(object):
def find_fibo(self, a):
if a == 0:
return 0
elif a == 1:
return 1
else:
return self.find_fibo(a-1) + self.find_fibo(a-2)
# 动态规划 O(N) 最优解
class Solution(object):
def find_fibo(self, a):
min1 = 0
min2 = 1
if a == 0:
return 0
elif a == 1:
return 1
else:
for i in range(2, a+1):
a = min2
min2 = min1 + min2
min1 = a
return min2
6. 复杂版跳台阶,对于n层台阶,一个青蛙可以一次跳1-n步,有多少种跳法?
# f(n) = f(n-1) + f(n-2) + ... + f(0)
# f(n-1) = f(n-2) + f(n-3) + ... + f(0)
# f(n) - f(n-1) = f(n-1) 等比
class Solution(object):
def jump_num(self, a):
if a == 0:
return 0
return 2**(a-1)
7. 二分查找
# 时间复杂度O(log2(N))
class Solution(object):
def main(self, a, b):
l = 0
h = len(a) - 1
while l <= h:
m = (h + l) // 2
if a[l] < b and a[m] > b:
h = m-1
elif a[h] > b and a[m] < b:
l = m+1
elif a[m] == b:
return m
else:
return -1
8. 有序旋转数组最小数字查找
# 时间复杂度O(log2(N)
class Solution(object):
def find_min(self, a):
if len(a) == 1:
return a[0]
v = a[0]
l = 0
h = len(a) - 1
while l < h:
mid = (h + l) // 2
if a[l] <= a[mid]:
if v > a[l]:
v = a[l]
l = mid
else:
if v > a[mid]:
v = a[mid]
h = mid - 1
return v
9. 机器人运动范围
# a*b矩阵,当a和b每位数之和sum((12,34),sum = 1+2+3+4)<=k时允许进入该格子,统计路径最多能走多远,这个解决的比原题要难一些。
class Solution(object):
def __init__(self):
self.rows = None
self.columns = None
def check_boundry(self, k, x, y):
c = 0
while x > 0:
c += x % 10
x = x // 10
while y > 0:
c += y % 10
y = y // 10
return True if k >= c else False
def max_move(self, mat, coordinate):
x, y = coordinate[0], coordinate[1]
if x < 0 or x >= self.rows:
return 0
elif y < 0 or y >= self.columns:
return 0
if mat[x, y] == 1:
mat[x, y] = 0
return 1 + max(self.max_move(mat, [x-1, y]), self.max_move(mat, [x+1, y]),
self.max_move(mat, [x, y-1]), self.max_move(mat, [x, y+1]))
else:
return 0
def main(self, k, m, n):
if k<0 or m<=0 or n<=0:
return 0
self.rows, self.columns = m, n
mat = np.mat(np.ones((m, n)))
# 生成矩阵,指明哪些能走,哪些不能走
for i in range(self.rows):
for j in range(self.columns):
if not self.check_boundry(k, i, j):
mat[i, j] = 0
return self.max_move(mat, [0, 0])
10. 剪绳子
# 一根长度为n的绳子,剪成m段,n,m >1且为整数,求子段长度最大乘积。贪婪算法
class Solution(object):
def maxproduct(self, a):
if a < 2:
return 0
elif a == 2:
return 1
elif a == 3:
return 2
elif a == 4:
return 4
elif a >= 5:
c = a // 3
r = a % 3
if r == 1:
return (3**(c-1)) * 4
else:
return (3**c) * r
11. 矩阵中的路径是否存在
判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向上下左右移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。
例如下面的矩阵包含了一条 bfce 路径。
from numpy import matrix
class Solution(object):
def __init__(self):
self.rows = None
self.columns = None
def find_root(self, a, m):
self.rows, self.columns = m.shape
for i in range(self.rows):
for j in range(self.columns):
if self.find(m, [i, j], a):
return True
return False
def find(self, data, coordinate, a, ):
x, y = coordinate[0], coordinate[1]
if x < 0 or x >= self.rows:
return False
elif y < 0 or y >= self.columns:
return False
if data[x, y] == a[0]:
if len(a) == 1:
return True
data[x, y] = ''
return self.find(data, [x-1, y], a[1:]) | \
self.find(data, [x+1, y], a[1:]) | \
self.find(data, [x, y-1], a[1:]) | \
self.find(data, [x, y+1], a[1:])
else:
return False
# m = matrix([['a','b','c'],['d','e','f'],['g','h','i']])
# s = Solution()
# print(s.find_root('adefc', m))
12. 进制转换问题
Excel表, A表示第一列, AA表示第27列,AB表示第28列,根据表的字符串索引转换成数字
class Solution(object):
def find_column(self, a):
res = 0
l = len(a) - 1
for i, value in enumerate(a):
res += (26**(l-i)) * (ord(value) - ord('A') + 1)
return res
13. 二进制中1的个数
class Solution(object):
def find_one_num(self, a):
res = 0
while a > 0:
a = a & a-1
res += 1
return res
14. 一条语句判断一个整数是不是2的整数次方
class Solution(object):
def whether_div_two(self, a):
return True if a & a-1 == 0 else False
15. 输入两个整数m,n,判断二进制最少改变多少位能得m->n
先求异或,再统计异或结果1的个数
16. 字符串解压缩
如输入 a = '3[ab]acc',则输出'abababacc'
class Solution(object):
def main(self, a):
res = ""
check_point_num = 0
check_point_str = ""
gate = 0
for i in a:
if i.isdigit():
check_point_num = int(i)
continue
elif i == "[":
gate = 1
continue
elif i == "]":
gate = 2
if gate == 1:
check_point_str += i
elif gate == 2:
res += check_point_str * check_point_num
gate = 0
check_point_num = 0
check_point_str = ""
elif gate == 0:
res += i
return res
17. O(1)时间删除链表节点
class ListNode(object):
def __init__(self):
self.val = None
self.next = None
class Solution(object):
def main(self, head, delete):
if head is None or delete is None:
return None
if delete.next is not None:
next = delete.next
delete.val = next.val
delete.next = next.next
else:
if head is None:
head = None
else:
cur = head
while cur != delete:
cur = cur.next
cur.next = None
return head
18.寻找所有可能子集合
输入[1,2,3],输出[[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
class Solution(object):
def main(self, a):
res = self.find_subset(a)
for i in a:
res += [[i]]
res.append([])
return res
def find_subset(self, a):
if len(a) <= 1:
return []
# 把当前最长加进去
res = [a]
for i,v in enumerate(a):
# 用子集获取最长串
for j in self.find_subset(a[0:i]+a[i+1:]):
if j not in res:
res.append(j)
return res
19. 输出字符串所有可能排列组合
输入'abc',输出['abc', 'acb', 'bac', 'bca', 'cab', 'cba']。
class Solution(object):
def main(self, a):
res = []
if len(a) == 1:
return a
# 把每个都有机会放最前面
for i, v in enumerate(a):
for j in self.main(a[:i] + a[i+1:]):
res.append(v + j)
return res
20. 顺时针打印长宽相等矩阵
class Solution(object):
def __init__(self):
self.rows = 0
self.columns = 0
def main(self, m):
self.rows, self.columns = m.shape
if self.rows == 1 and self.columns == 1:
return m[0, 0]
res = []
x1, y1 = 0, 0
x2, y2 = self.rows-1, self.columns-1
# 打印四个方向规律一样,打印完一圈往里走一圈
while x1 <= x2 and y1 <= y2:
if x1 == x2 and y1 == y2:
res.append(m[x1, y1])
break
for i in range(y1, y2+1):
res.append(m[x1, i])
for i in range(x1+1, x2+1):
res.append(m[i, y2])
for i in range(y1, y2)[::-1]:
res.append(m[x2, i])
for i in range(x1+1, x2)[::-1]:
res.append(m[i, y1])
x1 += 1
x2 -= 1
y1 += 1
y2 -= 1
return res
21. 找到数组中出现次数超过一半的数字
# 时间复杂度O(N), 空间复杂度O(1)
class Solution(object):
def main(self, a):
if len(a) == 1:
return a[0]
# 两两对冲
res = a[0]
num = 1
for i in range(1, len(a)):
if a[i] != res:
num -= 1
if num < 0:
res = a[i]
num = 1
else:
num += 1
return res
22. 数组中连续子数组最大和
# 初始设置sum为0,遍历数组往后加,遇到加之后小于0情况sum清零并且result记录sum上次大于0的值。
# 时间复杂度O(N)
class Solution(object):
def main(self, a):
if len(a) == 1:
return max(a[0])
res = 0
tmp = 0
checkpoint = 0
for i in a:
if checkpoint == 0 and i <= 0:
continue
if i >= 0:
checkpoint += i
else:
if res < checkpoint:
res = checkpoint
if checkpoint + i <= 0:
checkpoint = 0
else:
checkpoint += i
return max(res, checkpoint)
23. 正则表达式匹配
请实现一个函数用来匹配包括 '.' 和 '*' 的正则表达式。模式中的字符 '.' 表示任意一个字符,而 '*' 表示它前面的字符可以出现任意次(包含 0 次)。
class Solution(object):
def main(self, a, pattern):
if len(pattern) == 0:
return ""
res = ""
pass_flag = False
for i, v in enumerate(a):
if res != "":
return res
for j, vv in enumerate(pattern):
if pass_flag:
pass_flag = False
continue
# pattern到头
if j == len(pattern) - 1 and vv == "*":
while True:
if i < len(a) and res[-1] == a[i]:
res += a[i]
i += 1
else:
break
return res
# str到头
if i >= len(a):
res = ""
break
if vv == ".":
res += a[i]
i += 1
elif vv == "*":
while True:
if i >= len(a):
res = ""
break
if res[-1] == a[i]:
res += a[i]
i += 1
else:
break
else:
if vv == a[i]:
res += a[i]
i += 1
else:
if pattern[j+1] == "*":
pass_flag = True
else:
res = ""
break
return res
24. 链表反转
class Solution(object):
def main(self, a):
if a is None or a.next is None:
return a
next = a.next
a.next = None
b = self.main(next)
next.next = a
return b
25. 礼物最大价值
class Solution(object):
def main(self, m):
r, c = m.shape
if r * c == 0:
return 0
for i in range(r):
for j in range(c):
if i + j == 0:
continue
if i == 0:
m[0, j] += m[0, j-1]
elif j == 0:
m[i, 0] += m[i-1, 0]
else:
m[i, j] += max(m[i, j-1], m[i-1, j])
return m[r-1, c-1]
26. 和为n的所有连续正数列
class Solution(object):
def main(self, m):
res = []
for i in range(1, m//2):
s = 0
j = i
while True:
if s < m:
s += i
i += 1
else:
if s == m:
res.append([x for x in range(j, i)])
break
return res
27. 去除字符串字符连续出现次数大于2的
# While每次都遍历一遍字符串消除连续出现次数大于2的,直到有一次遍历没问题则跳出
class Solution(object):
def main(self, a):
while True:
checkpoint_v = ""
checkpoint_i = 0
counter = 0
break_flag = True
for v in a:
if v == checkpoint_v:
counter += 1
continue
if counter > 2:
a = a[:checkpoint_i] + a[checkpoint_i + counter:]
break_flag = False
else:
checkpoint_i = checkpoint_i + counter
checkpoint_v = v
counter = 1
if break_flag:
break
return a
28. 火柴拼成的数字,从一个数移动一根给另外一个数(只能移动一次),移动后最大值?
class Solution(object):
def __init__(self):
# 数字根数映射 & 根数对应最大数字映射
self.counter = {"0":6, "1":2, "2":5, "3":5, "4":4, "5":5, "6":6, "7":3, "8":7, "9": 6}
self.num_to_max_digit = {"2":"1", "3":"7", "4":"4", "5":"5", "6":"9", "7":"8"}
def replace_char(self, s, v, idx):
res = ""
for i in range(len(s)):
if i == idx:
res += v
else:
res += s[i]
return res
def main(self, a):
s = str(a)
if len(s) <= 1:
return a
max_value = a
for i in range(len(s)):
give_ = s[i]
if str(self.counter[give_] - 1) not in self.num_to_max_digit:
continue
give_after = self.num_to_max_digit[str(self.counter[give_] - 1)]
b = self.replace_char(s, give_after, i)
for j, receive_ in enumerate(b):
if j == i:
continue
if str(self.counter[receive_] + 1) not in self.num_to_max_digit:
continue
receive_after = self.num_to_max_digit[str(self.counter[receive_] + 1)]
c = self.replace_char(b, receive_after, j)
if int(c) > max_value:
max_value = int(c)
return max_value
29. 股票可以有一次买入和一次卖出,买入必须在前。求最大收益。
class Solution(object):
def main(self, n):
res = 0
for i in range(1, len(n)):
sell = n[i]
buy = min(n[:i])
profit = sell - buy
if profit > res:
res = profit
return res
30. 圆圈中最后的小孩,n个小孩,第0个开始数到m,无放回出列,再从下一个开始数,最后小孩是都在时候第几个?
class Solution(object):
def main(self, n, m):
if n < 1:
return -1
children = [i for i in range(n)]
start = 1
while len(children) > 1:
final = m + start - 1
if final % len(children) == 0:
children.pop(-1)
start = 1
else:
start = final % len(children)
children.pop(start - 1)
return children[0]
31. n个筛子,求扔出去和为s的概率
class Solution(object):
def main(self, n, s):
if n == 1 and s <= 6:
return 1
elif (n == 1 and s > 6) or (s < n):
return 0
return self.main(n-1, s-1) + self.main(n-1, s-2) \
+ self.main(n-1, s-3) + self.main(n-1, s-4) \
+ self.main(n-1, s-5) + self.main(n-1, s-6)
def result(self, n, s):
res = self.main(n, s)
return res/(6**n)
32. 滑动窗口最大值, 数组a,窗口大小为k
class Solution(object):
def main(self, a, k):
if k > len(a):
return []
res = []
for i in range(0, len(a)-k+1):
res.append(max(a[i:i+k]))
return res
33. 和为s两个数字,有多组选积最小的
class Solution(object):
def main(self, l, s):
product = float('inf')
j = len(l) - 1
for i in range(len(l)):
if j <= 0:
break
if l[i] + l[j] < s:
continue
elif l[i] + l[j] == s:
p = l[i] * l[j]
if p < product:
product = p
else:
j -= 1
return product
34. 一个数组只出现过一次的数,其余均两次
class Solution(object):
def main(self, a):
res = 0
for i in a:
res ^= i
return res
35. 有序数组指定数出现次数
class Solution(object):
def main(self, a, v):
l = 0
r = len(a) - 1
count = 0
while l < r:
m = r // 2
if a[m] < v:
l = m
elif a[m] > v:
r = m
else:
l = m-1
r = m+1
count += 1
while True:
if (l < 0 and r >= len(a)) or (a[l] != v and a[r] != v):
break
if l >= 0 and a[l] == v:
count += 1
l -= 1
if r >= 0 and a[r] == v:
count += 1
r += 1
break
return count
36. 丑数
class Solution(object):
def main(self, n):
if n <= 6:
return n
i2, i3, i5 = 0, 0, 0
res = [1]
cur_num = 1
while cur_num < n:
min_value = min(res[i2]*2, res[i3]*3, res[i5]*5)
res.append(min_value)
while res[i2]*2 <= min_value:
i2 += 1
while res[i3]*3 <= min_value:
i3 += 1
while res[i5]*5 <= min_value:
i5 += 1
cur_num += 1
return res[-1]
21。数字序列某一位数字
数字以123456789101112...格式序列化到一个字符序列中,求任意n位对应的数字,13位对应1
思想:前9位长度9,前99位长度2*(99-9)+9,前999位长度3*(999-99)+99
a = input()
b = int(a)
if b <=9:
print(n)
p = 9
lenn = 2
L = 9
i = 99
while(L<b):
tem = L
lenn1 = lenn
p1 = p
L = lenn*(i-p)+ L
p = i
i = i*10 + 9
lenn = lenn+1
result = int((b-tem)/lenn1)+p1
if int((b-tem)%lenn1) == 0:
result = result%10
else:
chang = (b-tem)%lenn1
tem1 = list(str(result+1))
result = tem1[chang-1]
print(int(result))
22.找出数组中和为s的任意两数字
时间复杂度O(n*log2(n)+n)
# 堆排序或快排对a排序,时间复杂度O(N*log2(N))
def find(a,x):
l= 0
r = len(a)-1
while(l < r):
if a[l]+a[r] > x:
r = r - 1
if a[l]+a[r] < x:
l = l + 1
if a[l]+a[r] == x:
return a[l],a[r]
break