1. 程式人生 > >今日頭條研發演算法崗實習生筆試題解答篇_0324晚

今日頭條研發演算法崗實習生筆試題解答篇_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)]  # 輸出5for 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)