Previous Permutation With One Swap in Python

Finding the previous permutation with one swap means finding the lexicographically largest permutation that is smaller than the given array by swapping exactly two elements. If no such permutation exists, we return the original array.

For example, given [3,2,1], we can swap positions 1 and 2 to get [3,1,2], which is the largest permutation smaller than the original.

Algorithm

The algorithm follows these steps ?

  • Find the rightmost position where A[left] > A[left + 1]
  • If no such position exists, return the original array
  • Find the largest element to the right of left that is smaller than A[left]
  • Swap these two elements

Implementation

def prevPermOpt1(A):
    n = len(A)
    
    # Find the rightmost position where A[left] > A[left + 1]
    left = -1
    for i in range(n - 2, -1, -1):
        if A[i] > A[i + 1]:
            left = i
            break
    
    # If no such position exists, return original array
    if left == -1:
        return A
    
    # Find the largest element smaller than A[left]
    max_element = 0
    swap_index = -1
    
    for right in range(left + 1, n):
        if A[right] < A[left] and A[right] > max_element:
            max_element = A[right]
            swap_index = right
    
    # Swap the elements
    A[left], A[swap_index] = A[swap_index], A[left]
    
    return A

# Test with examples
print("Example 1:", prevPermOpt1([4, 2, 3, 1, 3]))
print("Example 2:", prevPermOpt1([3, 2, 1]))
print("Example 3:", prevPermOpt1([1, 2, 3]))
Example 1: [4, 2, 1, 3, 3]
Example 2: [3, 1, 2]
Example 3: [1, 2, 3]

How It Works

Let's trace through the algorithm with [4, 2, 3, 1, 3] ?

  1. Find the pivot: Starting from right, we find A[1] = 2 > A[2] = 3 is false, but A[0] = 4 > A[1] = 2 is true, so left = 0
  2. Find swap candidate: Look for the largest element smaller than A[0] = 4 in positions 1-4. We find A[3] = 1 is the largest valid candidate
  3. Swap: Exchange A[0] and A[3] to get [1, 2, 3, 4, 3]

Edge Cases

The algorithm handles several edge cases ?

# Already smallest permutation
print("Already smallest:", prevPermOpt1([1, 2, 3, 4]))

# Single element
print("Single element:", prevPermOpt1([5]))

# All elements same
print("All same:", prevPermOpt1([2, 2, 2]))
Already smallest: [1, 2, 3, 4]
Single element: [5]
All same: [2, 2, 2]

Time Complexity

The algorithm has O(n) time complexity since we make at most two passes through the array. The space complexity is O(1) as we only use a constant amount of extra space.

Conclusion

The previous permutation algorithm finds the lexicographically largest permutation smaller than the input by identifying the rightmost "break point" and swapping with the optimal candidate. This approach efficiently handles all edge cases in linear time.

---
Updated on: 2026-03-25T08:32:09+05:30

507 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements