3796 凑平方(dfs)

1. 问题描述:

给定一个不含前导 0 的正整数 n。你可以对 n 进行删位操作。每次操作,可以将 n 的任意一位数字删去,但是需要保证每次操作完成后的数字仍然是不含前导 0 的正整数。如果想要使得 n 可以成为某个正整数的平方,那么最少需要对 n 进行多少次操作?

输入格式

第一行包含整数 T,表示共有 T 组测试数据。每组数据占一行,包含一个整数 n。

输出格式

每组数据输出一行结果,表示最少需要的操作次数,如果不可能使 n 变为某个正整数的平方,则输出 −1。

数据范围

前三个测试点满足 1 ≤ n ≤ 10000。
所有测试点满足 1 ≤ T ≤ 10,1 ≤ n ≤ 2 × 10 ^ 9。

输入样例1:

1
8314

输出样例1:

2

输入样例2:

1
625

输出样例2:

0

输入样例3:

1
333

输出样例3:

-1
来源:https://www.acwing.com/problem/content/description/3799/

2. 思路分析:​​​​​​​

分析题目可以知道n最多有9位数字,因为需要删除掉某些位所以我们可以选择当前位上的数字也不选当前位上的数字(不选表示删除),也即需要搜索出所有的方案,可以使用dfs来搜索,一个分支表示选择当前的数字,另外一个分支表示不选择当前的数字,这样一定可以枚举出所有的情况,我们可以将枚举出的数字存储到vector或者是列表中,然后从大到小排序,从大的数字开始枚举判断是否是平方数字即可。

3. 代码如下:

import math
from typing import List


class Solution:
    # 求解出选还是不选当前位对应的的数字的所有情况
    def dfs(self, u: int, nums: List[str], rec: List[int], s: str):
        if u == len(nums):
            # 筛选掉空串和前导0字符串
            if s and s[0] != "0":
                rec.append(int(s))
            return
        # 选择当前位置的元素
        self.dfs(u + 1, nums, rec, s + nums[u])
        # 不选择当前位置的元素
        self.dfs(u + 1, nums, rec, s)

    def process(self):
        T = int(input())
        for i in range(T):
            n = int(input())
            nums = list()
            t = n
            # 求解出n的每一位数字将其按照顺序插入到nums中
            while t > 0:
                nums.insert(0, str(t % 10))
                t //= 10
            rec = list()
            self.dfs(0, nums, rec, "")
            # 从大到小排序, 排在前面的肯定是长度比较长的
            rec.sort(reverse=True)
            flag = 0
            for x in rec:
                a = int(math.sqrt(x))
                if a * a == x:
                    print(len(str(n)) - len(str(x)))
                    flag = 1
                    break
            if not flag: print(-1)


if __name__ == "__main__":
    Solution().process()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值