数字与数学高频问题

32 阅读7分钟

跟孙哥学java

孙哥主页

数组实现加法专题

数字加法,小学生都会的问题,但是如果让你用数组来表示一个数,如何实现加法呢?理论上仍然从数组 末尾向前俟着计算就行了,但是实现的时候会发现有很多问题,例如算到A[O]位置时发现还要进位该怎么 办呢? 再拓展,假如给定的两个数,一个用数组存储的,另外一个是普通的整数,又该如何处理? 再拓展,如果两个整数是用字符串表示的呢?如果要按照二进制加法的规则来呢?

数组实现整数加法

加一 先看一个用数组实现逐个加一的问题。LeetCode66.具体要求是由整数组成的非空数组所表示的非负整 数,在其基础上加一。这里最高位数字存放在数组的首位,数组中每个元素只存储单个数字。并且假设除 了整数0之外,这个整数不会以零开头。例如: image.png :::info 这个看以很简单是不?从后向前依次加就行了,如果有进位就标记一下,但是如果到头了要进位怎么办 呢? 例如如果digits=[9,9,9],从后向前加的时候,到了A[O]的位置计算为0,需要再次进位但是数组却不能保 存了,该怎么办呢? 这里的关键是A[O]什么时候出现进位的情况,我们知道此时一定是9,99,999.…这样铂的结构才会出现加1之 后再次进位,而进位之后的结果一定是10,100,1000这样的结构,由于jva中数组默认初始化为0,所以 我们此时只要申请一个空间比A大一个的数组B0,然后将B[O]设置为1就行了。这样代码就会变得非常简 洁。 如果是其他语言,则要注意先将申请的数组初始化为零再执行,代码如下: :::

class Solution {
    public static void main(String[] args) {
        int[] digits={9,8,7,6,5,4,3,2,1,0};
        System.out.println(plusOne(digits));
    }
    public static int[] plusOne(int[] digits) {
        int len=digits.length;

        for (int i = len-1; i >=0; i--) {
            digits[i]=digits[i]+1;
            digits[i]=digits[i]%10;
            if(digits[i]!=0){
                return digits;
            }
        }
        digits=new int[len+1];
        digits[0]=1;
        return digits;

    }
}

字符串加法

字符串加法 我们继续看将数字保存在字符串中的情况:字符串加法就是使用字符串来表示数字,然后计算他们的和。 具体要求如下:给定两个字符串形式的非负整数num1和um2,计算它们的和并同样以字符串形式返 回。你不能使用任何内建的用于处理大整数的库(比如Biglnteger),也不能直接将输入的字符串转换为 整数形式。 :::info 例如: 输入: num1="456",num2="77" 输出:"533" ::: 从低到高逐位相加,如果当前位和超过10,则向高位进一位。 因此我们只要将这个过程用代码写出来即可。先定义两个指针i和分别指向num1和um2的末尾,即最 低位,同时定义一个变量add维护当前是否有进位,然后从末尾到开头逐位相加。 这里可能有个问题:两个数字位数不同该怎么处理?简单,补0即可。具体可以看下面的代码:

class Solution {
    public String addStrings(String num1, String num2) {

        char[] chars1 = num1. toCharArray();
        char[] chars2 = num2.toCharArray();
        int i = chars1.length-1;
        int j = chars2.length-1;
        int add=0;
        StringBuilder ans=new StringBuilder();
        while (i>=0||j>=0||add!=0){
            int x=i>=0? chars1[i]-'0':0;
            int y=j>=0? chars2[j]-'0':0;
            int result=x+y+add;
            ans.append(result%10);
            add=result/10;
            i--;
            j--;
        }
        ans.reverse();
        return ans.toString();
    }
}

二进制加法

二进制加法 我们继续看,如果这里是二进制该怎么处理呢? 详细要求:leetcode67.给你两个二进制字符串,这个字符串是用数组保存的,返回它们的和(用二进制表 示)。其中输入为非空字符串且只包含数字1和0。 image.png 这个题也是用字符串来表示数据的,也要先转换为字符数组。我们熟悉的十进制,是从各位开始,逐步向 高位加,达到10就进位,而对于二进制则判断相加之后是否为二进制的10,是则进位。本题解中大致思路 与上述一致,但由于字符串操作原因,不确定最后的结果是否会多出一位进位,下面2种处理方式都可 以: ·第一种,在进行计算时直接拼接字符串,得到一个反向字符,最后再翻转。 ·第二种,按照位置给结果字符赋值,最后如果有进位,则在前方进行字符串拼接添加进位 我们这里采用第一种实现。

class Solution {
    public String addBinary(String a, String b) {
        char[] charsa = a.toCharArray();
        char[] charsb = b.toCharArray();
        StringBuilder sb=new StringBuilder();
        int i = charsa.length-1;
        int j   = charsb.length - 1;
        int add=0;
        while (i>=0||j>=0||add!=0){
            int x=i>=0?charsa[i]-'0':0;
            int y=j>=0?charsb[j]-'0':0;
            int result=x+y+add;
            sb.append(result%2);
            add=result/2;
            i--;
            j--;
        }
        return sb.reverse().toString();

    }
}

幂运算

幂运算是常见的数学运算,其形式为a^b,即a的b次方,其中a称为底数,b称为指数,ab为合法的 运算(例如不会出现=0且b≤0的情况)。幂运算满足底数和指数都是实数。根据具体问题,底数和指数 的数据类型和取值范围也各不相同。例如,有的问题中,底数是正整数,指数是非负整数,有的问题中, 底数是实数,指数是整数。 力扣中,幂运算相关的问题主要是判断一个数是不是特定正整数的整数次幂,以及快速幂的处理。

求2的幂

2的幂 LeetCode231.给你一个整数n,请你判断该整数是否是2的幂次方。如果是,返回true;否则,返回 false。 如果存在一个整数×使得n==2^×,则认为n是2的幂次方。 示例1: 输入:n=1 输出: true 解释:20=1 示例2: 输入:n=16 输出:true 解释:24=16 示例3: 输入:n=3 输出:false

class Solution {
    public boolean isPowerOfTwo(int n) {

        //n<=0, 不可能存在, 2^x>0
        if(n<=0){
            return false;
        }
        //一直除2,直到余数不为0,若n=1,说明是2^x=n
        while (n%2==0){
            n/=2;
        }
        return n==1;

    }
}

求3的幂

3的幂 leetcode326给定一个整数,写一个函数来判断它是否是3的幂次方。如果是,返回true;否则,返回 false。整数n是3的幂次方需满足:存在整数X使得n==3^x 对于这个题,可以直接使用数学方法来处理,如果n是3的幂,则>0,且存在非负整数k使得=3^k。 首先判断n是否是正整数,如果n是0或负整数,则n一定不是3的幂。 当n是正整数时,为了判断n是否是3的幂,可以连续对n进行除以3的操作,直到n不能被3整除。 此时如果n=1,则n是3的幂,否则n不是3的幂。

class Solution {
    public boolean isPowerOfThree(int n) {
        if(n<=0){
            return false;
        }
        while (n%3==0){
            n/=3;
        }
        return n==1;

    }
}

这个题的问题和上面2的次幂一样,就是需要大量进行除法运算,我们能否优化一下呢?这里有个技巧。 由于给定的输入n是int型,其最大值为2^31-1。因此在int型的数据范围内存在最大的3的幂,不超过 2^31-1的最大的3的幂是3^19=1162261467。所以如果在1~2^31-1内的数,如果是3的幂,则一定 是1162261467的除数,所以这里可以通过一次除法就获得:

class Solution {
    public boolean isPowerOfThree(int n) {
        return n>0&&1162261467%n==0;
//        if(n<=0){
//            return false;
//        }
//        while (n%3==0){
//            n/=3;
//        }
//        return n==1;

    }
}

求4的幂

4的幂 LeetCode342给定一个整数,写一个函数来判断它是否是4的幂次方。如果是,返回true;否则,返回 false。整数n是4的幂次方需满足:存在整数X使得n==4^×。 image.png 第一种方法自然还是数学方法一直除,代码如下:

class Solution {
    public boolean isPowerOfFour(int n) {
        if(n<=0) return false;
        while (n%4==0){
            n/=4;
        }
        return n==1;

    }
}