906. 超级回文数

news2024/11/18 19:44:36

1. 题目

906. 超级回文数

2. 解题思路

题目意思很简单,在给定范围中找到所有满足,它本身是回文,且它的平方也是回文的数字个数。
这题需要注意题目给定的范围,后面很有用:
image.png
因为回文范围是有限的,那么我们可以先初始化基础情况,也就是枚举出单个数字,和两位数字的回文。
题目要求范围大于1,那么我们枚举的基础数字就是1-9,通过下面的代码就可以初始化好基础的回文。
image.png|700

然后我们针对每个回文进行判断,它的平方是不是回文,如果是就给结果加一。
如果当前回文数的长度是偶数,继续通过在中间插入一个或两个字符(从’0’到’9’)来生成新的、更长的回文数,并将它们加入队列。这样能够递归生成长度更长的回文数。
如果当前回文数的平方已经超出了范围 [left, right],则停止处理该回文数。
最后统计结果就好了。

注意:上面的代码在LC可以通过,但是在PAT有些用例会超出内存限制,所以下面进行一版优化:
整理思路方向不变,还是通过遍历生成回文数来判断,做如下优化:

  • 直接通过构建回文数的前半部分,然后反转其一部分生成完整的回文数。这避免了逐步拼接字符串的过程,提高了效率。
  • 循环从1到10位生成回文数,并且限制了每个回文数的生成长度。通过计算有效的起始和结束范围(startend),确保生成的数字合理。
  • 在生成每个回文数的平方后,立即检查其是否超过上限 R,如果超过,立刻停止后续的生成过程。

3. 代码

3.1. 注意点

[!NOTE] 1、19行的tmp.length() > 10 这个判断条件是啥意思
[1, 10^18) 是题目给定的整数范围,超过这个范围的数值不需要再检查。而数字的长度超过10位的平方肯定超过了这个范围。
回文数长度达到11位,那么它的平方就会超过 10^22,远远超出题目要求的范围 10^18

[!NOTE] 2、24行的if (tmpNum * tmpNum < 0) 这个判断条件是啥意思
我们的tmpNum类型为Long,当tmpNum * tmpNum 的结果超过Long的最大值,那么就会溢出成负数,这种情况也没必要处理了。

[!NOTE] 3、为什么在处理当前数字为偶数的时候要插入字符,并且只插入1、2个字符,不插入3、4、5…个
因为回文是数字对称的,它往往可以直接在当前回文上进行插入来得到新回文,处理代码会尝试在当前偶数长度的回文数中间插入一个或两个数字,生成更长的回文数。这样做的目的是生成可能符合条件的下一个更长的回文数,并且保持回文数的对称性。

  • 插入一个 字符:生成奇数长度的回文数。例如从 "1221" 生成 "12321",这个新回文数的长度是奇数。
  • 插入两个相同的 字符:生成偶数长度的回文数。例如从 "1221" 生成 "123321",这个新回文数的长度是偶数。
    这种方式已经覆盖了常见的奇数和偶数长度回文数的情况,不需要再增加额外的插入方式。

[!NOTE] 4、32行统计的答案是tmp还是tmp的平方?
答案是tmpNum*tmpNum
题目定义:如果一个正整数自身是回文数,而且它也是一个回文数的平方,那么我们称这个数为超级回文数。
所以tmpNum*tmpNum代表它是tmpNum的平方,所以tmpNum*tmpNum才是超级回文数

3.2. 完整代码

class Solution {
    public int superpalindromesInRange(String left, String right) {
        Long l = Long.parseLong(left);
        Long r = Long.parseLong(right);
        int res = 0;
        String[] strs = {
            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
        };
        Queue < String > queue = new LinkedList < > ();

        //L 和 R 是表示 [1, 10^18) 范围的整数的字符串。 所以i从1开始
        for (int i = 1; i < 10; i++) {
            queue.offer(strs[i]);
            queue.offer(strs[i] + strs[i]);
        }

        while (!queue.isEmpty()) {
            String tmp = queue.poll();
            if (tmp.length() > 10) {
                continue;
            }
            Long tmpNum = Long.parseLong(tmp);
            //处理溢出情况,tmp的平方有可能会大于Long的最大值
            if (tmpNum * tmpNum < 0) {
                continue;
            }
            if (tmpNum * tmpNum <= r) {
                StringBuilder sb = new StringBuilder();
                sb.append(tmpNum * tmpNum);
                //判断当前数字的平方是不是回文
                if (tmpNum * tmpNum >= l && sb.toString().equals(sb.reverse().toString())) {
                    res++;
                }
                if (tmp.length() % 2 == 0) {
                    //向当前回文数插入数字构造新的更长的回文数
                    for (String c: strs) {
                        queue.offer(tmp.substring(0, tmp.length() / 2) + c + tmp.substring(tmp.length() / 2));
                        queue.offer(tmp.substring(0, tmp.length() / 2) + c + c + tmp.substring(tmp.length() / 2));
                    }
                }
            }

        }
        return res;
    }
}

3.2.1. PAT完整代码

[!NOTE] 解释下新的核心代码,即17行开始的for循环
1、外层循环for (int length = 1; length <= 10; length++) :代表生成1-10位的回文数,为啥是10位呢?
题目要求的范围是[1, 10^18) ,10位数的平方已经超过这个范围了
2、起始和结束范围:通过计算范围来确定生成的数字范围,比如长度为2,那范围就是10-99

  • 计算起始值
  • int start = (int) Math.pow(10, halfLength - 1);
  • 这行代码计算当前半长度的最小值。
  • 例如:
  • halfLength = 1start = 10^0 = 1,表示从1开始。
  • halfLength = 2start = 10^1 = 10,表示从10开始。
  • halfLength = 3start = 10^2 = 100,表示从100开始。
  • 计算结束值int end = (int) Math.pow(10, halfLength);
  • 这行代码计算当前半长度的下一个值(不包括在内,通过for循环的结束条件来控制不包括在内)。
  • 例如:
  • halfLength = 1end = 10^1 = 10,表示到9为止。
  • halfLength = 2end = 10^2 = 100,表示到99为止。
  • halfLength = 3end = 10^3 = 1000,表示到999为止。

3、生成回文数
循环遍历从 startend 的所有数,构建回文数:

  • firstHalf 是前半部分(例如,123 的前半部分是 12)。
  • secondHalf 是前半部分的反转(例如,12 反转为 21),并与前半部分拼接成完整的回文数(例如,121)。

4、后续处理:
后续就判断该数字是否超过题目范围,以及它的平方数是不是回文,如果是,那它的平方数就是一个超级回文数
5、int halfLength = (length + 1) / 2为什么要加一
它为了处理奇数长度的情况,确保在生成回文时能够正确地获取中间的数字。例如,对于长度为 5 的回文,(5 + 1) / 2 结果为 3,这样可以包含中间的数字。
6、square > R后为什么直接break?
和LC的解法不同,PAT的解法是直接从小到大遍历的,当前的数据超出范围了,它后面的数据比它大,肯定也会超出范围,所以直接break
7、为什么firstPath.substring(0,length/2)不是firstPath.substring(0,firstPath.length()/2)
image.png

import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        List<Long> in = Arrays.stream(sc.nextLine().split(","))
            .map(Long::valueOf)
            .collect(Collectors.toList());
        long L = in.get(0);
        long R = in.get(1);

        List<Long> res = new ArrayList<>();
        
        // 从1到10位的数字开始生成回文数
        for (int length = 1; length <= 10; length++) {
            int halfLength = (length + 1) / 2;
            //Math.pow:10的halfLength - 1次方
            int start = (int) Math.pow(10, halfLength - 1);
            int end = (int) Math.pow(10, halfLength);
            
            for (int i = start; i < end; i++) {
                String firstHalf = Integer.toString(i);
                StringBuilder secondHalf = new StringBuilder(firstHalf.substring(0, length / 2)).reverse();
                
                String palindrome = firstHalf + secondHalf.toString();
                long num = Long.parseLong(palindrome);
                long square = num * num;
                
                if (square > R) {
                    break; // 剪枝:平方数超过R时停止
                }
                if (square >= L && isPalindrome(Long.toString(square))) {
                    res.add(square);
                }
            }
        }
        
        Collections.sort(res);
        System.out.println(res);
    }
    
    // 判断是否是回文数
    private static boolean isPalindrome(String s) {
        int left = 0;
        int right = s.length() - 1;
        while (left < right) {
            if (s.charAt(left) != s.charAt(right)) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2175329.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++(9.26)

1.什么是虚函数&#xff0c;什么是纯虚函数 虚函数是在基类中声明为virtual的函数&#xff0c;可以被重新定义来实现多态&#xff0c;纯虚函数则是以0结尾的虚函数&#xff0c;是没有实现的虚函数。 2.基类为什么需要虚构析函数 为了防止在后面delete释放空间时导致溢出 数据…

【IPV6从入门到起飞】5-6 IPV6+Home Assistant(ESPHome+ESP-cam)实时监控

5-6 IPV6Home Assistant[ESPHomeESP-cam]实时监控 1、背景2、ESPHome 安装2-1 ESPHome 简述2-2 安装 3、创建ESP32-CAM设备4、编辑yaml配置4-1 找到合适的配置4-2 修改配置4-3 验证配置4-4 编译项目 5、烧录固件6、绑定设备7、效果实现 1、背景 在前面我们已经实现了数据采集与…

【Python游戏开发】扫雷游戏demo

准备步骤 项目开发使用【Mu 编辑器】 1.使用Mu编辑器创建新项目 2.点击【保存】&#xff0c;将项目保存到指定路径中 3.点击【图片】&#xff0c;会打开项目图片存储位置&#xff0c;将所需图片复制粘贴至该文件夹中 游戏编写 1.设置游戏场景 ROWS 15 # 设置行数 COLS …

【面试题】软件测试实习(含答案)

软件测试实习常见面试题&#xff0c;主要是功能测试相关的基础问题 目录 一、软件测试基础 1、介绍一下你最近的项目&#xff0c;以及工作职责 2、软件项目的测试流程? 3、黑盒测试与白盒测试的区别? 4、黑盒测试常见的设计方法?怎么理解等价类方法和边界值方法 1&…

GO语言环境搭建和字符说明

Go的三种安装方式 Go有多种安装方式&#xff0c;你可以选择自己喜欢的。这里我们介绍三种最常见的安装方式&#xff1a; 1.Go源码安装&#xff1a;这是一种标准的软件安装方式。对于经常使用Unix类系统的用户&#xff0c;尤其对于开发者来说&#xff0c;从源码安装是最方便而…

传奇架设教程:传奇登录器公告窗口如何设置?link.htm网页文件制作教程

今天给大家分享传奇登录器公告窗口的设置教程&#xff1a; 我们玩服时可以看到很多服的登录器公告看上去都很高大上&#xff0c;并且窗口比例也非常的合适&#xff0c;但是自己架设起来并没有看到窗口公告&#xff0c;这是为什么呢&#xff1f; 这是因为你的列表没有设置公告…

计算机视觉中的2D变换:用Python让图像‘动’起来

嘿&#xff0c;小伙伴们&#xff01;今天我们要聊的是计算机视觉中的2D变换——那些能让图像‘动’起来的技术。无论你是初学者还是资深开发者&#xff0c;这篇文章都将带你深入了解2D变换&#xff0c;并通过Python代码实战演示。准备好了吗&#xff1f;让我们开始吧&#xff0…

Humans or LLMs as the Judge? A Study on Judgement Bias

文章目录 题目摘要引言相关作品论法官的偏见实验方案结果与讨论欺骗LLM法官结论 题目 人类还是LLMs作为裁判&#xff1f;判断偏差研究 论文地址&#xff1a;https://arxiv.org/pdf/2402.10669 摘要 采用人类和大型语言模型(LLM)作为评估LLM性能的评判者(也称为人类和LLM-as-a…

多车合作自动驾驶框架CoDrivingLLM:基于大语言模型驱动的决策框架

Abstract 目前&#xff0c;全球范围内已开始对联网自动驾驶汽车&#xff08;CAVs&#xff09;进行道路测试&#xff0c;但它们在复杂场景中的安全性和效率表现仍不令人满意。合作驾驶利用CAVs的连接能力&#xff0c;通过协同作用超越个体表现&#xff0c;使其成为在复杂场景中…

MySQL篇(主从复制/读写分离/分库分表)(持续更新迭代)

目录 讲解一&#xff1a;主从复制 一、何为主从复制&#xff1f; 二、主从复制的优点 三、主从复制原理 四、主从复制环境搭建 1. 准备 2. 主库配置 2.1. 修改配置文件 /etc/my.cnf 2.2. 重启MySQL服务器 2.3. 授予主从复制权限 2.4. 查看二进制日志坐标 3. 从库配置…

ubuntu 安装harbor

#安装包 wget https://github.com/goharbor/harbor/releases/download/v2.10.3/harbor-offline-installer-v2.10.3.tgz wget https://github.com/goharbor/harbor/releases/download/v2.10.3/harbor-offline-installer-v2.10.3.tgz.asc#导入签名公钥 gpg --keyserver hkps://ke…

EDM平台大比拼 用户体验与营销效果双重测评

本文评测了ZohoCampaigns、Mailchimp、Sendinblue、AWeber四款EDM平台&#xff0c;分别适合中小企业、多平台集成、多功能集成、初学者等需求。建议企业根据自身规模、技术水平和功能需求选择最适合的平台。 一、Zoho Campaigns 功能概述 Zoho Campaigns是Zoho旗下的一款专注…

每日OJ题_牛客_拼三角_枚举/DFS_C++_Java

目录 牛客_拼三角_枚举/DFS 题目解析 C代码1 C代码2 Java代码 牛客_拼三角_枚举/DFS 拼三角_枚举/DFS 题目解析 简单枚举&#xff0c;不过有很多种枚举方法&#xff0c;这里直接用简单粗暴的枚举方式。 C代码1 #include <iostream> #include <algorithm> …

探索RAG、AI Agents和Agentic RAG的架构、应用程序和主要区别

人工智能催生了能够执行各种任务的强大模型。该领域最具影响力的两项进步是检索增强生成 (RAG) 和Agents&#xff0c;它们在改进AI驱动的应用程序中发挥着独特的作用。然而&#xff0c;新兴的Agentic RAG概念提出了一种利用两种系统优势的混合模型。Agentic RAG是什么&#xff…

UML中类和类之间关系和各种图

文章目录 1.UML概述2.UML建模工具3.常见UML图_类图4.类图之类和类之间的关系5.用例图1.用例图是什么2.用例图所包含的元素3.用例图所包含的关系 6.状态图1.状态图是什么&#xff1f;2.状态图所包含的元素 7.活动图1.活动图的元素 8.时序图1.时序图是什么&#xff1f;2.时序图的…

混合密码系统——用对称密钥提高速度,用公钥密码保护会话密钥

混合密码系统&#xff08;Hybrid Cryptosystem&#xff09;是一种结合了多种密码学技术和算法的加密方案&#xff0c;旨在充分利用不同密码算法的优势&#xff0c;以提供更强大的安全性、更高的效率或更好的功能特性。以下是对混合密码系统的详细解释&#xff1a; 组成要素 对…

操作系统与进程

1.操作系统 操作系统是计算机中的一个重要软件&#xff0c;它是一个专门进行管理的软件。操作系统可以通过驱动程序来间接管理外部硬件&#xff0c;也可以为计算机中的程序提供一个稳定的运行环境&#xff0c;从而来方便管理各种程序的运行&#xff0c;让程序之间的运行互不影…

用于探索和测试API的开源IDE工具-Bruno

1、前言 在进行软件开发与测试过程中&#xff0c;无论是开发人员还是测试人员&#xff0c;都会或多或少地进行接口调试与接口测试。尤其针对那种测试流程规范性很高的项目&#xff0c;测试人员进行接口测试是不可或缺的一部分。而这其中&#xff0c;大多数都会使用 Postman 作…

.Net 基于IIS部署blazor webassembly或WebApi

1.安装IIS(若安装&#xff0c;请忽略) 选择:控制面板–>程序–>程序和功能 选择:启动或关闭Windows功能&#xff0c;勾选相关项&#xff0c;再点击确定即可。 2.安装Hosting Bundle 以.net6为例&#xff0c;点击连接https://dotnet.microsoft.com/en-us/download/dot…

免费的录屏软件有哪些?可以试试这4款。

录屏软件已经被用于很多的领域和场景当中&#xff0c;能够帮助我们进行在线教学&#xff0c;线上培训&#xff0c;游戏直播与分享&#xff0c;视频记录等等。并且很多的录屏软件都有免费的功能&#xff0c;它们让大家的录屏变得更加的方便。如果大家需要录屏工具的话&#xff0…