试题 B: 山
本题总分:5 分
【问题描述】
这天小明正在学数数。
他突然发现有些正整数的形状像一座“山”,比如 123565321、145541,它们左右对称(回文)且数位上的数字先单调不减,后单调不增。
小明数了很久也没有数完,他想让你告诉他在区间 [2022, 2022222022] 中有多少个数的形状像一座“山”。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
又是经典的回文串问题!
看到题目的回文串需要满足两个要求:
如:123565321、145541
我们不妨从题目给出的样例出发:
123565321是以6作为分界线的情况
145541是没有分界线的情况
无论是哪种情况,我们在枚举的时候只需要枚举前一半数字即可。
为什么?
回文串的性质:左右对称
即后一半数字为前一半数字反过来
如:123565321只需枚举1235再去验证后面的数字是否是5321即可
145541只需枚举145再去验证后面的数字是否是541即可
这样我们先满足第一个回文条件。
接下来,需要去判断是否先单调不减,后单调不增
同样的这里我们只需判断前一半数字是否满足单调不减即可
如果他是回文串,前一半数字单调不减后一半数字必定是单调不增!
为什么?
因为前一半数字确保严格单调不减,后面的回文数字是将前一半反过来是单调不增!
以123565321为例:
123565321是回文串
1235单调不减反过来5321刚好是单调不增
以145541为例:
145541是回文串
145单调不减反过来541是单调不增
也就是说:
他是回文串并且前一半数字严格满足单调不减这一条件
那么后一半数字必定满足单调不增!
因此,直接求不好求,可以间接求!
只要这个数不满足单调不减这个条件或者左右对称这两个条件其中之一
我们就可以直接返回false,剩下的便是满足回文串的答案
理清思路后,我们就可以写代码了~
import java.util.*;
public class Main{
public static void main(String []args) {
Scanner sc=new Scanner(System.in);
int cnt=0;
for(long i=2022;i<=2022222022;i++) {
if(check(i))cnt++;
}
System.out.print(cnt);
}
public static boolean check(long n) {
String s=String.valueOf(n);//创建字符串
char a[]=s.toCharArray();
for(int i=0;i<a.length/2;i++) {
if(a[i]>a[i+1]||a[i]!=a[a.length-i-1]) {
//判断是否是左右对称
return false;
}
}
return true;
}
}
public static boolean check(long n) {
String s=String.valueOf(n);
char a[]=s.toCharArray();
for(int i=0;i<a.length/2;i++) {
if(a[i]<=a[i+1]&&a[i]==a[a.length-i-1]) {
return true;
}
}
return false;
}
a[i]<=a[i+1]&&a[i]==a[a.length-i-1]
这句话是对数字扫一遍找到有满足的条件便留下来:
条件可以不同步
如2110
1<=1 && 1反过来等于1 满足这一语句
2110怎么可能会是我们要的答案!
因此,我们应该用筛选式的写法筛出满足条件的数字即可
检验一下是不是满足其中之一的条件,不满足其中之一则直接返回false
其他的答案便是正确的答案。
像上面这种写法我们一定要在程序中打印一下输出回文数内容,检验一下对不对!
细心细心再细心❗️ ❗️ ❗️
https://blog.csdn.net/weixin_57943259/article/details/124125788