zoukankan      html  css  js  c++  java
  • [Java] [刷题] Excel地址转换

    题目

    将一个整数转换为Excel的列号,整数范围为[1, 2147483647]。

    Excel的单元格中,列号表示如下:
    A表示第1列,
    B表示第2列,
    Z表示第26列,
    AA表示第27列,
    AB表示第28列,
    BA表示第53列,
    ……

    I/O 样例1 样例2
    输入 26 2054
    输出 Z BZZ

    来源

    蓝桥杯2012年高职高专组JAVA组 决赛第4题
    蓝桥杯2012年高职高专组C语言组 决赛第3题

    解题思路

    从题目附加描述中的“列号”可以看出,这一题应该用“进制转换”的解法,即除n求余倒插(n为进制数),但这题的坑在于——Excel的列号没有0

    十六进制符号有0到F十六个,分别代表0到15;Excel列号的符号有A到Z二十六个,按描述来说分别代表1到26,显然没有0。没有0的话不能按常规进位制算法处理,于是在前期将A到Z对应成0到25,再在后期“+1”,对应回原来的1到26。

    假设在前期的处理中,A对应0,Z对应25,那么Z+1(即25+1==26)对应什么呢?再进一步,假设此时存在列号“AA”,那么它的两个A是代表十进制数的0还是1呢?

    那么对题目附加描述进行分析,可以得到下表:

    列号 十进制数 分解算式 分解算式++
    A 1 1 26 * 0 + 1 * 1
    B 2 2 26 * 0 + 1 * 2
    AA 27 26+1 26 * 1 + 1 * 1
    AB 28 26+2 26 * 1 + 1 * 2
    BA 53 52+1 26 * 2 + 1 * 1

    按照正常进制算法用短除法分析样例中的2054,得到
    2054 == 676*3 + 26*1 + 1*0,对照ASCII表得到的CA@DBA都是错的。

    因为Excel的列号没有0,于是按照进位制的思想向前借一,得到
    2054 == 676*3 + 26*0 + 1*26,仍然有0。

    于是再向前借一,得到
    2054 == 676*2 + 26*26 + 1*26,对照ASCII表得到BZZ,正确!

    我的实现

    package top.qlin.leo;
    import java.util.Scanner;
    
    public class Main {
        /** ASCII表中字符A的前一个字符,代表进位制中的0。用于判断分解的结果中是否有0。 */
        final static char FLAG = 'A' - 1;
    
        public static void main(String[] args) {
            // 使用Scanner从输入流中获取等待被转换为Excel的整数num:
            Scanner sr = new Scanner(System.in);
            int num = sr.nextInt();
            sr.close();
    
            // 为了提升效率,使用StringBuffer存放结果:
            StringBuffer n26bf = new StringBuffer();
    
            // N进制转十进制的算法:
            // 将整数num除以二十六进制的进制数26,将余数转换为字母,插入到StringBuffer的位置0中(即先出现的余数放到结果的右端,后出现的余数放到左端);将商作为整数num送入下一循环再次运算。
            while (num > 0) {
                n26bf.insert(0, (char) ((num % 26) + 64));
                num /= 26;
            }
    
            // 将结果转换为字符数组:
            char[] n26cs = n26bf.toString().toCharArray();
    
            // 从结果的右端(最后一位数)循环遍历到左端(第二位数),若有0则向前借一:
            for (int i = n26cs.length - 1; i > 0; i--) {
                if (n26cs[i] == FLAG) {
                    n26cs[i] += 26;
                    n26cs[i - 1]--;
                }
            }
    
            // 借位完毕后,如果第一位为0,则只需从第二位开始输出。
            if (n26cs[0] == FLAG) {
                System.out.print(String.valueOf(n26cs).substring(1, n26cs.length));
            } else {
                System.out.print(String.valueOf(n26cs));
            }
        }
    }
    
    本文为博主原创,禁止转载或摘编。
  • 相关阅读:
    ASP.NET MVC中多种ActionResult用法总结
    jQuery中异步操作对象Deferred
    jQuery中bind方法和live方法区别解析
    深入理解Javascript中this, prototype, constructor
    SQL及常见的三种类型注释
    SQLServer的两个日期相减(间隔)datediff函数
    SQLServer查询进程与死锁语句
    SqlServer获取当前日期的详细写法
    SQL中 Decode 和 Sign 语法的简单用法
    数据仓库模型之CDM、LDM与PDM的区别
  • 原文地址:https://www.cnblogs.com/aixcyi/p/12218093.html
Copyright © 2011-2022 走看看