2020網易校招 算法工程師崗位 大題第一道——小易把1到n的所有排列按字典序列排成一排

2019年8月3日,網易校招 算法工程師崗位 大題第一道 

剛纔筆試,一道題沒做出來, 第一道題,寫出來了,時間複雜度還太大,測試超時了。很不甘心,於是交卷後又重新思考了一下。其實很簡單

 

題目:有一天,小易把1到n的所有排列按字典序列排成一排。小易從中選出了一個排列,假設它是正數第Q個排列,小易希望你能回答他倒數第Q個排列是什麼。

例如1到3的所有排列是:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

若小易選出的排列是 1 2 3 ,則Q=1,而你應該輸出排列3 2 1

輸入描述:

第一行數字n,表示排列長度接下來一行n個數字,表示選出的排列1<= n <= 300000

輸出描述:

一行n個數字,表示所求的排列。

示例1:

輸入

3
1 2 3

輸出:

3 2 1

示例2:

輸入

5
3 1 5 2 4

輸出:

3 5 1 4 2 

方法一:

這是我筆試時寫的。如果按照題目的思路,你需要先知道所有排列的可能性,然後安裝索引Q輸出。

也就是

1捕獲輸入;

2對所給輸入進行排序,把3 1 5 2 4 重新排序成 1 2 3 4 5  ,12345也是所有排列組合的第一種

3 羅列所有排列組合的可能性,12345、12354、12435、12453這種

4計算Q,你要知道3 1 5 2 4 是所有排列組合中的第幾種,這裏Q是第53,索引是52.

5輸出結果,然後輸出【所有排列可能性】中倒數第53個

這裏插一句,在線筆試題用的牛客網,編程時是可以切換頁面的。我們不妨把輸入功能寫成通用的方法,存放在自己的工具包中,下次使用,直接粘貼,很方面。(用我GitHub上代碼時能不能點個星)

下面是python代碼。完全可以不用看,直接看方法2

# https://github.com/zihaozhang9/utils/blob/master/OnlineExam.py

def decIn(Str_in):
    line = Str_in.strip().split()
    try:
        line = [int(i) for i in line]
    except:
        print('input error')
        exit()
    return line
def read1(chang):
    tmp = decIn(input())
    while len(tmp)<chang:
        tmp = decIn(input())
    return tmp
    
def swap(t1, t2):
    return t2, t1

#讀取輸入
n = read1(1)[0]
line1 = read1(1)
linesort = line1.copy()
linesort.sort()

#獲取所有排列組合情況
lines = []
while True:
    lines.append(linesort.copy())
    j = n-2
    while linesort[j]>=linesort[j+1]:
        j = j-1
    if j<0: break
    
    k = n -1 
    while (k>j)and(linesort[k]<=linesort[j]):
        k = k-1
    linesort[k],linesort[j]=swap(linesort[k],linesort[j])
    
    l = j+1
    r = n-1
    while l<r:
        linesort[l],linesort[r]=swap(linesort[l],linesort[r])
        l = l+1
        r = r-1
#計算Q
Q=0
for idx,i in enumerate(lines):
    if line1 == i:
        Q = idx
        break
#給出倒數第Q的結果
Q=Q+1
for i in lines[-Q]:
    print(i,end=' ')
        

結果當然是可以運行, 但時間複雜度太高,測試用例只通過40%。

方法二,五行代碼

可以將所有的排列組合看成一種樹結構。【第Q中排列】和【倒數第Q種】排列其實是對稱的。我們不需要知道所有的排列組合情況,我們只需要根據當前順序對稱過去就好了。

代碼-核心代碼其實就5行。不過這是考完之後想到的,沒測試過,不一定對。


def decIn(Str_in):
    line = Str_in.strip().split()
    try:
        line = [int(i) for i in line]
    except:
        print('input error')
        exit()
    return line
def read1(chang):
    tmp = decIn(input())
    while len(tmp)<chang:
        tmp = decIn(input())
    return tmp
    
n = read1(1)[0]
line_in = read1(1)
linesort = line_in.copy()
linesort.sort()
#或得到對稱的元素
def getflip(line,e):
    idx = line.index(e)+1
    return line[-idx]
#直接打印結果
for e in line_in:
    print( getflip(linesort,e), end=' ')

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章