洛谷 P1012 [NOIP1998 提高组] 拼数 (Java,重在思路)

文章讨论了一个关于数字拼接的问题,强调首位数字在排序中的重要性。通过使用桶子数据结构按首位数字分组,然后处理相同首位数字的排序,通过补足数字长度以首位数字进行比较。提供的Java代码实现了这一逻辑,用于解决NOIP1998提高组的拼数问题。
摘要由CSDN通过智能技术生成

        想一下何为拼接,是不是数越大越往前,当然不是,应该是首位数越大越往前,这样好像也不行,那首位数相等呢,例如 5,56,那么到底怎么比较呢。

        思路:

        首位数字一定是首先考虑的问题,用首位数字的桶子就可以解决。

        那在同一个桶子里面如何进行前后顺序的拼接才是这道题的难点。

        思考一下,同一个桶子里面是不是首位数字都一样的,那拼接的时候呢,后面是不是也是拼接的首位数字呢,这就很明白了,数字的长度不一致,那么我们要把他变成一致的才能比较谁放到前面吧,那么补充的数字是什么呢,很容易就想到了,一定是首位数字呀,按照这个思路。

例子

例如

3 34 应该34 放在前面                 3补充为33,比较34大,所以34要放到前面

3 32 应该3 放在前面                  3补充为33,比较33大,所以3 要放到前面
3 334 应该334 放在前面            3补充为333,比较334大,所以334要放到前面
3 332 应该3 放在前面                3补充为333,比较333大,所以3要放到前面


那么如何判断谁放到前面呢
就要能想到 3 变成33或者是333 的操作
那要是不是1位数对多位数嗯
35 355
这个操作就是要补首位就好了 将35补充为353进行比较因为拼接到后面一定首位是3的原因

代码具体如下(本人菜鸟,勿喷)

import java.util.*;

/**
 * @Author congge
 * @Date 2023/5/13 19:06
 * @description https://www.luogu.com.cn/problem/P1012
 * [NOIP1998 提高组] 拼数
 */
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        // 存放每一个首位数字的桶子
        ArrayList<LinkedList<Integer>> nums = new ArrayList<>(10);

        for (int i = 0; i < 10; i++) {
            nums.add(new LinkedList<>());
        }

        LinkedList<Integer> bucket = new LinkedList<>();

        // 存放当前输入的数字
        int curNum;
        // 当前输入数字的长度
        int curNumLen;
        // 当前输入数字的首位数字
        int curNumFirst;

        int[] bits = new int[10];
        for (int i = 1, bit = 1; i < bits.length; i++, bit *= 10) {
            bits[i] = bit;
        }
        // 带比较数字
        int compareNum;

        // 待比较的数字长度
        int compareNumLen;

        while (n-- > 0) {
            curNum = sc.nextInt();
            curNumLen = Integer.toString(curNum).length();
            curNumFirst = curNum / bits[curNumLen];
            // 取出首位数字的桶子
            bucket = nums.get(curNumFirst);

            int size = bucket.size();

            for (int i = 0; i < size; i++) {
                int changeNum = curNum;
                int changeLen = curNumLen;
                compareNum = bucket.get(i);
                compareNumLen = Integer.toString(compareNum).length();

                // 比较哪一个放在最前面最好
                
                if (changeLen != compareNumLen) {
                    while (changeLen < compareNumLen) {
                        changeNum = changeNum * 10 + curNumFirst;
                        changeLen++;
                    }

                    while (compareNumLen < changeLen) {
                        compareNum = compareNum * 10 + curNumFirst;
                        compareNumLen++;
                    }
                }

                // 比较插入
                if (compareNum < changeNum) {
                    bucket.add(i, curNum);
                    break;
                }
            }
            if (size == bucket.size()) {
                bucket.add(curNum);
            }
        }

        StringBuilder ans = new StringBuilder();

        for (int i = 9; i >= 1; i--) {
            bucket = nums.get(i);
            for(int num:bucket){
                ans.append(num);
            }
        }
        System.out.println(ans);
    }
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值