Permute Digits

本文介绍了一个名为D-PermuteDigits的算法问题,该问题要求通过改变一个给定正整数a的数字顺序来构造一个不超过另一个给定正整数b的最大可能数值。文章详细解释了算法的具体实现过程,包括输入输出格式、示例和核心代码逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D - Permute Digits
You are given two positive integer numbers a and b. Permute (change order) of the digits of a to construct maximal number not exceeding b. No number in input and/or output can start with the digit 0.

It is allowed to leave a as it is.

Input
The first line contains integer a (1 ≤ a ≤ 1018). The second line contains integer b (1 ≤ b ≤ 1018). Numbers don’t have leading zeroes. It is guaranteed that answer exists.

Output
Print the maximum possible number that is a permutation of digits of a and is not greater than b. The answer can’t have any leading zeroes. It is guaranteed that the answer exists.

The number in the output should have exactly the same length as number a. It should be a permutation of digits of a.

Example
Input
123
222
Output
213
Input
3921
10000
Output
9321
Input
4940
5000
Output
4940

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int k = 0;
int main(){
    char a[20],b[20];
    int ans[20],cnt[10],flag,flag1;
    memset(cnt,0,sizeof(cnt));
    flag = -2;
    flag1 = 0;
    cin>>a>>b;
    for(int i = 0;i < strlen(a);i++)
        cnt[a[i]-'0']++;
    ///位数比b小,直接逆序输出 
    if(strlen(a)<strlen(b)){
        for(int i = 9;i>=0;i--){
            while(cnt[i]-- != 0) ans[k++] = i;
        }
    }
    ///位数相等的时候 
    else{
        while(k<strlen(a)){
            ///判断是否需要回溯 
            if(flag == 1){
                k--;
                cnt[ans[k]]++;
                for(int i = b[k]-'0'-1;i>=0;i--){
                    if(cnt[i]!=0){
                        ans[k] = i;
                        cnt[i]--;
                        flag = -1;
                        break;
                    }
                }
                ///如果回溯,此时一定比b该位的数小,后面直接逆序输出 
                if(flag == -1) break;
                if(flag == 1) continue;         
            }
            ///如果i位和b该位相等继续循环 
            if(cnt[b[k]-'0']!=0){
                cnt[b[k]-'0']--;
                ans[k] = b[k]-'0';
            }
            ///如果i位比b该位小,打破循环,后面逆序输出 
            else{
                flag1 = 0;
                for(int i = (b[k]-'0')-1;i>=0;i--){
                    if(cnt[i]!=0){
                        ans[k] = i;
                        cnt[i]--;
                        flag1 = flag = -1;
                        break;
                    }
                }
                if(flag1 != -1) flag = 1;
            }
            if(flag == -1) break;
            if(flag==1) continue;
            k++;
        }

    }
    ///中途跳出来循环 剩下的逆序输出 
    if(flag == -1){
        for(int i = 9;i >= 0;i--)
            while(cnt[i]!=0){
                ans[++k] = i;
                cnt[i]--;   
            }
        for(int i = 0;i < strlen(a);i++)
            cout<<ans[i];
            cout<<endl; 
    }
    ///中途为打破循环 等于b或者位数比b小 
    else{
        for(int i = 0;i < strlen(a);i++)
            cout<<ans[i];
            cout<<endl; 
    }
    return 0;
}

代码方法:计数a中0-9出现个数,然后从第一位开始找,如果有和b改为相等的数,继续循环,如果没有,找比b该位小的数(如果没有比b该位小的数,回溯上一位找比b小的数)。注意其中的flag的值变化。
修改过程中卡死的好久的一个特例:1230 1300

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值