邻位交换的最小次数

题目链接

视频讲解

给你一个表示大整数的字符串 num ,和一个整数 k 。

如果某个整数是 num 中各位数字的一个 排列 且它的 值大于 num ,则称这个整数为 妙数 。可能存在很多妙数,但是只需要关注 值最小 的那些。

例如,num = "5489355142" :
第 1 个最小妙数是 "5489355214"
第 2 个最小妙数是 "5489355241"
第 3 个最小妙数是 "5489355412"
第 4 个最小妙数是 "5489355421"
返回要得到第 k 个 最小妙数 需要对 num 执行的 相邻位数字交换的最小次数 。

测试用例是按存在第 k 个最小妙数而生成的。

 

示例 1:

输入:num = "5489355142", k = 4
输出:2
解释:第 4 个最小妙数是 "5489355421" ,要想得到这个数字:
- 交换下标 7 和下标 8 对应的位:"5489355142" -> "5489355412"
- 交换下标 8 和下标 9 对应的位:"5489355412" -> "5489355421"
示例 2:

输入:num = "11112", k = 4
输出:4
解释:第 4 个最小妙数是 "21111" ,要想得到这个数字:
- 交换下标 3 和下标 4 对应的位:"11112" -> "11121"
- 交换下标 2 和下标 3 对应的位:"11121" -> "11211"
- 交换下标 1 和下标 2 对应的位:"11211" -> "12111"
- 交换下标 0 和下标 1 对应的位:"12111" -> "21111"
示例 3:

输入:num = "00123", k = 1
输出:1
解释:第 1 个最小妙数是 "00132" ,要想得到这个数字:
- 交换下标 3 和下标 4 对应的位:"00123" -> "00132"
 

提示:

2 <= num.length <= 1000
1 <= k <= 1000
num 仅由数字组成

这个题可以用那个next_mutation来求它的变换后的次序

然后这个题就变成了,就是如果一个字符串变成令一个字符串并且只能交换相邻的元素

这个第一反应就能想到逆序对,这个题就是把上面的数字映射到下面,然后在求一个逆序对就行了

然后还有一个问题就是如果出现这个数字多次怎么来映射嗯?

答案是按照顺序来映射

由于这个题是数据范围很小,求逆序对的时候可以用暴力求,如果很大的时候,可以用树状数组求

class Solution {
public:
    int getMinSwaps(string a, int k) {
        string b=a;
        while(k--) next_permutation(b.begin(),b.end());
        int n=b.size();
        int cnt[10]={0};
        vector<int>c(n);
        for(int i=0;i<n;i++){
            int x=a[i]-'0';
            cnt[x]++;//出现次数
            int y=cnt[x];
            for(int j=0;j<n;j++){
                if(b[j]-'0'==x){
                    y--;
                    if(y==0){
                        c[i]=j;
                        break;
                    }
                }
            }
            
        }
        int ans=0;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                if(c[i]>c[j]){
                    ans++;
                }
            }
        }
        return ans;
    }
};

 

posted @ 2021-05-04 19:54  lipu123  阅读(219)  评论(0)    收藏  举报