I am working on a problem about building a min heap from an array. I have 2 approaches - the first is recursion and the second is using a while loop. The recursion approach passed the tests on the online grader, but the while loop version doesn't seem to work. I generated some random stress tests in my code below and found that the 2 methods gave different answers as well.
May I know what's the mistake in my second method? The question is as follows:
Input Format. The first line of the input contains single integer 𝑛. The next line contains 𝑛 space-separated integers 𝑎𝑖.
Constraints. 1 ≤ 𝑛 ≤ 100 000; 0 ≤ 𝑖, 𝑗 ≤ 𝑛 − 1; 0 ≤ 𝑎0, 𝑎1,..., 𝑎𝑛−1 ≤ 109. All 𝑎𝑖 are distinct.
Output Format. The first line of the output should contain single integer 𝑚 — the total number of swaps.
𝑚 must satisfy conditions 0 ≤ 𝑚 ≤ 4𝑛. The next 𝑚 lines should contain the swap operations used to convert the array 𝑎 into a heap. Each swap is described by a pair of integers 𝑖, 𝑗 — the 0-based indices of the elements to be swapped. After applying all the swaps in the specified order the array must become a heap, that is, for each 𝑖 where 0 ≤ 𝑖 ≤ 𝑛 − 1 the following conditions must be true:
- If 2𝑖 + 1 ≤ 𝑛 − 1, then 𝑎𝑖 < 𝑎2𝑖+1.
- If 2𝑖 + 2 ≤ 𝑛 − 1, then 𝑎𝑖 < 𝑎2𝑖+2.
Note that all the elements of the input array are distinct. Note that any sequence of swaps that has length at most 4𝑛 and after which your initial array becomes a correct heap will be graded as correct.
My code:
# python3
from random import randint
swaps = []
def sift_down(i, n, data):
min_index = i
left_child = 2*i + 1
right_child = 2*i + 2
if left_child < n and data[left_child] < data[min_index]:
min_index = left_child
if right_child < n and data[right_child] < data[min_index]:
min_index = right_child
if i != min_index:
swaps.append([i, min_index])
data[i], data[min_index] = data[min_index], data[i]
sift_down(min_index, n, data)
def build_heap(data):
n = len(data)
for i in range(n//2, -1, -1):
sift_down(i, n, data)
return swaps
# wrong answer using while loop instead of recursion
def build_heap2(data):
swap = []
for i in range(len(data)-1, 0, -1):
current_node = i
prev_node = i // 2 if i % 2 != 0 else i // 2 - 1
while data[prev_node] > data[current_node] and current_node != 0:
swap.append((prev_node, current_node))
data[prev_node], data[current_node] = data[current_node], data[prev_node]
current_node = prev_node
prev_node = current_node // 2 if current_node % 2 != 0 else current_node // 2 - 1
return swap
def main():
# n = int(input())
# data = list(map(int, input().split()))
# assert len(data) == n
while True:
n = randint(1, 100000)
data = []
data2 = []
for i in range(n):
data.append(randint(0, 10^9))
data2 = data.copy()
swaps = build_heap(data)
swaps2 = build_heap2(data2)
if swaps != swaps2:
print("recursion")
print(data[0], len(data), len(swaps))
print("loop:")
print(data2[0], len(data2), len(swaps2))
break
else:
print("success")
swaps = build_heap(data)
print(len(swaps))
for i, j in swaps:
print(i, j)
if __name__ == "__main__":
main()