今日頭條研發演算法崗實習生筆試題解答篇_0324晚
python實現,個人理解和總結。有錯誤煩請指正,感謝!!
C++版參見牛客
1.陣列中差為K的數對
題目: 給定n個數,k是差值,計算非重複數字對的個數。
第一行輸入n,k; 第二行輸入n個數
法1:nums中每個元素+k, 得到新陣列new, set(nums)和set(new)取交集
法2:
(1)和法1類似,建立一個dic儲存nums中元素出現的個數;
(2)然後遍歷雜湊表中的數字, 如果k為0且該數字出現的次數大於1,則結果res自增1;
(3)如果k不為0,且用當前數字加上k後得到的新數字也在陣列中存在,則結果res自增1法3:時間換空間。給陣列排序,然後使用雙指標。遍歷排序後的陣列,然後在當前數字之後找第一個和當前數之差不小於k的數字,若這個數字和當前數字之差正好為k,那麼結果res自增1,然後遍歷後面的數字去掉重複數字。
程式碼:
def findPairs1(nums, k):
new = [num+k for num in nums]
return len(set(nums)&set(new))
def findPairs2(nums, k):
dic = {}
for num in nums:
if num in dic:
dic[num] += 1
else:
dic[num] = 1
res = 0
for num in dic:
if k == 0 and dic[num] > 1:
res += 1
elif k > 0 and num + k in dic:
res += 1
return res
def findPairs3(nums, k):
res = 0
nums.sort()
i = 0
while i < len(nums):
j = i+1 # i後面的第一個數
while j < len(nums) and nums[j] - nums[i] < k: # 找到第一個和當前數之差≥k的數字
j += 1
if j < len(nums) and nums[j] - nums[i] == k:
res += 1
while i < len(nums)-1 and nums[i] == nums[i+1]: # 去重
i += 1
i += 1
return res
2.求函式呼叫次數
題目: 定義兩個字串變數:s和m,再定義兩種操作:
① m = s; s = s + s; ② s = s + m
假設s初始化如下:s = “a”, m = s;
求最小的操作步驟數, 可以將s拼接到長度等於n。
示例:
輸入6,輸出3;輸入5,輸出4;輸入7,輸出6;輸入9,輸出4。
解法:
法1:(遞迴)從頭開始考慮選用①或②
法2:(BFS)模擬層次遍歷,每一步兩條路走
可以轉換為 ① m = s; s = s + m; ② s = s + m ——> 複製操作m=s和貼上操作s=s+m
??不懂哎
程式碼:
def get_minpot(s,m,n):
cnt = 0
# 截止條件
if s == n:
return cnt
if s > n:
return n
return min(get_minpot(s*2,s,n), get_minpot(s+m,m,n)) + 1
def countStep1(n):
return get_minpot(1,1,n)
def countStep2(n):
step = 0
queue = [(1,1,step)] # 初始化為(s,m)
while queue:
size = len(queue)
for i in range(size):
temp = queue.pop(0)
if temp[0] == n:
return step
# 採用①
if temp[0]*2 <= n:
queue.append((temp[0]*2,temp[0]))
# 採用②
if temp[0] + temp[1] <= n:
queue.append((temp[0] + temp[1],temp[1]))
step += 1 # 每遍歷一層,步數+1
3. 輸出666
程式碼:
nn = [
[
'66666',
'6...6',
'6...6',
'6...6',
'66666'
],[
'....6',
'....6',
'....6',
'....6',
'....6'
],[
'66666',
'....6',
'66666',
'6....',
'66666'
],[
'66666',
'....6',
'66666',
'....6',
'66666'
],[
'6...6',
'6...6',
'66666',
'....6',
'....6'
],[
'66666',
'6....',
'66666',
'....6',
'66666'
],[
'66666',
'6....',
'66666',
'6...6',
'66666'
],[
'66666',
'....6',
'....6',
'....6',
'....6'
],[
'66666',
'6...6',
'66666',
'6...6',
'66666'
],[
'66666',
'6...6',
'66666',
'....6',
'66666'
]
]
if __name__ == '__main__':
n = int(input())
for _ in range(n):
s = input() # 比如輸入6+6
s = str(eval(s)) # 求得s='12'
ans = [[] for _ in range(5)] # 輸出5行
for i in s:
x = int(i)
ans[0].append(nn[x][0])
ans[1].append(nn[x][1])
ans[2].append(nn[x][2])
ans[3].append(nn[x][3])
ans[4].append(nn[x][4])
for i in range(5):
print('..'.join(ans[i]))
4.Magic
解法:
都排序,比較平均值大小,均值大A的往均值小的B放數(數a大於B均值,且小於A均值)
程式碼:
def magic(A, B):
A = sorted(A)
B = sorted(B)
if sum(set(A))/len(A) < sum(set(B))/len(B):
A, B = B, A
cnt = 0
av_A = sum(set(A))/len(A)
av_B = sum(set(B))/len(B)
for i in range(len(A)):
if len(A) <= 1:
return cnt
if A[i] > av_B and A[i] < av_A:
B = set(B)
B.add(A[i])
A.pop(i)
print('A:',A)
print('B:',B)
cnt += magic(A, B)+1
break
return cnt
5.跳板遊戲
題目: 已知空中有N個高度不同的跳板,小T剛開始在高度為0的地方,每次跳躍可以選擇和直接當前..
解法:
注意:不一定每次都要貪心選最好的跳板
比如1 3 4 6,h=2,貪心只能0-2-6,而實際上可以0-2-4-8
解法:每層都儲存跳1,2..H高度的結果,層次遍歷
程式碼:
# (×)考慮不周全的程式碼
N = [1,3,6]
K = 3 # K次
H = 2 # 高度差
start = 0
N.sort()
for _ in range(K):
for i in range(len(N)):
if N[i] - start > H or len(N) == 1 and N[i] - start <= H: # 找到第一個大於的
start = 2 * N[i-1] - start
N.pop(i-1)
break
print(start)
# 參照牛客改的Python版,跑起來好慢...
N = [1,3,6]
K = 4 # K次
H = 2 # 高度差
vis = [0] * int(1e8)
# 建立一個稀疏向量,儲存臺階的位置
a = [0] * int(1e8)
for n in N:
a[n] = 1
start = 0
step= 0
q = [(start,step)] # (位置,到該位置要跳多少下)
res = 0 # 高度
while q:
start, step = q.pop(0)
if step > K: # 此處判斷>K,是想讓K次的最高位置都儲存了
break
if start > res:
res = start
for h in range(1,H+1): # 一次跳多高
# 位置有跳板,&可以跳到未被訪問的位置
if a[start+h] and not vis[start+2*h]:
vis[start+2*h] = True # 之前跳到過這個位置,不用再儲存了
q.append((start+2*h,step+1))
# 5,10,11 H=6,K=4可以回跳,最高可以到14
if start-2*h>0 and a[start-h] and not vis[start-2*h]:
vis[start+2*h] = True # 之前跳到過這個位置,不用再儲存了
q.append((start-2*h,step+1))
print(res)