pythonalgorithmduplicatesinfinite-loop

Cyclic Sort Infinite Loop in LeetCode "Set Mismatch" Problem


I am trying to solve the Set Mismatch problem using Cyclic Sort in Python. The problem statement is as follows:


Problem Statement

You have a set of integers s, which originally contains all numbers from 1 to n. Unfortunately, one of the numbers got duplicated, and another number is missing. Given an integer array nums representing the current state of the set, find the number that occurs twice and the missing number and return them as [duplicate, missing].


Examples

Input: nums = [1,2,2,4]
Output: [2,3]

Input: nums = [1,1]
Output: [1,2]

My Current Solution

I attempted to use Cyclic Sort to place numbers in their correct positions and identify the misplaced duplicate. However, my implementation enters an infinite loop for certain inputs like [2,3,2].

from typing import List

def findErrorNums(nums: List[int]) -> List[int]:
    i = 0
    n = len(nums)
    duplicated = 0

    while i < n:
        print(f"i: {i}")
        print(f"Before: {i}, nums: {nums}")

        # If the number is in the right spot, skip it
        if i == nums[i] - 1:
            i += 1

        # If the target index already has the same number, it is a duplicate
        elif nums[i] == nums[nums[i] - 1]:
            duplicated = nums[i]
            i += 1

        # Send the number to its correct index
        else:
            nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]

        print(f"After: {i}, nums: {nums}")
        print()
    
    # Identify the missing number
    for i in range(n):
        if i + 1 != nums[i]:
            return [duplicated, i + 1]

Issue

For the input:

nums = [2,3,2]

The debug output shows an infinite loop where nums[0] keeps swapping between 2 and 3 without making progress.


Debug Output (Repeating Pattern)

i: 0
Before: 0, nums: [3, 2, 2]
After: 0, nums: [2, 3, 2]

i: 0
Before: 0, nums: [2, 3, 2]
After: 0, nums: [3, 3, 2]

i: 0
Before: 0, nums: [3, 3, 2]
After: 0, nums: [2, 3, 2]

i: 0
Before: 0, nums: [2, 3, 2]
After: 0, nums: [3, 3, 2]

...
(repeats indefinitely)

I am unable to understand why 3 is being duplicated instead of being swapped. Is there a bug in my code that I am unable to see?


Solution

  • The problem is caused by your multiple assignment statement:

    nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]
    

    This assignment evaluates the right hand side, but then first assigns to the first tuple member (nums[i]) and only then evaluates where the second assignment must be made, ... using the new value of nums[i] when evaluating nums[i]-1!

    To avoid this, you could do this:

    j = nums[i] - 1
    nums[i], nums[j] = nums[j], nums[i]
    

    Now your code will work.