给定一个正整数,请通过对其数字进行最多K个交换操作来找到最大可能的整数。
例子:
Input: M = 254, K = 1
Output: 524
Swap 5 with 2 so number becomes 524
Input: M = 254, K = 2
Output: 542
Swap 5 with 2 so number becomes 524
Swap 4 with 2 so number becomes 542
Input: M = 68543, K = 1
Output: 86543
Swap 8 with 6 so number becomes 86543
Input: M = 7599, K = 2
Output: 9975
Swap 9 with 5 so number becomes 7995
Swap 9 with 7 so number becomes 9975
Input: M = 76543, K = 1
Output: 76543
Explanation: No swap is required.
Input: M = 129814999, K = 4
Output: 999984211
Swap 9 with 1 so number becomes 929814991
Swap 9 with 2 so number becomes 999814291
Swap 9 with 8 so number becomes 999914281
Swap 1 with 8 so number becomes 999984211
天真的解决方案:
方法:想法是考虑每个数字,然后一次将其替换为跟在其后的数字,并查看它是否导致最大数。该过程重复K次。如果将当前数字替换为小于随后数字的数字,则可以进一步优化代码。
算法:
- 创建一个全局变量,该变量将存储最大字符串或数字。
- 定义一个将字符串作为k的数字和值的递归函数
- 运行一个嵌套循环,外部循环从0到字符串-1的长度,内部循环从i + 1到字符串。
- 交换第ith个字符和第j个字符,检查字符串现在是否最大并更新最大字符串。
- 使用参数: 字符串和k-1递归调用该函数。
- 现在再次换回ith和jth字符。
C++
// C++ program to find maximum
// integer possible by doing
// at-most K swap operations
// on its digits.
#include
using namespace std;
// Function to find maximum
// integer possible by
// doing at-most K swap
// operations on its digits
void findMaximumNum(
string str, int k, string& max)
{
// Return if no swaps left
if (k == 0)
return;
int n = str.length();
// Consider every digit
for (int i = 0; i < n - 1; i++) {
// Compare it with all digits after it
for (int j = i + 1; j < n; j++) {
// if digit at position i
// is less than digit
// at position j, swap it
// and check for maximum
// number so far and recurse
// for remaining swaps
if (str[i] < str[j]) {
// swap str[i] with str[j]
swap(str[i], str[j]);
// If current num is more
// than maximum so far
if (str.compare(max) > 0)
max = str;
// recurse of the other k - 1 swaps
findMaximumNum(str, k - 1, max);
// Backtrack
swap(str[i], str[j]);
}
}
}
}
// Driver code
int main()
{
string str = "129814999";
int k = 4;
string max = str;
findMaximumNum(str, k, max);
cout << max << endl;
return 0;
}
Java
// Java program to find maximum
// integer possible by doing
// at-most K swap operations
// on its digits.
import java.util.*;
class GFG{
static String max;
// Function to find maximum
// integer possible by
// doing at-most K swap
// operations on its digits
static void findMaximumNum(char[] str,
int k)
{
// Return if no swaps left
if (k == 0)
return;
int n = str.length;
// Consider every digit
for (int i = 0; i < n - 1; i++)
{
// Compare it with all digits
// after it
for (int j = i + 1; j < n; j++)
{
// if digit at position i
// is less than digit
// at position j, swap it
// and check for maximum
// number so far and recurse
// for remaining swaps
if (str[i] < str[j])
{
// swap str[i] with
// str[j]
char t = str[i];
str[i] = str[j];
str[j] = t;
// If current num is more
// than maximum so far
if (String.valueOf(str).compareTo(max) > 0)
max = String.valueOf(str);
// recurse of the other
// k - 1 swaps
findMaximumNum(str, k - 1);
// Backtrack
char c = str[i];
str[i] = str[j];
str[j] = c;
}
}
}
}
// Driver code
public static void main(String[] args)
{
String str = "129814999";
int k = 4;
max = str;
findMaximumNum(str.toCharArray(), k);
System.out.print(max + "\n");
}
}
// This code is contributed by 29AjayKumar
Python3
# Python3 program to find maximum
# integer possible by doing at-most
# K swap operations on its digits.
# utility function to swap two
# characters of a string
def swap(string, i, j):
return (string[:i] + string[j] +
string[i + 1:j] +
string[i] + string[j + 1:])
# function to find maximum integer
# possible by doing at-most K swap
# operations on its digits
def findMaximumNum(string, k, maxm):
# return if no swaps left
if k == 0:
return
n = len(string)
# consider every digit
for i in range(n - 1):
# and compare it with all digits after it
for j in range(i + 1, n):
# if digit at position i is less than
# digit at position j, swap it and
# check for maximum number so far and
# recurse for remaining swaps
if string[i] < string[j]:
# swap string[i] with string[j]
string = swap(string, i, j)
# If current num is more than
# maximum so far
if string > maxm[0]:
maxm[0] = string
# recurse of the other k - 1 swaps
findMaximumNum(string, k - 1, maxm)
# backtrack
string = swap(string, i, j)
# Driver Code
if __name__ == "__main__":
string = "129814999"
k = 4
maxm = [string]
findMaximumNum(string, k, maxm)
print(maxm[0])
# This code is contributed
# by vibhu4agarwal
C#
// C# program to find maximum
// integer possible by doing
// at-most K swap operations
// on its digits.
using System;
class GFG{
static String max;
// Function to find maximum
// integer possible by
// doing at-most K swap
// operations on its digits
static void findMaximumNum(char[] str,
int k)
{
// Return if no swaps left
if (k == 0)
return;
int n = str.Length;
// Consider every digit
for (int i = 0; i < n - 1; i++)
{
// Compare it with all digits
// after it
for (int j = i + 1; j < n; j++)
{
// if digit at position i
// is less than digit
// at position j, swap it
// and check for maximum
// number so far and recurse
// for remaining swaps
if (str[i] < str[j])
{
// swap str[i] with
// str[j]
char t = str[i];
str[i] = str[j];
str[j] = t;
// If current num is more
// than maximum so far
if (String.Join("", str).CompareTo(max) > 0)
max = String.Join("", str);
// recurse of the other
// k - 1 swaps
findMaximumNum(str, k - 1);
// Backtrack
char c = str[i];
str[i] = str[j];
str[j] = c;
}
}
}
}
// Driver code
public static void Main(String[] args)
{
String str = "129814999";
int k = 4;
max = str;
findMaximumNum(str.ToCharArray(), k);
Console.Write(max + "\n");
}
}
// This code is contributed by gauravrajput1
C++
// C++ program to find maximum
// integer possible by doing
// at-most K swap operations on
// its digits.
#include
using namespace std;
// Function to find maximum
// integer possible by
// doing at-most K swap operations
// on its digits
void findMaximumNum(
string str, int k,
string& max, int ctr)
{
// return if no swaps left
if (k == 0)
return;
int n = str.length();
// Consider every digit after
// the cur position
char maxm = str[ctr];
for (int j = ctr + 1; j < n; j++) {
// Find maximum digit greater
// than at ctr among rest
if (maxm < str[j])
maxm = str[j];
}
// If maxm is not equal to k,
// decrement k
if (maxm != str[ctr])
--k;
// search this maximum among the rest
for (int j = ctr; j < n; j++) {
// If digit equals maxm swap
// the digit with current
// digit and recurse for the rest
if (str[j] == maxm) {
// swap str[ctr] with str[j]
swap(str[ctr], str[j]);
// If current num is more than
// maximum so far
if (str.compare(max) > 0)
max = str;
// recurse other swaps after cur
findMaximumNum(str, k, max, ctr + 1);
// Backtrack
swap(str[ctr], str[j]);
}
}
}
// Driver code
int main()
{
string str = "129814999";
int k = 4;
string max = str;
findMaximumNum(str, k, max, 0);
cout << max << endl;
return 0;
}
Java
// Java program to find maximum
// integer possible by doing
// at-most K swap operations on
// its digits.
import java.io.*;
class Res {
static String max = "";
}
class Solution {
// Function to set highest possible digits at given
// index.
public static void findMaximumNum(char ar[], int k,
Res r)
{
if (k == 0)
return;
int n = ar.length;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
// if digit at position i is less than digit
// at position j, we swap them and check for
// maximum number so far.
if (ar[j] > ar[i]) {
char temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
String st = new String(ar);
// if current number is more than
// maximum so far
if (r.max.compareTo(st) < 0) {
r.max = st;
}
// calling recursive function to set the
// next digit.
findMaximumNum(ar, k - 1, r);
// backtracking
temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
}
}
}
}
// Function to find the largest number after k swaps.
public static void main(String[] args)
{
String str = "129814999";
int k = 4;
Res r = new Res();
r.max = str;
findMaximumNum(str.toCharArray(), k, r);
//Print the answer stored in res class
System.out.println(r.max);
}
}
输出:
999984211
复杂度分析:
- 时间复杂度: O((n ^ 2)^ k)。
对于每个递归调用,将生成n ^ 2个递归调用,直到k的值为0。因此,递归调用总数为O((n ^ 2)^ k)。 - 空间复杂度: O(n)。
这是存储输出字符串所需的空间。
高效的解决方案:
方法:上述方法在每次递归调用时遍历整个字符串,这是非常低效且不必要的。同样,在递归调用时,在电流之后预先计算最大位数,可以避免与每个位数进行不必要的交换。可以看出,要生成最大的字符串,最大的数字将移到最前面。因此,不要尝试所有对,而仅尝试其中元素之一是尚未交换到最前面的最大数字的那些对。
每个测试用例都有27580微秒的改进。
算法:
- 创建一个全局变量,该变量将存储最大字符串或数字。
- 定义一个将字符串作为数字,k的值和当前索引的递归函数。
- 在当前索引范围内找到要结束的最大元素的索引。
- 如果最大元素的索引不等于当前索引,则减小k的值。
- 从当前索引到数组末尾运行循环
- 如果第i个数字等于最大元素
- 在当前索引处交换ith和element,检查字符串现在是否最大并更新最大字符串。
- 使用参数: 字符串和k递归调用该函数。
- 现在再次将ith和element换回当前索引。
C++
// C++ program to find maximum
// integer possible by doing
// at-most K swap operations on
// its digits.
#include
using namespace std;
// Function to find maximum
// integer possible by
// doing at-most K swap operations
// on its digits
void findMaximumNum(
string str, int k,
string& max, int ctr)
{
// return if no swaps left
if (k == 0)
return;
int n = str.length();
// Consider every digit after
// the cur position
char maxm = str[ctr];
for (int j = ctr + 1; j < n; j++) {
// Find maximum digit greater
// than at ctr among rest
if (maxm < str[j])
maxm = str[j];
}
// If maxm is not equal to k,
// decrement k
if (maxm != str[ctr])
--k;
// search this maximum among the rest
for (int j = ctr; j < n; j++) {
// If digit equals maxm swap
// the digit with current
// digit and recurse for the rest
if (str[j] == maxm) {
// swap str[ctr] with str[j]
swap(str[ctr], str[j]);
// If current num is more than
// maximum so far
if (str.compare(max) > 0)
max = str;
// recurse other swaps after cur
findMaximumNum(str, k, max, ctr + 1);
// Backtrack
swap(str[ctr], str[j]);
}
}
}
// Driver code
int main()
{
string str = "129814999";
int k = 4;
string max = str;
findMaximumNum(str, k, max, 0);
cout << max << endl;
return 0;
}
Java
// Java program to find maximum
// integer possible by doing
// at-most K swap operations on
// its digits.
import java.io.*;
class Res {
static String max = "";
}
class Solution {
// Function to set highest possible digits at given
// index.
public static void findMaximumNum(char ar[], int k,
Res r)
{
if (k == 0)
return;
int n = ar.length;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
// if digit at position i is less than digit
// at position j, we swap them and check for
// maximum number so far.
if (ar[j] > ar[i]) {
char temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
String st = new String(ar);
// if current number is more than
// maximum so far
if (r.max.compareTo(st) < 0) {
r.max = st;
}
// calling recursive function to set the
// next digit.
findMaximumNum(ar, k - 1, r);
// backtracking
temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
}
}
}
}
// Function to find the largest number after k swaps.
public static void main(String[] args)
{
String str = "129814999";
int k = 4;
Res r = new Res();
r.max = str;
findMaximumNum(str.toCharArray(), k, r);
//Print the answer stored in res class
System.out.println(r.max);
}
}
输出:
999984211
复杂度分析:
- 时间复杂度: O(n ^ k)。
对于每个递归调用,将生成n个递归调用,直到k的值为0。因此,递归调用总数为O((n)^ k)。 - 空间复杂度: O(n)。
存储输出字符串所需的空间。
锻炼:
- 通过对数字进行至少K个交换操作来找到最小整数。
- 通过对数字进行精确的K交换运算,找到可能的最大/最小整数。