Python GeeksForGeeks arrange array alternatively problem

Question:

I am attempting a Python practice problem on GeeksForGeeks, but my code raises IndexError every time.

The problem is as follows:

Given a sorted array of positive integers arr, and an integer n which represents the length of arr, your task is to rearrange the array elements alternatively i.e first element should be max value, second should be min value, third should be second max, fourth should be second min and so on.
Note: Modify the original array itself.

My code however raises IndexError: list index out of range

Here is my code:

def rearrange(arr, n):
        arr1,arr2 = sorted(arr[:(n//2)]), sorted(arr[(n//2):],reverse=True)
        arr.clear()
        for i in range(n):
            arr.append(arr2[0]); arr2.pop(0)
            arr.append(arr1[0]); arr1.pop(0)

Here is the error:

File "/home/4c7d0350d40e21b84be527508f21cb47.py", line 9, in rearrange
    arr.append(arr2[0]); arr2.pop(0)
IndexError: list index out of range

I don’t understand why this is happening. Can anyone provide an explanation?

Asked By: 433MEA

||

Answers:

An index out of range means you are trying to access an item in your list at an index that does not exist.

Answered By: 00robinette

In your code, both arr1 and arr2 are initialized with a length of n//2. In your for loop:

for i in range(n):
    arr.append(arr2[0]); arr2.pop(0)
    arr.append(arr1[0]); arr1.pop(0)

You access the first element and remove the first element n times! This requires there to be n elements in arr1 and arr2, but there are not this many. So, you keep trying to access the 0 index element of the array even after the array is empty, which causes this error.

Answered By: linger1109

Disclaimer – this is not a direct answer to OP’s question, since it’s been addressed really clearly. But I’m tempting to share a reference implementation:
(which I think is more elegant – because it use the deque -operations at both end is O(1))

Limitation in this case, it assumes the array/list is even-sized, otherwise it won’t work. Thanks @Kelly’s reminder.


from collections import deque
L = deque(nums)
print(L)
#deque([1, 2, 3, 4, 5, 6, 7, 8, 9])

while L:
    print(L.pop(), L.popleft())

    
9 1
8 2
7 3
6 4

# it will hit this error at the end:
#  IndexError: pop from an empty deque    # it's easier to convert it to a function and try-except ...      (leave as an exercise) 

As @KellyBundy is interesting in the timing.

Thanks for the opportunity of comparison.
about the complete code, here it goes:

from collections import deque

def rearr(A, n):
    dq = deque(A)
    A[:] = list()

    while dq:
        A.append(dq.pop())
        A.append(dq.popleft())

    return A

# sample 
A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(rearr(A, 10))                   # would like to find out the running time...

Updates – final conclusion.

Per @Kelly quick timing testing proves that slicing is faster than the deque because the latter involved expensive function calls. Thanks!

from timeit import timeit
from collections import deque

def Deque(A):
    n = len(A)
    dq = deque(A)
    A[:] = list()
    while dq:
        A.append(dq.pop())
        A.append(dq.popleft())

def Slice(a):
  n = len(a)
  c = n // 2
  b = n - c
  a[::2], a[1::2] = a[:~b:-1], a[:c]

funcs = Deque, Slice

for n in range(0, 11, 2):
  for f in funcs:
    a = list(range(n))
    f(a)
    print(a, f.__name__)

for _ in range(3):
  print()
  for func in funcs:
    xss = [list(range(n)) for n in range(1000, 1008, 2)]
    t = timeit(lambda: [func(xs) for xs in xss], number=1)
    print(t * 1e6, func.__name__)

Output:

] Deque
[] Slice
[1, 0] Deque
[1, 0] Slice
[3, 0, 2, 1] Deque
[3, 0, 2, 1] Slice
[5, 0, 4, 1, 3, 2] Deque
[5, 0, 4, 1, 3, 2] Slice
[7, 0, 6, 1, 5, 2, 4, 3] Deque
[7, 0, 6, 1, 5, 2, 4, 3] Slice
[9, 0, 8, 1, 7, 2, 6, 3, 5, 4] Deque
[9, 0, 8, 1, 7, 2, 6, 3, 5, 4] Slice

458.1600078381598 Deque
27.825008146464825 Slice

448.2280055526644 Deque
25.852001272141933 Slice

446.4329977054149 Deque
26.448993594385684 Slice
Answered By: Daniel Hao
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.