Lexicographically Previous Permutation (original) (raw)
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.
Table of Content
- [Naive Approach] Generate All Permutations - O(|s| × |s|!) Time and O(|s|) Space
- [Expected Approach] Previous Permutation - O(|s|) Time and O(1) Space
[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 &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] = FalseFunction to find the lexicographically previous permutation
def prevPermutation(s): global res
res = "-1"
curr = []
used = [False] * len(s)
generate(s, curr, used, s)
return resif 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));
`
[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));
`