Merge Sort

Merge sort-ը ամենարագ տեսակավորման ալգորիթմներից մեկն է։ Շատ ծրագրեր արտադրական միջավայրում օգտագործում են Merge sort-ի որևէ տարբերակը։ Մենք արդեն դիտարկել ենք ալգորիթմներ, որոնք աշխատում են քառակուսի ժամանակային բարդությամբ , օրինակ՝ Bubble sort (Պղպջակային տեսակավորում) կամ Selection sort (Ընտրությամբ տեսակավորում)։ Merge sort-ը շատ ավելի արագ է, քան բոլոր քառակուսի ժամանակային բարդությամբ տեսակավորումները և աշխատում է բարդությամբ։
Video preview
Merge sort-ը «Բաժանիր և տիրիր (Divide & Conquer)» մոտեցման ալգորիթմ է, որը ռեկուրսիվ կերպով տեսակավորում է զանգվածի միջակայքերը և ապա միացնում (merge) դրանք։ Ալգորիթմի հիմնական մասն այն արդյունավետ մեխանիզմն է, որ երկու տեսակավորված զանգվածները միացնում է մեկ տեսակավորված զանգվածի մեջ։ Ալգորիթմը աշխատանքի ընթացքում զանգվածը բաժանում է երկու մասի։ Այնուհետև ռեկուրսիվ կերպով տեսակավորում է առաջին մասը, հետո ռեկուրսիվ տեսակավորում է երկրորդ մասը, և վերջում միացնում է (merge) երկու տեսակավորված մասերը մեկ ընդհանուր տեսակավորված զանգվածում։
def merge(a, b):
    i, j, res = 0, 0, []                # i-ի և j-ի ինդեքսները a-ի և b-ի համար, իսկ res-ը արդյունքների զանգվածն է
    while i < len(a) or j < len(b):     # Քանի դեռ կան մնացած էլեմենտներ
        ai = a[i] if i < len(a) else float('inf')
        bj = b[j] if j < len(b) else float('inf')

        if ai < bj:                     # Եթե a[i] < b[j], ապա վերցնենք a[i]
            res.append(ai)              # Ավելացնել a[i]-ը արդյունքների մեջ
            i += 1                      # Անցնել հաջորդ էլեմենտին
        else:                           # Եթե a[i] >= b[j], ապա վերցնել b[j]
            res.append(bj)              # Ավելացնել b[j]-ը արդյունքների մեջ
            j += 1                      # Անցնել հաջորդ էլեմենտին
    return res


def merge_sort(a):
    if len(a) <= 1:                     # Եթե տեսակավորելու բան չկա
        return a                        # Ուղղակի վերադարձնել նույն զանգվածը

    l = merge_sort(a[: len(a) // 2])    # Տեսակավորել ձախ մասը
    r = merge_sort(a[len(a) // 2:])     # Տեսակավորել աջ մասը
    return merge(l, r)
Յուրաքանչյուր փուլում ալգորիթմը վերցնում է զանգվածը, բաժանում այն երկու մասի, առանձին տեսակավորում յուրաքանչյուր մասը և միացնում (merge) արդյունքը։ Նկատեք, որ մինչ այժմ դիտարկված բոլոր ալգորիթմները տեսակավորում էին տեղում (in-place), այսինքն՝ փոփոխում էին նույն զանգվածը։ Իսկ Merge sort-ն ամեն փուլում ստեղծում է նոր զանգված։ Տեղում Merge sort գրելը բավականին բարդ կլինի։ Կարո՞ղ եք բացատրել, թե ինչու։
Եկեք քայլ առ քայլ ուսումնասիրենք ալգորիթմի աշխատանքը մի քանի զանգվածների վրա:
[4, 1, -1, 0, 2, 8]
  1. merge_sort([4, 1, -1, 0, 2, 8]):
    1. merge_sort([4, 1, -1])
    2. merge_sort([0, 2, 8])
  1. merge_sort([4, 1, -1]):
    1. merge_sort([4]) → return [4]
    2. merge_sort([1, -1])
  1. merge_sort([1, -1]):
    1. merge_sort([1]) → return [1]
    2. merge_sort([-1]) → return [-1]
  1. Back to merge_sort([1, -1]) → return [-1, 1]
  1. Back to merge_sort([4, 1, -1]) → return [-1, 1, 4]
  1. merge_sort([0, 2, 8]):
    1. merge_sort([0]) → return [0]
    2. merge_sort([2, 8])
  1. merge_sort([2, 8]):
    1. merge_sort([2]) → return [2]
    2. merge_sort([8]) → return [8]
  1. Back to merge_sort([2, 8]) → return [2, 8]
  1. Back to merge_sort([0, 2, 8]) → return [0, 2, 8]
  1. Back to merge_sort([4, 1, -1, 0, 2, 8]) → return [-1, 0, 1, 2, 4, 8]

Առաջադրանք

Տրված է n ամբողջ թվերից բաղկացած զանգված։ Պահանջվում է տեսակավորել այն նվազման կարգով, օգտագործելով Merge Sort ալգորիթմը։

Մուտք

Մուտքի առաջին տողում տրված է մեկ ամբողջ թիվ n (1 ≤ n ≤ 100 000)։
Հաջորդ տողում տրված են n ամբողջ թվեր , որոնց ամբողջականությունը գտնվում է հատվածում :

Ելք

Ծրագիրը պետք է տպի n ամբողջ թվերը նվազման կարգով (բացատով բաժանված):

Օրինակներ

Мուտք
Ելք
4 7 4 9 1
9 7 4 1
5 -4 8 2 -3 6
8 6 2 -3 -4
 

Constraints

Time limit: 5 seconds

Memory limit: 512 MB

Output limit: 10 MB

To check your solution you need to sign in
Sign in to continue