加
题目链接
题目描述
:
给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。
你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。
思路
:
- 创建一个进位位,从两个字符串尾部开始遍历
- 只要有一个字符串不小于0或进位位不等于0,进行-‘0’记录此个位数字,然后三数相加(进位,num1,num2)
- 大于10就把进位位置为sum/10,再往复循环
代码如下:
class Solution { public: string addStrings(string num1, string num2) { string s1; int add=0,size1=num1.length()-1,size2=num2.length()-1; while(size1>=0||size2>=0||add!=0) { int x=size1>=0?num1[size1]-'0':0; int y=size2>=0?num2[size2]-'0':0; int sum=x+y+add; s1.push_back('0'+sum%10); add=sum/10; size1--; size2--; } reverse(s1.begin(),s1.end()); return s1; } };
注意:在c++中insert非常不推荐使用,在这里反转字符串的时候用insert会把时间复杂度提到O(n^2)
减
思路
:
- 两数会有大小,为保证永远是大数-小数,可以写一个比较函数
- 设置一个结果正负标志位,先判断两输入字符大小,小数减大数标志位设为负,同时变换为大减小(swap(num1,num2))
- 按位减 (参考加法) 如果减后的数小于0,需要借位,所以需要一个借位标志位,同时小于0的数加10,最后append到字符串后面
- 总体逆置一下
乘
题目链接
题目描述
:
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
复用加法
思路
: (时间复杂度
:O(mn+n^2) m,n两字符串的长度,空间复杂度
:O(m+n))
- 做加法,以num2为乘数便利每一位,以乘法处理方式(注意加0问题)
- 每一次乘出的值
复用
加法逻辑相加
代码如下:
class Solution { public: string addStrings(string num1, string num2) { string s1; int add=0,size1=num1.length()-1,size2=num2.length()-1; while(size1>=0||size2>=0||add!=0) { int x=size1>=0?num1[size1]-'0':0; int y=size2>=0?num2[size2]-'0':0; int sum=x+y+add; s1.push_back('0'+sum%10); add=sum/10; size1--; size2--; } reverse(s1.begin(),s1.end()); return s1; } string multiply(string num1, string num2) { if(num1=="0"||num2=="0") { return "0"; } else { int carry=0,i1=num1.size()-1,i2=num2.size()-1; string sum=""; for(int i=num2.size()-1;i>=0;--i) { string ret; i1 = num1.size() - 1; while(i1>=0||carry!=0) { int x=i1>=0?num1[i1]-'0':0; int y=(num2[i]-'0'); int multi=x*y+carry; ret.push_back((multi%10)+'0'); carry=multi/10; i1--; } reverse(ret.begin(),ret.end());//注意这里不是.end()-1 int count=num2.size()-1-i;//计数添几个0 while(count--) { ret.push_back('0'); } sum=addStrings(ret,sum); } return sum; } } };
竖式乘法(优化)
思路
:
- 做乘法,由于两数相乘必为位数m+n或m+n-1,创建一个m+n大小的数组来存储,提高效率
- 通过两数相乘时,乘数某位与被乘数某位相乘,与产生结果的位置的规律来完成
代码如下
:class Solution { public: string multiply(string num1, string num2) { if(num1=="0"||num2=="0") return "0"; int max_size=num1.length()+num2.length();//两种情况 m+n,m+n-1 int i=max_size-1,j=max_size-2; vector<int> arr(max_size,0); for(int i2=num2.size()-1;i2>=0;i2--) { i=j+1; for(int i1=num1.size()-1;i1>=0;i1--) { int tmp=(num1[i1]-'0')*(num2[i2]-'0'); arr[i]+=tmp; if(arr[i]>=10) { arr[i-1]+=arr[i]/10; arr[i]=arr[i]%10; } i--; } j--; } string s=""; for(int i=0;i<max_size;i++) { if(0==i&&arr[i]==0) continue; else s+=(arr[i]+'0'); } return s; } };
龟速乘
使用场景
: 爆long long的时候比如两个long long相乘再取模a×b超过long long能表示的范围(a×b%c)
思路如下
: 类似快速幂(二进制位)
代码如下
:long long cheng(long long a, long long b,int c) { long long ret = 0; while (b) { if (b & 1) c = (ret + a) % c; a = (a + a) % c; b >>= 1; } return ret; }
除法(优化)
幂操作(快速幂)
题目链接
题目描述
:
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn),要求时间复杂度小于O(n)
思路一
:从二进制的角度---迭代(时间复杂度O(logn) 空间复杂度O(1))
(例子
: 求pow(x,77) )
- 要求时间复杂度小于O(n),必然不可以连乘x n次
- 77的二进制为(1001101)2,77=20*1 + 21*0 +22*1 + 23*1+…+ 26*1
- 将上面表达式带入x77:x77=x * x4 * x8 * x64 (1,4,8,64就是77二进制为1对应十进制)
- 当指数n为负数时,我们可以计算 x{-n} 再取倒数得到结果
代码如下
:
注意:
int负数转 正数需要精度更高的来表示
x*=x;表示x->x^2->x^4->x^8
注意x*=x;语句可能爆long long我们可以复用上面龟速乘的函数
class Solution { public: double myPow(double x, int n) { if(x==0) return 0; else if(n==0) return 1; else{ long n1=n;//int负数转 正数需要精度更高的来表示 double ret=1.0; if(n1<0)//负数处理 { n1*=(-1); x=1/x; } while(n1!=0)//不断右移,直到二进制中无1 { if((n1)&1==1) ret*=x; x*=x;//x->x^2->x^4->x^8 n1>>=1;//不断右移 } return ret; } } };
思路二
:从分治的角度---递归(时间复杂度O(logn) 空间复杂度O(logn))
- 我们可以这样(除2向下取整):77/2=38,38/2=19,19/2=9,9/2=4,4/2=2,2/2=1
指数每次乘以2
x1 ——> x2 ——> x4 —+1
—> x9 —+1
—> x19 ——> x38 —+1
—> x77- 分为两种情况:奇数和偶数,奇数/2就多出一个x,偶数就不用
- 用递归,每次指数会减少一半
代码如下(leetcode 官方解法一)
:class Solution { public: double quickMul(double x, long long N) { if (N == 0) { return 1.0; } double y = quickMul(x, N / 2); return N % 2 == 0 ? y * y : y * y * x; } double myPow(double x, int n) { long long N = n; return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N); } }; 作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/powx-n/solution/powx-n-by-leetcode-solution/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。