leetcode 906. 超级回文数

1,214 阅读2分钟
如果一个正整数自身是回文数,而且它也是一个回文数的平方,那么我们称这个数为超级回文数。 现在,给定两个正整数 L 和 R (以字符串形式表示),返回包含在范围 [L, R] 中的超级回文数的数目。



输入:L = "4", R = "1000" 输出:4 解释: 4,9,121,以及 484 是超级回文数。 注意 676 不是一个超级回文数: 26 * 26 = 676,但是 26 不是回文数。  


提示:  

1 <= len(L) <= 18 

1 <= len(R) <= 18

 L 和 R 是表示 [1, 10^18) 范围的整数的字符串。

 int(L) <= int(R)  


对从[L,R] 内进行遍历,判断是否是回文数且其开平方后的数也是回文数。这种方法遍历的数过于大,会导致超时。

为减少遍历所需要的数,可以对[L,R]中每一个回文数进行遍历,判断其平方是否为回文数。

对于如何构造回文数,可以观察回文数的规律

位数为1的回文数:

1 2 3 4 5 6 7 8  ....... 9

位数为2 

11  22  33 44  ........ 99

位数为3 

101   111    121  ......    202  212  .......  999

可以得知在位数相同时,回文数的最外层数字可以为 1-9  内层为 0-9 

而且回文数递增的规律是外层数字相同下,根据内层数字大小递增。外层元素越大,回文数越大,因此可以采用递归形式,先构造1-9的最外层元素,再构造内层0-9的内层元素



代码:

    public int superpalindromesInRange(String L, String R) {
        long leftVaule = Long.valueOf(L);
        long rightVaule = Long.valueOf(R);
        long left = (long)Math.sqrt(leftVaule);
        long right = (long)Math.sqrt(rightVaule);
        int start = String.valueOf(left).length();
        int end = String.valueOf(right).length();
        int result = 0;
        //从开始范围的回文数位数开始遍历
        for(int i=start;i<=18;++i){
            ArrayList<Long> list = new ArrayList<>();
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.setLength(i);
            dfs(0,i-1,stringBuilder,list,true);
            for(long k : list){
                long tmp = k*k;
                if(tmp>=leftVaule&&tmp<=rightVaule&&isReverse(tmp))
                    ++result;
                else if(tmp>rightVaule)
                    return result;
            }
        }
        return result;
    }

    //判断是否为回文数
    public boolean isReverse(Long l){
        long tmp = l;
        long ans = 0;
        while (l>0){
            ans = ans*10 + l%10;
            l = l/10;
        }
        return tmp==ans;
    }
    //构造回文数 从外层开始
    public void dfs(int start,int end,StringBuilder string,ArrayList<Long> list,boolean op){
        //当递归到末尾时,回文数构造完成,添加进行list中
        if(start>end) {
            list.add(Long.valueOf(string.toString()));
            return;
        }
        if(op) {
            //最外层从0-9构造
            for (char i = '1'; i <= '9'; ++i) {
                string.setCharAt(start, i);
                string.setCharAt(end, i);
                dfs(start + 1, end - 1, string, list, false);
            }
        }
        else {
            //内层从1-9开始构造
            for (char i = '0'; i <= '9'; ++i) {
                string.setCharAt(start, i);
                string.setCharAt(end, i);
                dfs(start + 1, end - 1, string, list, op);
            }
        }
    }