📌  相关文章
📜  通过最多进行K次交换来查找最大数目

📅  最后修改于: 2021-05-24 20:27:26             🧑  作者: Mango

给定一个正整数,请通过对其数字进行最多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次。如果将当前数字替换为小于随后数字的数字,则可以进一步优化代码。
算法:

  1. 创建一个全局变量,该变量将存储最大字符串或数字。
  2. 定义一个将字符串作为k的数字和值的递归函数
  3. 运行一个嵌套循环,外部循环从0到字符串-1的长度,内部循环从i + 1到字符串。
  4. 交换第ith个字符和第j个字符,检查字符串现在是否最大并更新最大字符串。
  5. 使用参数: 字符串和k-1递归调用该函数。
  6. 现在再次换回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微秒的改进
算法:

  1. 创建一个全局变量,该变量将存储最大字符串或数字。
  2. 定义一个将字符串作为数字,k的值和当前索引的递归函数。
  3. 在当前索引范围内找到要结束的最大元素的索引。
  4. 如果最大元素的索引不等于当前索引,则减小k的值。
  5. 从当前索引到数组末尾运行循环
  6. 如果第i个数字等于最大元素
  7. 在当前索引处交换ith和element,检查字符串现在是否最大并更新最大字符串。
  8. 使用参数: 字符串和k递归调用该函数。
  9. 现在再次将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)。
    存储输出字符串所需的空间。

锻炼:

  1. 通过对数字进行至少K个交换操作来找到最小整数。
  2. 通过对数字进行精确的K交换运算,找到可能的最大/最小整数。