要使一个数成为完全平方数,需要删除的最少位数

data structurec++programming

问题描述包括找出要使一个数成为完全平方数,需要删除的最少位数。

完全平方数表示为 $\mathrm{x^{2}}$,它是一个正整数,它是一个整数与其自身的乘积。

给定一个正数 N,我们需要找出可以从 N 中删除的最少位数,使其成为完全平方数,即某个整数与其自身的乘积。

例如,N=42

我们可以从 N 中删除 1 位数字,即 2,使其成为完全平方数,也就是 4,也是一个完全平方数。

在这个问题中,我们将给定一个数字 N 作为输入,我们的任务是通过从 N 中删除最少位数的数字和从 N 中移除 1 位数字,使其成为一个完全平方数。

在某些情况下,从 N 中移除任意位数的数字后,它仍然不是完全平方数,因此打印 -1。如果通过移除最少位数的数字可以形成多个完全平方数,则打印其中任意一个。

让我们通过以下示例来理解这个问题。

输入

N=490

输出

49 1

解释- 输入数字为 490,它不是完全平方数。如果我们从数字中移除一位数字,即 0,则数字变为 49,即一个完全平方数 (7*7)。同时,如果我们从 N 中移除两位数字,即 9 和 0,该数字将变为 4,这也是一个完全平方数。

由于我们需要找到最少移除的位数才能使 N 成为完全平方数,因此仅移除 1 位数字,输出将为 49。

输入

N=323

输出

-1

解释- 给定的数字是 323,它不是完全平方数,即使从 N 中移除任意位数,也无法使其成为完全平方数。因此,输出为 -1。

让我们理解一下算法,找出从 N 中移除的最少位数,使其成为完全平方数。

算法

我们需要通过移除任意位数,使给定的数字 N 成为完全平方数。我们需要找出移除的最少位数,才能使其成为完全平方数。

为了找出从 N 中移除的最少位数,使其成为一个完全平方数,我们只需找到数字 N 的所有子序列即可。例如,假设 N 为 8641,则该数字的所有子序列为

8、6、4、1、86、84、81、64、61、41、864、861、841、641、8641。

我们将检查每个子序列是否为完全平方数,并找出从 N 中移除最少位数后可以形成的完全平方数子序列。完全平方数为 4、81、64 和 841。为了使其成为完全平方数,需要从 N 中移除的最少位数为 1,即 6。 841.

为了找到 N 的所有可能子序列,我们将使用递归的概念来查找所有子序列。我们创建一个函数来查找数字 N 的子序列,其中我们将传递一个字符串数据类型的数字和一个空字符串。

递归函数的边界条件是,当字符串长度为 0 时,我们将返回该函数。否则,我们将字符串的第一个字符存储在一个变量中,并更新字符串,但不包括第一个字符。然后,我们将调用相同的函数,传递更新后的字符串,并在 ans 字符串中添加字符,然后不添加 ans 字符串,最终将生成数字的所有可能子序列。

一旦数字的字符串长度为 0,即我们找到了 N 的一个可能子序列,如果 ans 字符串不为空,我们将调用一个函数,通过从 N 中删除最少位数来检查它是否是一个完全平方数。

我们将初始化两个变量,分别存储使 N 成为完全平方数所需删除的最少位数,以及在函数外部存储的完全平方数 N,以获得所需的输出。

为了找到通过删除 N 的最少位数而得到的完全平方数,我们将子序列的平方根存储在一个 int 数据类型的变量中。如果变量的平方等于数字,我们将检查子序列的长度是否大于 a,然后将子序列的长度存储在 a 中,并将子序列存储在另一个变量中。

这样,我们可以得到 N 的所有子序列,并找到最大长度的子序列,该子序列与 N 的大小之差将给出使 N 成为完全平方数所需移除的最小位数。

方法

为了找到使 N 成为完全平方数所需移除的最小位数,我们按照以下步骤实现我们方法中的算法:

  • 为了计算 N 的所有可能子序列,我们调用一个递归函数,对于每个子序列,我们将检查它是否是 N 的最长子序列,即完全平方数。

  • 我们将初始化两个变量来存储数字它是一个完全平方数,并且需要移除的位数最少。

  • 我们将使用 to_string() 函数将输入数字 N 转换为字符串,并调用递归函数,该函数将返回最长可能长度的完全平方数。

  • 打印完全平方数和移除的最少位数。

示例

//C++ 代码,用于查找使 N 成为完全平方数所需的最少移除位数
#include<bits/stdc++.h>

using namespace std;

int res=-1; //从 N 中移除数字后存储完全平方数
int a=0; //存储完全平方数的位数

//检查子序列是否为最大长度的完全平方数
void checkMaximum(int m,string ans)
{
    
    
       int check=sqrt(m); //求子序列的平方根
       
         if(check*check==m) 
         {
           if(a < ans.size()) //如果子序列的长度大于
           {
               a = ans.size(); //将子序列的长度存储在
               res = m; //将数字存储在 res 中,这是一个完全平方数
           }
         }
         
}

// 查找所有可能的子序列
void subsequence(string str,string ans){
    
    if(str.length() == 0){
        
        if( !ans.empty()){
            
         int temp = stoi(ans); //将子序列转换为 int
         
         checkMaximum(temp, ans); //通过删除最小数字来检查它是否是完全平方数
        
        }
     return;
    }
        //使用递归生成所有可能的子序列
        char ch = str[0];
        string roq = str.substr(1);
        subsequence(roq, ans + ch);
        subsequence(roq, ans);
    
}

int main()
{
    int N=78467;
    
    string str =to_string(N); //使用内置函数将 N 转换为字符串
    string ans =""; //用于存储 N 所有可能子序列的字符串
    
    //调用函数
    subsequence(str, ans);
    
    if(res==-1){
       cout<<res<<endl;
    }
    else{
    cout<<res<<endl;
    //str 大小与完全平方的长度之差将给出最少位数
    cout<<str.size()-a<<endl;
    }
    
    return 0;
}

输出

784
2

时间复杂度− $\mathrm{O(2^{n})}$,其中 n 是递归树的深度。

空间复杂度− $\mathrm{O(2^{n})}$,因为递归函数使用堆栈内存。

结论

本文讨论了从 N 中找出需要移除的最少数字,以使其成为完全平方数的问题。我们用 C++ 方法生成了 N 的所有子序列,并对每个子序列进行递归检查,以确定其是否是长度尽可能长的完全平方数,从而得到需要移除的最少数字和最终结果。

希望您在阅读本文后能够理解这个问题以及解决问题的方法。


相关文章