跟孙哥学java
数组实现加法专题
数字加法,小学生都会的问题,但是如果让你用数组来表示一个数,如何实现加法呢?理论上仍然从数组 末尾向前俟着计算就行了,但是实现的时候会发现有很多问题,例如算到A[O]位置时发现还要进位该怎么 办呢? 再拓展,假如给定的两个数,一个用数组存储的,另外一个是普通的整数,又该如何处理? 再拓展,如果两个整数是用字符串表示的呢?如果要按照二进制加法的规则来呢?
数组实现整数加法
加一
先看一个用数组实现逐个加一的问题。LeetCode66.具体要求是由整数组成的非空数组所表示的非负整
数,在其基础上加一。这里最高位数字存放在数组的首位,数组中每个元素只存储单个数字。并且假设除
了整数0之外,这个整数不会以零开头。例如:
:::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。
这个题也是用字符串来表示数据的,也要先转换为字符数组。我们熟悉的十进制,是从各位开始,逐步向
高位加,达到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^×。
第一种方法自然还是数学方法一直除,代码如下:
class Solution {
public boolean isPowerOfFour(int n) {
if(n<=0) return false;
while (n%4==0){
n/=4;
}
return n==1;
}
}