算法通关村第十三关——数字与数学青铜挑战笔记

该部分主要对于一些数字处理和数学问题进行归纳总结,一些小技巧在算法题中往往能发挥巨大作用,此外对于面前的回文数字(非回文字符串)判断进行再次巩固并使用全新判断方法;对于进制问题,我们给出解题模板,指出模板中需要注意的特例情况;此外,我们还对溢出问题再次进行复盘,足以见得溢出问题其重要程度。

休息14天,那么接下来,请踏踏实实认认真真开始学习,业精于勤!

1.溢出问题

1.1整数反转

在整数反转过程中,难免有溢出现象发生,比如int类型的范围是[-2^31,2^31-1],最大可达2147483647,反转后7463847412已经超出返回,发生溢出。

那么,如何解决溢出问题?答,使用long类型接收反转后的数字,判断其是否大于Integer.MAX_VALUE即可。如果需要判断long类型是否发生溢出呢?答:再找一个更大类型的变量存储然后比较就可以了

遗憾的是,很多算法题中,不能使用更大类型的变量,如long,那么我们应该如何解决呢?

我们可以比较214748364 7这个临界数字,如果当前数字有下一位且除去下一位后的数字临界数字数字大,一定溢出了;如果相等,则需要比较临界数字的最后一位7当前数字的下一位大小,判断是否发生越界。

坑:前面我们还总结了位运算技巧,一个数字可由二进制串组成,反转二进制串数字是否发生反转?答:未必反转!比如,1000对应数字8,反转之后0001对应数字1。

厘清思路,直接上代码!

    public static int myReverse(int x) {
        int ans = 0;
        while(x != 0){
            if(ans > Integer.MAX_VALUE / 10 || ans < Integer.MIN_VALUE / 10) return 0;
            if(ans == Integer.MAX_VALUE / 10 && (x % 10) > Integer.MAX_VALUE % 10) return 0;
            if(ans == Integer.MIN_VALUE / 10 && (x % 10) < Integer.MIN_VALUE % 10) return 0;
            ans *= 10;
            ans += (x % 10);
            x /= 10;
        }
        return ans;
    }

1.2回文数字

回文数字,回文字符串本质是同一类东西,判断回文数字可以视作判断回文字符串问题进行解决,其思路方法相当成熟,就是将字符串进行反转,然后判断两个字符串是否相等即可!

当然,如果回文数字不按照字符串进行处理,而是就按照数字进行处理,当处理到非回文数字的时候可能反转过程中就会发生溢出问题,有没有什么好的解决办法?

令人振奋的是,方法存在,且是模板!我们可以仅反转该数字串的后半部分,判断数字串的前半部分和反转部分是否相等即可

但是,怎么界定何时达到数字串的中间,即区分数字串的前半部分和后半部分呢?答:比较当前数字串和反转数字串的大小即可,仅当当前数字串>反转数字串时,数字串还未处理到中间。

比如,123321,数字串的前半部分123,后半部分321,反转后半部分123,比较反转后半部分前半部分是否相等即可!比如,1234321,数字串前半部分123,后半部分4321,反转后半部分1234,比较反转后半部分123 4(删除)前半部分是否相等!

特例情况:当数字是负数,不是回文数字;数字最后一位为0,不是回文数字,比如10;当数字就是0,是回文数字!

厘清思路,直接上代码!

    public static boolean myIsPalindrome2(int x) {
        int ans = 0;
        if(x < 0 || (x % 10 == 0 && x != 0)) return false;
        while(x > ans){
            ans = ans * 10 + (x % 10);
            x = x / 10;
        }
        return x == ans || x == ans / 10;
    }

2.进制问题

2.1七进制数

怎么将一个数字转化成七进制数字,最好的办法就是短除法,然后将余数从下至上排列。存储余数的时候是从上至下存储的,因此需要将其反转!

那么如何处理负数呢?按照正数来处理,最后处理符号,比如-9,七进制的9就是12,那么存储余数的时候,存储顺序为:21,然后加入符号,即存储顺序:21-,反转之后变成-12,也就是-9。

特例情况,0如何处理?特殊情况特殊处理,直接返回0即可,当然也可以修改while取余数的循环,前者方法已经提到多次,我们采取后者处理策略,直接上代码!

    public static String myConvertToBase7(int num) {
        StringBuilder sb = new StringBuilder();
        //符号
        boolean sign = num >= 0;
        if(!sign) num = -num;
        //对于0这一特殊情况
        do{
            sb.append(num % 7);
            num /= 7;
        }while(num != 0);
        if(!sign) sb.append("-");
        return sb.reverse().toString();
    }

2.2进制转换

2.1我们解决了七进制问题,那对于输入进制,该如何处理?简单的办法,十以上的进制单独if判断,比如13进制下,10就是a,显然这种处理方法很繁琐,甚至部分if判断条件无法使用。

小技巧:可以声明一个进制数组,用来保存进制对应的数字,然后根据当前余数,确定数组下标,最终确定应保存的字符。

直接上代码!

    public static final String[] D = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
    public static String myConvert(int M, int N) {
        boolean sign = M > 0;
        if(!sign) M = -M;
        StringBuffer buf = new StringBuffer();
        while(M != 0){
            int index = M % N;
            buf.append(D[index]);
            M /= N;
        }
        if(!sign) buf.append("-");
        return buf.reverse().toString();
    }

OK,《算法通关村第十三关——数字与数学青铜挑战笔记》结束,喜欢的朋友三联加关注!关注鱼市带给你不一样的算法小感悟!(幻听)

再次,感谢鱼骨头教官的学习路线!鱼皮的宣传!小y的陪伴!ok,拜拜,第十三关第二幕见!

你可能感兴趣的:(笔记)