笔试题56. LeetCode OJ (43)

Posted _从未止步

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔试题56. LeetCode OJ (43)相关的知识,希望对你有一定的参考价值。

       

 这个题是个大数乘法运算的题,两个乘数以string的形式给出,求他们相乘的结果,题目给的限制条件是:

        1.所给的数字可以任意的大,但是不为负数

        2.不能将题目所给的string转化为整数

        3.不能引入大数运算相关的库

从题目的描述中我知道了这个题让我们自己去实现大数运算的乘法,就是这么个意思,那么我们开始吧:在纸上算的时候我们都会,可是用程序去做的时候就比较难了吧,而且乘法运算从右往左运算的,我们怎么往string的头部插入一个字符串呢?不用担心,我们请看下图:

    

既然从右往左运算的时候字符串不好操作,那么我们就将从右往左运算的结果从左往右存储,最后再反转字符串就可以解决了,这样的做法还有一些其他问题需要注意,比如 0 的处理,什么地方得添加 0 ,什么位置不用添加 0;还有就是进位的处理,写了两个函数一个用来计算乘法一个用来处理进位问题,因为我发现这两个功能不能复用,那么请看我的代码吧,其中有很多细节的地方需要注意,这道题考的就是细心的程度!

class Solution {
public:
	string multiply(string num1, string num2)
	{
		/*
		这个题的意思是返回两个大数相乘的结果
		两个乘数可以很大且非负
		不能将字符串转化为int
		不能使用大数相关的库
		*/

		string ret = "";
		int sz1 = num1.size();
		int sz2 = num2.size();
        if (sz1 == 1 && num1[0] == '0' || sz2 == 1 && num2[0] == '0')
		{
			ret.push_back('0');
			return ret;
		}
		
		//先往右进位,最后将结果逆置一下
		for (int i = sz1-1; i >=0; --i)
		{
			int begin = sz1 - i - 1;
			for (int j = sz2-1; j >= 0; --j)
			{
				int tmp = (num1[i] - '0') * (num2[j] - '0');
				carrybit(ret, begin, tmp);
				++begin;
			}
		}

		//逆序
		reverse(ret);

		return ret;
	}

	void carrybit(string& str, int begin, int num)
	{
		const int first = begin;
		if (num == 0)
		{
			if (begin >= str.size())
			{  // 相乘的结果为 0 且出现在最后面的位置,这个时候得补上0,否则缺位
				str.push_back('0');
			}
		}

		while (num)
		{
			int cur = num % 10;
			if (begin >= str.size())
			{//在最后面的位置上添加的时候得添加‘字符’
				str.push_back(cur + '0');
				++begin;
			}
			else
			{//在中间的位置上只需要加‘整数’
				str[begin++] += cur;
			}
			num /= 10;
		}

		//判断当前位是否产生进位
		int bigger = str[first] - '0';
		if (bigger >= 10)
		{//判断当前位是否产生了进位,若进位则处理进位
			curcarrybit(str, first, bigger);
		}
	}
	
	//进位处理函数
	void curcarrybit(string &str, int  begin, int num)
	{
		int first = begin;
		while (num)
		{
			int cur = num % 10;
			if (begin >= str.size())
			{
				str.push_back(cur + '0');
				++begin;
			}
			else
			{
				if (first == begin)
				{//当前位产生进位,留下余下的,所以用赋值语句
					str[begin++] = (cur + '0');
				}
				else
				{//进位的数目补到后面的位置上
					str[begin++] += cur;
				}
			}
			num /= 10;
		}
	}

	//翻转字符串
	void reverse(string & s)
	{
		int right = s.size() - 1;
		int left = 0;
		while (left < right)
		{
			swap(s[left], s[right]);
			++left;
			--right;
		}
	}
};
最终结果如下:


      我觉得这个题我是按照乘法原则一步一步去实现的,这种的做法好像不是最优的,但是我没有想出更优的方法来,不知道看到我的文章的人有没有更优的方法,如果有的话希望画上你几秒钟的时间指点指点。

以上是关于笔试题56. LeetCode OJ (43)的主要内容,如果未能解决你的问题,请参考以下文章

笔试题68. LeetCode OJ (55)

笔试题58. LeetCode OJ (45)

笔试题57. LeetCode OJ (44)

笔试题61. LeetCode OJ (48)

笔试题55. LeetCode OJ (42)

笔试题65. LeetCode OJ (52)