大于或等于x的等差数是多少?

本文解析了一道京东笔试中的难题,涉及如何找到大于或等于给定数x的最小等差数。解题关键在于理解等差数的定义,通过枚举位差和数字长度构建等差数,确保每个位数遵循规则。算法步骤包括遍历位差、检查合法性,并可能调整最高位。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大于或等于x的等差数是多少?

提示:京东20220416笔试题
京东笔试的风格:
30个选择题,各个都难,要求基础贼深,这个需要去百度的(2分一个)=60分
2个算法题(20分一个)=40分 算法题是真的难!!!平时不好好练习准备,临场啥也做不出来。


题目

题目1–小明觉得“等差数”是一类非常妙的数字,这类数字定义如下:
是十进制下的数字,
设这个数字有n位,di表示该数从低位到高位的第i位,则由d2-d1=d3-d2=…=dn-dn-1.特别地,n=1也是等差数。
例如:10,2345,5432,111,9,0,86420,94是等差数,而233,114514,2356,1325,124则不是等差数。
小明随手写了一个数字x,他想知道,大于或等于x的最小的等差数是多少?
输入:第一行一个整数T,表示有T组数据,每一组数据,输入一行一个非负整数x。0<=x<10^17,1<=T<=100;
输出:对于每一组数据,输出一行一个十进制数,表示答案。
样例输入:
5
100
0
152
233
212
输出:
111
0
159
234
222


一、审题

示例:互联网大厂的题目输入描述和输出描述与样例就是审题细节,讲得很清楚。


二、解题

考试当时我完全没有思路,所以算法题一个都不会
后来在牛客网上见到一个大佬的解法,觉得很有道理:

答题作者:青少年心理健康专家–链接:来源:牛客网

第一题思路:
称等差数前一位减后一位的差为位差,所有等差数的位差都在 [-9,9] ,如果确定了一个等差数的位差、任意一位的数字和这个数的长度,就可以确定这个数。
如等差数首位为8,长度为4,位差为-2,则这个数为8642
输入的数字是a,要找大于等于这个数的等差数b
首先可以b的最高位一定是大于或等于s的(我理解这个s就是a的最高位),且长度等于a(不管a是什么,总可以找到999…9这样的和a等长的等差数)【这里很关键,不管如何,b一定与a等长的,大不了1变2,变变变,到最高位9999…9这样的数】

对于b的每一个最高位s,往后每一位怎么取值?
b最高位等于a最高位s,位差从-9到9开始遍历(首位相同时位差越小这个数就越小),
每次同一个等差,从高位到低位,把b的前面一位+d作为b本位的值,然后看合法与否?直到找到一个合法的等差数就是答案。
不合法的情况:

  1. 某一位的数字小于0或大于9 【这有用,因为往后面找,一旦数字小于0,就违规,或者超过9,那就要重新用一个d】
  2. 数值小于a

关键点
如果找不到合法的等差数,尝试下一种位差d;
如果所有的位差到了9还是不合法,只能令b的最高位加1再重复上面的过程!!【也即让最外面一层for循环,尝试b的最高位从a的最高位s–9走一遍】

图1

注意,实际调试代码的时候,可能会遇到11111这种,d0,判断到N-1位时,都能满足所有d0,那就是它,不需要往上+1了。
还会遇到一个特殊情况,比如212这种,找到221了,那前面d=0,但是最后这个1
代码:

public static class Main {
        public static void main(String[] args) {
            Scanner in = new Scanner(System.in);
            // 注意 hasNext 和 hasNextLine 的区别
            int T = in.nextInt();
            while (T != 0){
                process();
                T--;
            }
        }

        public static void process(){
            //读一个数,干一次,输出一个结果
            Scanner in = new Scanner(System.in);
            // 注意 hasNext 和 hasNextLine 的区别
            String str = in.next();
            //找>=x的等差数
            //数为2位,1位原数就是
            int N = str.length();

            if (N <= 2) {
                System.out.println(str);
                return;
            }

            //至少3位数
            char[] arr = str.toCharArray();
            int[] ans = new int[N];//最终长度也是相同的,大不了来一个全数字一样的数999...999
            //int d = arr[0] - arr[1];//高位-地位,永远在-9--9之间
            for (int i = 0; i <= 9; i++) {
                //枚举最高位需要在arr基础上增加的数字,最多99999
                ans[0] = arr[i] - '0' + i;
                //遍历ans的后面每一位,值是前面值+d,d取-9--9之间
                for (int d = -9; d <= 9; d++) {
                    String tmp = String.valueOf(ans[0]);//记录目前构成的新数字为字符串
                    for (int j = 1; j < N; j++) {
                        ans[j] = ans[j - 1] + d;//构成等差
                        tmp += String.valueOf(ans[j]);

                        if (ans[j] < 0 && ans[j] > 9 ||
                                (j == N - 1 && tmp.compareTo(str) < 0)) {
                            break;//不合法,重新尝试下一个等差d
                        }else if (j == N - 1 && tmp.compareTo(str) >= 0){
                            if (d == 0 && ans[N - 1] != ans[N - 2]){
                                //2221这种
                                ans[N - 1] = ans[N - 2];//构成等差22222
                                tmp = tmp.substring(0, N-1) + String.valueOf(ans[N-1]);//截取,加
                                System.out.println(tmp);
                                return;
                            }else if (d == 0 && ans[N - 1] == ans[N - 2]){
                                System.out.println(tmp);//d=0的话,111这种
                                return;
                            }
                            //
                            if (d != 0 ){
                                System.out.println(tmp);//d不是0的话,必然是1234,5432这种
                                return;
                            }
                        }
                    }
                }
            }
            return;
        }

总结

提示:重要经验:

1)基础不牢,地动山摇!!!好好练习根基的算法代码,关于数字这方面的题目,多积累
2)每次遇到不会的题,找大佬的思路,学,自己coding,练习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰露可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值