【番外】刷题、面试可能用到的小技巧(3)

256 阅读2分钟

掘金更文挑战

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情


空间限制下的整型溢出判断

字符串转换为整型是常见的题目情景,一般来说,我们会这样拼接数字:

int p = 0;
int ans = 0;
while(p < s.length()){
    ans *= 10;
    ans += (s.charAt(p) - '0');
}

ans 初始化为0,并在循环中先乘十再加上新的数位,是一个比较优雅的小技巧,因为遍历到最后一位就不需要乘十了。

如果题目到此位置的化,就是一道比较 字符串相关的简单题了。

如果是中等题的化,会将数据输入的范围扩大,如给出超越32位有符号数极限的数字,并规定越界输出。

通常情况下只需要用long类型粗暴的比较一下就好了,但如何在只是用int变量即32位有符号数)的同时,优雅的判断溢出呢?

只需要在循环过程中这么做:(向上溢出输出最大值,向下溢出输出最小值)

int sign = 1; //sign 从字符串的正负号中得出
int p = 0;
int ans = 0;
int p = 0;
while(p < n){
            char c = str.charAt(p);
            if(c <= '9' && c >= '0'){
                //累加之前判断ans是否已经过大了 不然再判断要累加的数。
                if(ans > (Integer.MAX_VALUE / 10) || 
                   (ans == (Integer.MAX_VALUE / 10) && (c-'0') > Integer.MAX_VALUE % 10)){
                   //Integer.MAX_VALUE % 10 其实就是 7.
                    if(flag == 1) return Integer.MAX_VALUE;
                    else return Integer.MIN_VALUE;
                }
                ans *= 10;
                ans += c - '0';
                p++;
            }
  }

这个技巧十分简单,符合直觉。鉴于在做题的时候,这种题目通常会给字符串里面加入乱七八糟要判断的东西,比如字母符号空格,规定一些奇怪的东西如连字符表示连接数字等等规则。能熟记这个小技巧的话,真遇到了这样的题目就能更专心模拟题目条件了。

除法取整公式

Java的整数除法本身相当于向下取整,可以使用以下公式快速计算向上取整。

以 m/n 为例, Java m/n 本身输出为商向下取整的值,设f(x)向上取整,g(x) 为向下取整
有 f(m / n) = g((m + n - 1) / n)

取整函数.jpg

注意,图中被取整的是x的值,相当于函数括号中的数。

f(m / n) = g((m + n - 1) / n) = g((m-1) / n) + 1

根据取整的意义,显然,n 可以提取出来,表现在图中相当于向下取整函数整体上移 1。

此时函数图像已经基本重合,只差边界,即 x 取整数的时候(就是图中的圈圈们)。

只需证明,(m-1) / n只会在(m/n)取整数值的时候(也就是x取整数值的时候),使得g(x)减小1,即可。

由于m、n均为整数,可设 m = k*n + b (b>0)

所以可以得出:

m == k*n的时候,m-1 = (k-1)*n + (n-1)

m == k*n + b的时候,m-1 = k*n + b-1。由于b>0,不会影响g(m-1/n)的值。