📌  相关文章
📜  用相同的数字找到小于N的最大数字

📅  最后修改于: 2021-04-27 19:54:57             🧑  作者: Mango

给定数字N的字符串形式。任务是找到与N具有相同数字集且小于N的最大数字。如果找不到任何这样的数字,则打印“不可能”。

例子

Input:  N = "218765"
Output: 218756

Input:  N = "1234"
Output: Not Possible

Input: N = "262345"
Output: 256432

以下是关于小于N的最大数的一些观察结果:

  1. 如果所有数字都按升序排列,则输出始终为“不可能”。例如1234。
  2. 如果所有数字都按降序排列,那么我们需要交换最后两位数字。例如4321。
  3. 对于其他情况,我们需要从最右边处理数字(为什么?因为我们需要找到所有较小数字中的最大数字)。

算法

  • 从最右边的数字遍历给定的数字,继续遍历直到找到一个比先前遍历的数字更大的数字。例如,如果输入数字为“ 262345”,则由于在6处比前一个数字5大,所以我们在6处停止。如果找不到这样的数字,则输出为“不可能”。
  • 现在,在上述找到的数字“ d”的右侧搜索小于“ d”的最大数字。对于“ 262345”,6的右侧包含“ 2345”。小于6的最大数字是5。
  • 交换上面找到的两位数,在上面的示例中我们得到“ 252346”。
  • 现在,按降序对从“ d”旁边的位置到数字末尾的所有数字进行排序。排序后得到的数字就是输出。对于上面的示例,我们将数字以粗体25 2346排序。我们得到256432 ,这是输入262345的先前较小的数字。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
#include 
using namespace std;
  
// Function to find previous number
void findPrevious(string number, int n)
{
    int i, j;
  
    // I) Start from the right most digit
    // and find the first digit that is
    // smaller than the digit next to it.
    for (i = n - 1; i > 0; i--)
        if (number[i] < number[i - 1])
            break;
  
    // If no such digit is found
    // then all digits are in ascending order
    // means there cannot be a smallest number
    // with same set of digits
    if (i == 0) {
        cout << "Previous number is not possible";
        return;
    }
  
    // II) Find the greatest digit on
    // right side of (i-1)'th digit that is
    // smaller than number[i-1]
    int x = number[i - 1], greatest = i;
    for (j = i; j < n; j++)
        if (number[j] < x && number[j] > number[greatest])
            greatest = j;
  
    // III) Swap the above found smallest digit with number[i-1]
    swap(number[greatest], number[i - 1]);
  
    // IV) Sort the digits after (i-1) in descending order
    sort(number.begin() + i, number.begin() + n, greater());
  
    cout << "Greatest smaller number with same set of digits is " << number;
  
    return;
}
  
// Driver code
int main()
{
    string digits = "262345";
    int n = digits.length();
  
    findPrevious(digits, n);
  
    return 0;
}


Java
// Java implementation of the above approach
import java.util.*;
  
class GFG 
{
  
    // Function to find previous number
    static void findPrevious(char[] number, int n) 
    {
        int i, j;
  
        // I) Start from the right most digit
        // and find the first digit that is
        // smaller than the digit next to it.
        for (i = n - 1; i > 0; i--) 
        {
            if (number[i] < number[i - 1]) 
            {
                break;
            }
        }
  
        // If no such digit is found
        // then all digits are in ascending order
        // means there cannot be a smallest number
        // with same set of digits
        if (i == 0)
        {
            System.out.print("Previous number is not possible");
            return;
        }
  
        // II) Find the greatest digit on
        // right side of (i-1)'th digit that is
        // smaller than number[i-1]
        int x = number[i - 1], greatest = i;
        for (j = i; j < n; j++) 
        {
            if (number[j] < x && number[j] > number[greatest]) 
            {
                greatest = j;
            }
        }
  
        // III) Swap the above found smallest digit with number[i-1]
        swap(number, greatest, i - 1);
  
        // IV) Sort the digits after (i-1) in descending order
        Arrays.sort(number, i, n);
        reverse(number, i, n - 1);
        System.out.print("Greatest smaller number with" + 
              "same set of digits is " + String.valueOf(number));
  
        return;
    }
  
    static String swap(char[] ch, int i, int j) 
    {
        char temp = ch[i];
        ch[i] = ch[j];
        ch[j] = temp;
        return String.valueOf(ch);
    }
  
    static void reverse(char str[], int start, int end) 
    {
  
        // Temporary variable to store character 
        char temp;
        while (start <= end)
        {
            // Swapping the first and last character 
            temp = str[start];
            str[start] = str[end];
            str[end] = temp;
            start++;
            end--;
        }
    }
      
    // Driver code
    public static void main(String[] args)
    {
        String digits = "262345";
        int n = digits.length();
  
        findPrevious(digits.toCharArray(), n);
    }
}
  
// This code has been contributed by 29AjayKumar


Python3
# Python3 implementation of the above approach
  
# Function to find previous number
def findPrevious(number, n):
  
    # This is necessary as strings
    # do not support item assignment
    number = list(number)
  
    i, j = -1, -1
  
    # I) Start from the right most digit
    # and find the first digit that is
    # smaller than the digit next to it.
    for i in range(n - 1, 0, -1):
        if number[i] < number[i - 1]:
            break
      
    # If no such digit is found
    # then all digits are in ascending order
    # means there cannot be a smallest number
    # with same set of digits
    if i == 0:
        print("Previous number is not possible")
        return
      
    x, greatest = number[i - 1], i
  
    # II) Find the greatest digit on
    # right side of(i-1)'th digit that is
    # smaller than number[i-1]
    for j in range(i, n):
        if (number[j] < x and
            number[j] > number[greatest]):
            greatest = j
      
    # III) Swap the above found smallest digit
    # with number[i-1]
    (number[greatest], 
     number[i - 1]) = (number[i - 1], 
                       number[greatest])
  
    l = number[i:]
    del number[i:]
  
    # IV) Sort the digits after(i-1)
    # in descending order
    l.sort(reverse = True)
  
    number += l
  
    # Again join the list to make it string
    number = '' . join(number)
    print("Greatest smaller number with",
          "same set of digits is", number)
  
    return
  
# Driver Code
if __name__ == "__main__":
    digits = "262345"
    n = len(digits)
  
    findPrevious(digits, n)
  
# This code is contributed by sanjeev2552


C#
// c# implementation of the approach
using System;
using System.Collections.Generic; 
  
class GFG 
{
  
    // Function to find previous number
    static void findPrevious(char[] number, int n) 
    {
        int i, j;
  
        // I) Start from the right most digit
        // and find the first digit that is
        // smaller than the digit next to it.
        for (i = n - 1; i > 0; i--) 
        {
            if (number[i] < number[i - 1]) 
            {
                break;
            }
        }
  
        // If no such digit is found
        // then all digits are in ascending order
        // means there cannot be a smallest number
        // with same set of digits
        if (i == 0)
        {
            Console.Write("Previous number is not possible");
            return;
        }
  
        // II) Find the greatest digit on
        // right side of (i-1)'th digit that is
        // smaller than number[i-1]
        int x = number[i - 1], greatest = i;
        for (j = i; j < n; j++) 
        {
            if (number[j] < x && number[j] > number[greatest]) 
            {
                greatest = j;
            }
        }
  
        // III) Swap the above found 
        // smallest digit with number[i-1]
        swap(number, greatest, i - 1);
  
        // IV) Sort the digits after (i-1) in descending order
        Array.Sort(number, i, n-i);
        reverse(number, i, n - 1);
        Console.Write("Greatest smaller number with" + 
            "same set of digits is " + String.Join("",number));
  
        return;
    }
  
    static String swap(char[] ch, int i, int j) 
    {
        char temp = ch[i];
        ch[i] = ch[j];
        ch[j] = temp;
        return String.Join("",ch);
    }
  
    static void reverse(char []str, int start, int end) 
    {
  
        // Temporary variable to store character 
        char temp;
        while (start <= end)
        {
            // Swapping the first and last character 
            temp = str[start];
            str[start] = str[end];
            str[end] = temp;
            start++;
            end--;
        }
    }
      
    // Driver code
    public static void Main(String[] args)
    {
        String digits = "262345";
        int n = digits.Length;
  
        findPrevious(digits.ToCharArray(), n);
    }
}
  
/* This code contributed by PrinciRaj1992 */


输出:
Greatest smaller number with same set of digits is 256432