文档内容
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
2021
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]=132.再算出顺时针的的列表,对应的口号是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
56
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
3233
34
35
36
37
38
39
40
41
42
43
44
45
2.顺时针打印矩阵
类似题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
2324
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
5051
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
78
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
3435
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
—————————————