将给定数字转换为幸运数字所需的最小移动次数[关闭]

Posted

技术标签:

【中文标题】将给定数字转换为幸运数字所需的最小移动次数[关闭]【英文标题】:minimum number of moves required to convert a given into a lucky number [closed] 【发布时间】:2021-09-02 11:58:43 【问题描述】:

给您一个数字,一次您可以将一个数字增加 1 或减少 1,这被视为一个移动找到将给定数字转换为幸运数字所需的最小移动数。如果一个数字中的所有数字都是偶数,则该数字称为幸运数字。

我已经编写了代码,但我不确定它是否正确。有人可以确认一下吗?

#include<bits/stdc++.h>
using namespace std;

int count(int n)

    int count = 0;
    while (n != 0)
    
        n = n / 10;
        ++count;
    
    return count;


int firstDigit(int n)

    // Remove last digit from number
    // till only one digit is left
    while (n >= 10)
        n /= 10;
     
    // return the first digit
    return n;


int main()

    int n;
    cin >> n;

    int i,j,ans=0;

    int x = count(n);

    while(x--)
    
        if(firstDigit(n)%2 != 0)
        
            if(firstDigit(n) == 9)
            
                ans = ans + pow(10,x);
                n = n-pow(10,x);
            

            else
            
                ans = ans + pow(10,x);
                n = n + pow(10,x);
            
        
        
        else
        n = n - pow(10,x);

    

    cout << ans << endl;


编辑:

我发现它在 100 处给出了错误的答案。你能帮我找出错误吗

【问题讨论】:

好消息:你可以做到。编写测试。用笔和纸计算出某些输入的预期输出,并将其与代码的输出进行比较。尝试考虑边缘情况,例如输入已经是一个幸运数字,有两种可能的解决方案都是最优的,等等。 与许多其他所谓的“竞争”或“在线评委”提交(看起来像)相比,您的代码相当不错。然而,有两件事你仍然需要改变你的习惯:首先是Why should I not #include <bits/stdc++.h>?;然后Why is "using namespace std;" considered bad practice? @463035818_is_not_a_number 我试过了,到现在看来还不错 每次看到pow(10,x)都会让我难过。在这种情况下,浮点运算可能很危险。 int i,j,ans=0;, i, j 似乎未使用。 【参考方案1】:

并非所有代码都可以轻松测试,这就是为什么您应该努力从一开始就编写可测试的代码(而不是先编写所有代码然后然后尝试确认正确性)。在您的情况下,可测试性可以从将大部分逻辑从main 转移到专用函数中受益匪浅:

 int minimal_steps(int input) 
        ....
 

一旦你有了它,你可以像现在一样使用用户提供的输入在main 中调用它,但你也可以更轻松地编写测试:

 void test() 
      assert( minimal_steps(2222) == 0);
      assert( minimal_steps(2221) == 1); 
      ...etc...
 

一旦您养成了测试代码的习惯(您还应该为countfirstDigit 编写测试),您可能会考虑使用测试框架来自动化测试。


PS: 没有错,但是这样浪费CPU周期值得一提(其实评论里已经提到了)。您不需要在x 是循环计数器的循环中计算pow(10,x)。考虑到您计算 10^2 的次数几乎与循环的迭代次数一样多。 10^3 在每次迭代中也是相同的。相反,您应该只更新*10(以防x 增加)或/10x 在迭代之间递减时更新。此外,pow 用于浮点数,而不是整数。

【讨论】:

与 catch2 直播:godbolt.org/z/jcKPxedvb 我发现它在 100 处给出了错误的答案。你能帮我找出错误吗 @ububush 我已经在答案中给出了提示:测试countfirstDigit 看看是否存在错误。下一步是使用调试器 @ububush 我不知道您的算法应该如何工作,例如if(firstDigit(n)%2 != 0) 我不知道为什么?所以我不知道如何通过不从头开始来解决它。我很确定其他人也有类似的问题。也许你应该改变你的方法?只需遍历所有可能的数字并计算隐藏给定数字所需的步骤数,使其仅包含该数字。然后只需找到最少的步骤数就可以了。这是具有O(n) 复杂性的简单粗暴强制方法,因此没有必要寻找更聪明的方法。

以上是关于将给定数字转换为幸运数字所需的最小移动次数[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

给定数组表示 S 所需的最小数字计数

使序列的所有元素为 0 所需的最小步骤数

给定一个随机顺序的整数数组,您必须找到最小交换次数才能将其转换为循环排序数组

1822. 最小移动次数

搜索排序数组中出现次数超过一半的元素所需的最小比较

牛客练习赛13