该部分主要对于一些数字处理和数学问题进行归纳总结,一些小技巧在算法题中往往能发挥巨大作用,此外对于面前的回文数字(非回文字符串)判断进行再次巩固并使用全新判断方法;对于进制问题,我们给出解题模板,指出模板中需要注意的特例情况;此外,我们还对溢出问题再次进行复盘,足以见得溢出问题其重要程度。
休息14天,那么接下来,请踏踏实实认认真真开始学习,业精于勤!
在整数反转过程中,难免有溢出现象发生,比如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;
}
回文数字,回文字符串本质是同一类东西,判断回文数字可以视作判断回文字符串问题进行解决,其思路方法相当成熟,就是将字符串进行反转,然后判断两个字符串是否相等即可!
当然,如果回文数字不按照字符串进行处理,而是就按照数字进行处理,当处理到非回文数字的时候可能反转过程中就会发生溢出问题,有没有什么好的解决办法?
令人振奋的是,方法存在,且是模板!我们可以仅反转该数字串的后半部分,判断数字串的前半部分和反转部分是否相等即可!
但是,怎么界定何时达到数字串的中间,即区分数字串的前半部分和后半部分呢?答:比较当前数字串和反转数字串的大小即可,仅当当前数字串>反转数字串时,数字串还未处理到中间。
比如,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;
}
怎么将一个数字转化成七进制数字,最好的办法就是短除法,然后将余数从下至上排列。存储余数的时候是从上至下存储的,因此需要将其反转!
那么如何处理负数呢?按照正数来处理,最后处理符号,比如-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.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,拜拜,第十三关第二幕见!