文档内容
2021 届秋招——华为数据分析笔试
1.矩阵的旋转
一个nXn阶的矩阵,第一个位置上的人喊1,延矩阵顺时针报号依次
加1,若十位是奇数且各位是7,则为特种兵,请返回特种兵的位置。
思路:基于第三题的思想:螺旋打矩阵
递归解决:
螺旋矩阵用二维数组表示,坐标(x,y),即(x轴坐标,y轴坐标)
顺时针螺旋的方向是->右,下,左,上,用数值表示即是x加1格(1,0),y加1格(0,1),x减1格
(-1,0),y减1格(0,-1)
坐标从(0,0)开始行走,当超出范围或遇到障碍时切换方向
cycle(iterable)
创建一个迭代器,对iterable中的元素反复执行循环操作,内部会生成iterable中的
元素的一个副本,此副本用于返回循环中的重复项。
cycle(“abc”) #重复序列的元素,既a, b, c, a, b, c …
使用for或者__next__()调用里面的元素。
import itertools
import numpy as np
#递归解决
def spiral(m,n):
ans=[]#存储矩阵
result=[]#存储特种兵的索引
_status = itertools.cycle(['right','down','left','up'])#用于状态周期
性的切换
_movemap = {
'right':(1,0),
'down':(0,1),
'left':(-1,0),
'up':(0,-1),
}
pos2no = dict.fromkeys([(x,y) for x in range(m) for y in range(n)])
#{(0, 0): None,
# (0, 1): None,
# (1, 0): None,
# ....
# (m-1, n-1): None}
_pos = (0,0)#当前位置
_st = next(_status)#⽤next()函数来获取迭代器的下⼀条数据for i in range(1,m*n+1):
_oldpos = _pos#旧位置
#_pos=(0,0),_movemap['right']=(1,0)
#tuple(map(sum,zip((2,3),(3,4)))):(5,7)实现两个tuple对应位置相加
_pos = tuple(map(sum,zip(_pos,_movemap[_st])))#根据状态下一次该到
的位置
if (_pos not in pos2no) or (pos2no[_pos]):#当超出范围或遇到障碍时
(此位置已有值)切换方向
_st = next(_status)#切换下一次的状态
_pos = tuple(map(sum,zip(_oldpos,_movemap[_st])))
pos2no[_oldpos] = i
#根据口号规则找出特种兵的位置
if i//10%2!=0 and i%10==7:
result.append(_oldpos[::-1])
for i in range(m):
ans1=[]
for j in range(n):
ans1.append(pos2no[(j,i)])
ans.append(ans1)
return ans, result
a,b=spiral(10,10)
print('特种兵:',b)
print('矩阵:')
a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43思想2:基于第2题的思想:顺时针打印矩阵
1.先创建一个矩阵使得矩阵的每一位置上的值等于索引,A[0][3]=3,A[1][3]=13
2.再算出顺时针的的列表,对应的口号是1:m*n+1
3.判断i口号是否满足特征兵的条件
4.满足的对值进行索引转化:**此处有问题,对于不同的m,n转化规则没有很好的找到
def printMatrix( matrix):
# write code here
result = []
while(matrix):
result+=matrix.pop(0)#抛出第一行
if not matrix or not matrix[0]:
break
matrix = turn(matrix)
return result
#旋转矩阵使得第一行为所需元素
def turn(matrix):
num_r = len(matrix)
num_c = len(matrix[0])
newmat = []
for i in range(num_c):
newmat2 = []
for j in range(num_r):
newmat2.append(matrix[j][i])newmat.append(newmat2)
newmat.reverse()#行颠倒交换
return newmat
if __name__ == '__main__':
#1.先创建一个矩阵
m=int(input())
n=int(input())
matrix=[]
for i in range(0,m):
matrix1=[]
for j in range(0,n):
matrix1.append(10*i+j)
matrix.append(matrix1)
print(matrix)
#再算出顺时针的的列表
result=printMatrix( matrix)
ss=len(result)+1
ans=[]
for i in range(1,ss):
#3.判断i口号是否满足特征兵的条件
if i//10%2!=0 and i%10==7:
s=result[i-1]
#.满足的对值进行索引转化
s1=s//m
s2=s%m
ans.append([s1,s2])
print(ans)
1
2
3
4
5
6
7
8
9
10
11
12
13
14 15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
452.顺时针打印矩阵
类似题1:题目20顺时针打印矩阵
3.螺旋矩阵
类似题目2:
思路:
1.构建斐波那契数列
2.递归解决:螺旋矩阵用二维数组表示,坐标(x,y),即(x轴坐标,y轴坐标)
顺时针螺旋的方向是->右,下,左,上,用数值表示即是x加1格(1,0),y加1格(0,1),x减1格
(-1,0),y减1格(0,-1)
坐标从(0,0)开始行走,当超出范围或遇到障碍时切换方向
import itertools
import numpy as np
#1.构建斐波那契数列
def Fibonacci(n):
if n <= 0:
return 0
a = b = 1
res=[1,1]
for i in range(2,n):
a,b=b,a+b
res.append(b)
return res
#2.递归解决
def spiral(n,arr):
_status = itertools.cycle(['right','down','left','up'])#用于状态周期
性的切换
_movemap = {
'right':(1,0),
'down':(0,1),
'left':(-1,0),
'up':(0,-1),
}
pos2no = dict.fromkeys([(x,y) for x in range(n) for y in range(n)])
#{(0, 0): None,
# (0, 1): None,
# (1, 0): None,
# (1, 1): None}
_pos = (0,0)
_st = next(_status)#⽤next()函数来获取迭代器的下⼀条数据
#每次对旧位置赋值,并判断下一个位置怎么走
for i in range(1,n*n+1):
_oldpos = _pos
#_pos=(0,0),_movemap[_st]=(1,0)
#zip():0,1;0,0,对应位置求和
_pos = tuple(map(sum,zip(_pos,_movemap[_st])))#根据状态进行移动
(1,0)if (_pos not in pos2no) or (pos2no[_pos]):#当超出范围或遇到障碍时
(位置上已有数字)切换方向
_st = next(_status)
_pos = tuple(map(sum,zip(_oldpos,_movemap[_st])))
pos2no[_oldpos] = arr[i-1]
return pos2no
def display_spiral(n):
ans=[]
arr=Fibonacci(n)
n1=int(np.sqrt(n))
pos2no = spiral(n1,arr)
for i in range(n1):
ans1=[]
for j in range(n1):
ans1.append(pos2no[(j,i)])
ans.append(ans1)
return ans
matrix=display_spiral(9)
print('螺旋矩阵:',matrix)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
4.堆积木两个数字字符串a,b,a是不超过10位,b是1-9位,a代表下面已有
的积木,b代表上面落下的积木,两者尽可能的抵消,请问最终留下最
少的行数。
思路:
1.判断a,b字符串的长度
2.通过两个字符串相加(需要移动根据1的条件),使得最大值-最小值的差最小
2.1当a/b长度为1时,只需要找出b/a最小元素的位置+a/b,在计算新列表的最大值-最小
值
2.2当a与b的长度相等时,两者直接对应元素相加,在计算新列表的最大值-最小值
2.3当a,b长度都大于1,且不相等时,需要来回移位,找出最小的那个
#输入
#a=[2,2,0,2]
#b=[2]
#输出:0
aa = list(map(int, input().split()))
bb =list(map(int, input().split()))
a=[]
b=[]
for i in range(len(aa)):
a.append(int(aa[i]))
for i in range(len(bb)):
b.append(int(bb[i]))
def listsum(a,b):
for i in range(len(a)):
a[i]=a[i]+b[i]
return a
def fun(a,b):
sb=len(b)
sa=len(a)
#2.0特殊情况
if not b:
return max(a)
if not a:
return max(b)
if not a and not b:
return 0
#2.1长度为1
if sb==1:
c=min(a)sb=a.index(c)
a[sb]=c+b[0]
return max(a)-min(a)
if sa==1:
c=min(b)
sb=b.index(c)
b[sb]=c+a[0]
return max(b)-min(b)
#2.2长度相等
if sb==sa:
a=listsum(a,b)
return max(a)-min(a)
#2.3长度大于1,且不相等
if sb>1 and sa>1 and sb1 and sa>1 and sb>sa:
ans=[]
for i in range(sb-sa+1):
c=listsum(b[i:i+sa],a)
c=c+b[(i+2):]+b[0:i]
ans.append(max(c)-min(c))
return min(ans)
print(fun(a,b))
1
2
3
4
5
6
7
8
9
10
11
12
13 14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 55
56
57