Lexicographically Previous Permutation

Last Updated : 3 Jun, 2026

Given a string s representing a non-negative integer, find the lexicographically previous permutation of its digits. Each digit of s must be used exactly once, and the resulting number must not contain leading zeros.

  • If no previous permutation exists, return "-1".
  • The answer should be returned as a string.

Examples:

Input: s = "4321"
Output: "4312"
Explanation:The lexicographically previous permutation of "4321" is "4312".

Input: s = "1234"
Output: "-1"
Explanation: The string "1234" is sorted in ascending order, so no previous permutation exists.

Try It Yourself
redirect icon

[Naive Approach] Generate All Permutations - O(|s| × |s|!) Time and O(|s|) Space

The idea is to generate all possible permutations of the digits of s using recursion (backtracking). For each permutation, we check whether it is valid,. Among all valid permutations, we keep track of the largest one. If no valid permutation exists, return “-1”.

C++
#include <bits/stdc++.h>
using namespace std;

// Stores the largest valid permutation smaller than the original string
string res;

// Backtracking function to generate all permutations
void generate(string &s, string &curr,
              vector<bool> &used, string &original) {

    // Base case: full permutation formed
    if (curr.size() == s.size()) {

        // Skip leading zero numbers
        if (curr[0] == '0') return;

        // Check if valid candidate
        if (curr < original) {
            if (res == "-1" || curr > res)
                res = curr;
        }
        return;
    }

    // Try each unused digit
    for (int i = 0; i < s.size(); i++) {

        if (used[i]) continue;

        used[i] = true;
        curr.push_back(s[i]);

        generate(s, curr, used, original);

        // Backtrack
        curr.pop_back();
        used[i] = false;
    }
}

// Function to find lexicographically previous permutation
string prevPermutation(string &s) {

    //  reset global variable for each call
    res = "-1";

    string curr = "";
    vector<bool> used(s.size(), false);

    generate(s, curr, used, s);

    return res;
}
int main() {

    string s = "4321";

    cout << prevPermutation(s);

    return 0;
}
Java
class GFG {

    // Stores the largest valid permutation smaller than the original string
    static String res = "-1";

    // Function to generate all permutations of the string
    static void generate(String s, StringBuilder curr,
                         boolean[] used, String original) {

        // If a complete permutation is formed
        if (curr.length() == s.length()) {

            String temp = curr.toString();

            // Ignore permutations with leading zeros
            if (temp.charAt(0) == '0')
                return;

            // Update answer if the current permutation is
            // smaller than the original and larger than
            // the previously found answer
            if (temp.compareTo(original) < 0) {
                if (res.equals("-1") || temp.compareTo(res) > 0)
                    res = temp;
            }
            return;
        }

        // Try placing every unused digit at the current position
        for (int i = 0; i < s.length(); i++) {

            if (used[i])
                continue;

            used[i] = true;
            curr.append(s.charAt(i));

            generate(s, curr, used, original);

            // Backtrack
            curr.deleteCharAt(curr.length() - 1);
            used[i] = false;
        }
    }

    // Function to find the lexicographically previous permutation
    static String prevPermutation(String s) {

        res = "-1";

        StringBuilder curr = new StringBuilder();
        boolean[] used = new boolean[s.length()];

        generate(s, curr, used, s);

        return res;
    }

    public static void main(String[] args) {

        String s = "4321";

        System.out.println(prevPermutation(s));
    }
}
Python
# Stores the largest valid permutation smaller than the original string
res = "-1"

# Function to generate all permutations of the string
def generate(s, curr, used, original):
    global res

    # If a complete permutation is formed
    if len(curr) == len(s):

        temp = "".join(curr)

        # Ignore permutations with leading zeros
        if temp[0] == '0':
            return

        # Update answer if the current permutation is
        # smaller than the original and larger than
        # the previously found answer
        if temp < original:
            if res == "-1" or temp > res:
                res = temp
        return

    # Try placing every unused digit at the current position
    for i in range(len(s)):

        if used[i]:
            continue

        used[i] = True
        curr.append(s[i])

        generate(s, curr, used, original)

        # Backtrack
        curr.pop()
        used[i] = False

# Function to find the lexicographically previous permutation
def prevPermutation(s):
    global res

    res = "-1"

    curr = []
    used = [False] * len(s)

    generate(s, curr, used, s)

    return res

if __name__ == "__main__":

    s = "4321"

    print(prevPermutation(s))
C#
using System;
using System.Text;

class GFG
{
    // Stores the largest valid permutation smaller than the original string
    static string res = "-1";

    // Function to generate all permutations of the string
    static void generate(string s, StringBuilder curr,
                         bool[] used, string original)
    {
        // If a complete permutation is formed
        if (curr.Length == s.Length)
        {
            string temp = curr.ToString();

            // Ignore permutations with leading zeros
            if (temp[0] == '0')
                return;

            // Update answer if the current permutation is
            // smaller than the original and larger than
            // the previously found answer
            if (string.Compare(temp, original) < 0)
            {
                if (res == "-1" || string.Compare(temp, res) > 0)
                    res = temp;
            }
            return;
        }

        // Try placing every unused digit at the current position
        for (int i = 0; i < s.Length; i++)
        {
            if (used[i])
                continue;

            used[i] = true;
            curr.Append(s[i]);

            generate(s, curr, used, original);

            // Backtrack
            curr.Length--;
            used[i] = false;
        }
    }

    // Function to find the lexicographically previous permutation
    static string prevPermutation(string s)
    {
        res = "-1";

        StringBuilder curr = new StringBuilder();
        bool[] used = new bool[s.Length];

        generate(s, curr, used, s);

        return res;
    }

    // Driver code
    static void Main()
    {
        string s = "4321";

        Console.WriteLine(prevPermutation(s));
    }
}
JavaScript
// Stores the largest valid permutation smaller than the original string
let res = "-1";

// Function to generate all permutations of the string
function generate(s, curr, used, original) {

    // If a complete permutation is formed
    if (curr.length === s.length) {

        let temp = curr.join('');

        // Ignore permutations with leading zeros
        if (temp[0] === '0')
            return;

        // Update answer if the current permutation is
        // smaller than the original and larger than
        // the previously found answer
        if (temp < original) {
            if (res === "-1" || temp > res)
                res = temp;
        }
        return;
    }

    // Try placing every unused digit at the current position
    for (let i = 0; i < s.length; i++) {

        if (used[i])
            continue;

        used[i] = true;
        curr.push(s[i]);

        generate(s, curr, used, original);

        // Backtrack
        curr.pop();
        used[i] = false;
    }
}

// Function to find the lexicographically previous permutation
function prevPermutation(s) {

    res = "-1";

    let curr = [];
    let used = new Array(s.length).fill(false);

    generate(s, curr, used, s);

    return res;
}

// Driver code
let s = "4321";

console.log(prevPermutation(s));

Output
4312

[Expected Approach] Previous Permutation - O(|s|) Time and O(1) Space

Instead of generating all permutations, we directly construct the previous permutation. We first find the pivot, the first index from the right where s[i] > s[i+1]. This is the point where the number can be reduced.

  • Find the first index i from right such that s[i] > s[i+1]
  • If not found, return "-1"
  • Find the largest digit smaller than s[i] on the right
  • Swap pivot with that digit (avoid leading zero if i == 0)
  • Reverse suffix from i + 1 and return result

Consider the input: s = "534976"

Step 1: Traverse from right and find the first index i such that s[i] > s[i + 1].

  • Scan from right: 5 3 4 9 7 6 . Here, 7 > 6, so pivot index = 4 and pivot digit = 7.
  • This is the position where the number can be made smaller.

Step 2: From the right side of pivot, find the largest digit smaller than pivot digit.

  • Right side = [6]
  • The largest digit smaller than 7 is 6.

Step 3: Swap the pivot digit with the selected digit.

  • Before Swap: 5 3 4 9 7 6
  • After Swap: 5 3 4 9 6 7

Step 4: Reverse the suffix after the pivot. Since the suffix is already in increasing order, reversing it makes it descending and gives the largest possible arrangement.

  • Suffix = [7]
  • Since the suffix contains only one digit, it remains unchanged.

Step 5: The resulting string is: 534967

Therefore, the lexicographically previous permutation of "534976" is: 534967

C++
#include <bits/stdc++.h>
using namespace std;

string prevPermutation(string &s) {
    int n = s.size();

    // Step 1: Find the pivot
    int i = n - 2;
    while (i >= 0 && s[i] <= s[i + 1]) {
        i--;
    }

    // No previous permutation exists
    if (i < 0) {
        return "-1";
    }

    // Step 2: Find the largest digit smaller than s[i]
    int j = -1;
    for (int k = n - 1; k > i; k--) {

        if (s[k] < s[i]) {

            // Avoid leading zero
            if (i == 0 && s[k] == '0')
                continue;

            j = k;
            break;
        }
    }

    // No valid swap possible
    if (j == -1) {
        return "-1";
    }

    // Step 3: Swap pivot with the chosen digit
    swap(s[i], s[j]);

    // Step 4: Reverse the suffix
    reverse(s.begin() + i + 1, s.end());

    return s;
}

int main() {

    string s = "534976";

    cout << prevPermutation(s) << endl;

    return 0;
}
Java
class GFG {

    static String prevPermutation(String s) {
        int n = s.length();

        // Step 1: Find the pivot
        int i = n - 2;
        while (i >= 0 && s.charAt(i) <= s.charAt(i + 1)) {
            i--;
        }

        // No previous permutation exists
        if (i < 0) {
            return "-1";
        }

        // Step 2: Find the largest digit smaller than s[i]
        int j = -1;
        for (int k = n - 1; k > i; k--) {

            if (s.charAt(k) < s.charAt(i)) {

                // Avoid leading zero
                if (i == 0 && s.charAt(k) == '0')
                    continue;

                j = k;
                break;
            }
        }

        // No valid swap possible
        if (j == -1) {
            return "-1";
        }

        char[] arr = s.toCharArray();

        // Step 3: Swap pivot with the chosen digit
        char temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;

        // Step 4: Reverse the suffix
        int left = i + 1, right = n - 1;
        while (left < right) {
            temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }

        return new String(arr);
    }

    public static void main(String[] args) {

        String s = "534976";

        System.out.println(prevPermutation(s));
    }
}
Python
def prevPermutation(s):
    n = len(s)
    s = list(s)

    # Step 1: Find the pivot
    i = n - 2
    while i >= 0 and s[i] <= s[i + 1]:
        i -= 1

    # No previous permutation exists
    if i < 0:
        return "-1"

    # Step 2: Find the largest digit smaller than s[i]
    j = -1
    for k in range(n - 1, i, -1):

        if s[k] < s[i]:

            # Avoid leading zero
            if i == 0 and s[k] == '0':
                continue

            j = k
            break

    # No valid swap possible
    if j == -1:
        return "-1"

    # Step 3: Swap pivot with the chosen digit
    s[i], s[j] = s[j], s[i]

    # Step 4: Reverse the suffix
    s[i + 1:] = reversed(s[i + 1:])

    return "".join(s)


if __name__ == "__main__":

    s = "534976"

    print(prevPermutation(s))
C#
using System;

class GFG
{
    static string prevPermutation(string s)
    {
        int n = s.Length;

        // Step 1: Find the pivot
        int i = n - 2;
        while (i >= 0 && s[i] <= s[i + 1])
        {
            i--;
        }

        // No previous permutation exists
        if (i < 0)
        {
            return "-1";
        }

        // Step 2: Find the largest digit smaller than s[i]
        int j = -1;
        for (int k = n - 1; k > i; k--)
        {
            if (s[k] < s[i])
            {
                // Avoid leading zero
                if (i == 0 && s[k] == '0')
                    continue;

                j = k;
                break;
            }
        }

        // No valid swap possible
        if (j == -1)
        {
            return "-1";
        }

        char[] arr = s.ToCharArray();

        // Step 3: Swap pivot with the chosen digit
        char temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;

        // Step 4: Reverse the suffix
        Array.Reverse(arr, i + 1, n - i - 1);

        return new string(arr);
    }

    static void Main()
    {
        string s = "534976";

        Console.WriteLine(prevPermutation(s));
    }
}
JavaScript
function prevPermutation(s) {
    let n = s.length;
    s = s.split('');

    // Step 1: Find the pivot
    let i = n - 2;
    while (i >= 0 && s[i] <= s[i + 1]) {
        i--;
    }

    // No previous permutation exists
    if (i < 0) {
        return "-1";
    }

    // Step 2: Find the largest digit smaller than s[i]
    let j = -1;
    for (let k = n - 1; k > i; k--) {

        if (s[k] < s[i]) {

            // Avoid leading zero
            if (i === 0 && s[k] === '0')
                continue;

            j = k;
            break;
        }
    }

    // No valid swap possible
    if (j === -1) {
        return "-1";
    }

    // Step 3: Swap pivot with the chosen digit
    [s[i], s[j]] = [s[j], s[i]];

    // Step 4: Reverse the suffix
    let left = i + 1, right = n - 1;
    while (left < right) {
        [s[left], s[right]] = [s[right], s[left]];
        left++;
        right--;
    }

    return s.join('');
}

// Driver code
let s = "534976";
console.log(prevPermutation(s));

Output
534967
Comment