Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8944303
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T11:59:33+00:00 2026-06-15T11:59:33+00:00

Based on that answer here are two versions of merge function used for mergesort.

  • 0

Based on that answer here are two versions of merge function used for mergesort.
Could you help me to understand why the second one is much faster.
I have tested it for list of 50000 and the second one is 8 times faster (Gist).

def merge1(left, right):
    i = j = inv = 0
    merged = []
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            merged.append(left[i])
            i += 1
        else:
            merged.append(right[j])
            j += 1
            inv += len(left[i:])

    merged += left[i:]
    merged += right[j:]
    return merged, inv

.

def merge2(array1, array2):
    inv = 0
    merged_array = []
    while array1 or array2:
        if not array1:
            merged_array.append(array2.pop())
        elif (not array2) or array1[-1] > array2[-1]:
            merged_array.append(array1.pop())
            inv += len(array2)
        else:
            merged_array.append(array2.pop())
    merged_array.reverse()
    return merged_array, inv

Here is the sort function:

def _merge_sort(list, merge):
    len_list = len(list)
    if len_list < 2:
        return list, 0
    middle = len_list / 2
    left, left_inv   = _merge_sort(list[:middle], merge)
    right, right_inv = _merge_sort(list[middle:], merge)
    l, merge_inv = merge(left, right)
    inv = left_inv + right_inv + merge_inv
    return l, inv

.

import numpy.random as nprnd
test_list = nprnd.randint(1000, size=50000).tolist()

test_list_tmp = list(test_list) 
merge_sort(test_list_tmp, merge1)

test_list_tmp = list(test_list) 
merge_sort(test_list_tmp, merge2)
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T11:59:33+00:00Added an answer on June 15, 2026 at 11:59 am

    Similar answer as kreativitea‘s above, but with more info (i think!)

    So profiling the actual merge functions, for the merging of two 50K arrays,

    merge 1

             311748 function calls in 15.363 seconds
    
       Ordered by: standard name
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            1    0.001    0.001   15.363   15.363 <string>:1(<module>)
            1   15.322   15.322   15.362   15.362 merge.py:3(merge1)
       221309    0.030    0.000    0.030    0.000 {len}
        90436    0.010    0.000    0.010    0.000 {method 'append' of 'list' objects}
            1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    

    merge2

             250004 function calls in 0.104 seconds
    
       Ordered by: standard name
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            1    0.001    0.001    0.104    0.104 <string>:1(<module>)
            1    0.074    0.074    0.103    0.103 merge.py:20(merge2)
        50000    0.005    0.000    0.005    0.000 {len}
       100000    0.010    0.000    0.010    0.000 {method 'append' of 'list' objects}
            1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
       100000    0.014    0.000    0.014    0.000 {method 'pop' of 'list' objects}
            1    0.000    0.000    0.000    0.000 {method 'reverse' of 'list' objects}
    

    So for merge1, it’s 221309 len, 90436 append, and takes 15.363 seconds.
    So for merge2, it’s 50000 len, 100000 append, and 100000 pop and takes 0.104 seconds.

    len and append pop are all O(1) (more info here), so these profiles aren’t showing what’s actually taking the time, since going of just that, it should be faster, but only ~20% so.

    Okay the cause is actually fairly obvious if you just read the code:

    In the first method, there is this line:

    inv += len(left[i:])
    

    so every time that is called, it has to rebuild an array. If you comment out this line (or just replace it with inv += 1 or something) then it becomes faster than the other method. This is the single line responsible for the increased time.

    Having noticed this is the cause, the issue can be fixed by improving the code; change it to this for a speed up. After doing this, it will be faster than merge2

    inv += len(left) - i
    

    Update it to this:

    def merge3(left, right):
        i = j = inv = 0
        merged = []
        while i < len(left) and j < len(right):
            if left[i] <= right[j]:
                merged.append(left[i])
                i += 1
            else:
                merged.append(right[j])
                j += 1
                inv += len(left) - i
    
        merged += left[i:]
        merged += right[j:]
        return merged, inv
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have two issues here, the second one is irrelevant if the first one
For the following question, I am looking for an answer that is based on
THE ANSWER THAT WORKED FOR ME BASED ON AN ANSWER GIVEN while($post = mysql_fetch_array($tags))
I have a 2D-array that I want to sort based on the second column.
I have a follow up question on the accepted answer given here: Two models
I wrote method that return random number between two given numbers. Here it's header:
Here are two functions that split iterable items to sub-lists. I believe that this
Based on Martin Smith's answer here , I've been trying to use a very
Based on some answers to this question it appears that +alloc does some behind-the-scenes
We have a mass emailing tool (.net based) that we developed in house. html

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.