超级回文数

 如果一个正整数自身是回文数,而且它也是一个回文数的平方,那么我们称这个数为超级回文数。 现在,给定两个正整数 L 和 R (以字符串形式表示),返回包含在范围 [L, R] 中的超级回文数的数目。https://leetcode-cn.com/problems/super-palindromes/

回文数: 就是正序读和反序读是同一个数字, 比如121, 正序是"121", 反序还是"121", 这样就是回文数.

 输入:L = "4", R = "1000"

 输出:4

 解释:

 4,9,121,以及 484 是超级回文数。

 注意 676 不是一个超级回文数: 26 * 26 = 676,但是 26 不是回文数。

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


最简单直观的想法, 就是按照要求开始处理, 枚举出[L,R]之间的值, 然后判断是否符合要求, 统计即可, 

有个小地方需要注意, 循环的开始是从 "根号L" 开始的, 到 "根号R"结束. 

#if os(Linux)
import Glibc
#else
import Darwin
#endif

class Solution {

    func superpalindromesInRange(_ L: String, _ R: String) -> Int {
        let lNum = Int64(L)!
        let rNum = Int64(R)!
        var array = [Int64]()

        let beginNum = Int64(sqrt(Double(lNum)))
        for i in beginNum ..< rNum {
      
            guard isKeyNum(num: i) else {
                continue
            }
            
            let res = i*i
            guard res<=rNum else {
                break
            }
            guard res>=lNum else {
                continue
            }
            
            if isKeyNum(num: res) {
                array.append(res)
            }
            
        }
        
        print(array)
        return array.count
    }
    
    // 是否是回文数
    func isKeyNum(num: Int64) -> Bool {
        
        let str = String(num)
        let reverStr = str.reversed()
        if str.elementsEqual(reverStr) {
            return true
        }
        return false
    }
    
    
}

超时了, 看来是R给的太大了, 导致循环次数太多, 要是能通过计算找出下一个回文数就会好很多, 这样就是跳步循环, 应该就不会超时.

对暴力法不服气, 凭什么超时啊, 专门测试了一下时间

Int32.max(大约2.1亿) 需要0.083秒
10^10 需要0.143秒
10^12 需要1.317秒
10^13 需要3.987秒
10^14 需要12.752秒
10^15 需要40秒
10^18 需要22分钟, 这个只执行了一次, 10^15次方需要循环10^7.5次, 10^18次方需要循环10^9次, 
多了10^1.5次, 也就是大约31倍, 40*31=1240s ≈ 20.6分钟, 符合预期

好吧, 想办法计算出下一个回文数字吧, 经过一番尝试后, 没什么思路, 看了LeetCode上的题解, 又比较复杂, 感觉也是不太好处理, 逼良为娼, 那还是用点奇淫技巧吧, 用暴力法把从1~10^18之间的超级回文数列出来, 然后判断[L,R]直接有几个数字.    查表法,真香!~

class Solution {
    
    func superpalindromesInRange(_ L: String, _ R: String) -> Int {
        let lNum = Int64(L)!
        let rNum = Int64(R)!

        var array = [1,4,9,121,484,10201,12321,14641,40804,44944,1002001,1234321,4008004,100020001,102030201,104060401,121242121,123454321,125686521,400080004,404090404,/*前int32的结果*/10000200001,10221412201,12102420121,12345654321,40000800004,1000002000001,1002003002001,1004006004001,1020304030201,1022325232201,1024348434201,1210024200121,1212225222121,1214428244121,1232346432321,1234567654321,4000008000004,4004009004004,100000020000001,100220141022001,102012040210201,102234363432201,121000242000121,121242363242121,123212464212321,123456787654321,400000080000004,10000000200000001,10002000300020001,10004000600040001,10020210401202001,10022212521222001,10024214841242001,10201020402010201,10203040504030201,10205060806050201,10221432623412201,10223454745432201,12100002420000121,12102202520220121,12104402820440121,12122232623222121,12124434743442121,12321024642012321,12323244744232321,12343456865434321,12345678987654321,40000000800000004,40004000900040004]
        
        var count = 0
        
        for i in array {
            
            if i>=lNum && i<=rNum {
                count += 1;
            }
            
        }
        return count
    }
    

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值