每日一题 -- LeetCode1850

118 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情image.png

前言

每日一题,轻松解题

每日一题为刷题系列 每日刷一题LeetCode题,并且对题目进行分析,分享思路。

正文

:邻位交换的最小次数

难度:中等

题目要求:

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

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

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

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

举个例子

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

:解题

方法一 :模拟 + 贪心

模拟 + 贪心

贪心
贪婪算法(贪心算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有利)的选择,从而希望能够导致结果是最好或者最优的算法

算法所得到的结果不一定是最优的结果(有时候会是最优解),但是都是相对近似(接近)最优解的结果

以上面的问题问题,若使用贪心算法求出的结果,有时候不一定是最优的结果,因为有可能成本问题不是最好的,但是它是相对接近最优解的

解题思路:

本题是一道由两个经典模型进行拼接得到的题目。

  • 第一步我们需要求出比num 大的第 kk 个排列 num k

  • 第二步我们需要将 num 通过交换操作得到num k,每一步交换操作只能交换相邻的两个字符。

编辑代码:

class Solution {
public:
    int getMinSwaps(string num, int k) {
        string num_k = num;
        for (int i = 0; i < k; ++i) {
            next_permutation(num_k.begin(), num_k.end());
        }
        
        int n = num.size();
        int ans = 0;
        
        for (int i = 0; i < n; ++i) {
            if (num[i] != num_k[i]) {
                for (int j = i + 1; j < n; ++j) {
                    if (num[j] == num_k[i]) {
                        for (int k = j - 1; k >= i; --k) {
                            ++ans;
                            swap(num[k], num[k + 1]);
                        }
                        break;
                    }
                }
            }
        }
        
        return ans;
    }
};

总结

无论做什么分析最重要,其中我们分析了题目,分析了解题思路,其实在分析完解题思路后,代码其实就是很简单的事情了,养成习惯,无论做什么之前,都要进行分析,这样有助于你更快更好的完成这件事。