文章目录
前言
今天的问题主要是处理 "大数加法"问题。
做题链接:大数加法、链表相加、大数乘法。
1. 大数加法
1.1 题目描述
1.2 解题思路
这类问题都有统一的模板写法-----高精度加法。
使用两个指针表示两个字符串的末尾(因为是从末尾开始相加的),从后往前进行枚举,一次相加。
处理进位问题:可以提前设置一个进位变量t,初始化为0,在每一次枚举相加的结果之上,再加上进位值,不断循环即可。
1.3 代码实现
class Solution {
public:
string solve (string s, string t) {
int cur1 = s.size() - 1, cur2 = t.size() - 1, n = 0;
string ret;
while (cur1 >= 0 || cur2 >= 0 || n)
{
int sum = 0;
if (cur1 >= 0) sum += (s[cur1--] - '0');
if (cur2 >= 0) sum += (t[cur2--] - '0');
sum += n;
ret += to_string(sum % 10);
n = sum / 10;
}
reverse(ret.begin(), ret.end());
return ret;
}
};
2. 链表相加
2.1 题目描述
2.2 解题思路
这个的做法与第一题一样,不过由于是单链表,所以我们相较于第一题,无法从后开始进行枚举,必须需要自己实现链表的逆序。
对于链表的逆序,我们可以创建一个链表结点,如何将我们需要的逆序的链表,不断头插到我们新建的链表中,当全部头插完成后,也就实现了链表的逆序了。
之后的写法就与第一题一模一样的, 使用两个指针从头一次枚举然后相加即可,再将计算出来的结果添加到最终的结果链表中,循环完成之后再将结果链表进行逆置就可以。(如果看题解不理解,我建议可以边看代码,边看题解来理解)
2.3 代码实现
class Solution {
public:
ListNode * Reverse(ListNode *&list)
{
ListNode * p = nullptr, * c = list, * n = list->next;
while (c)
{
c->next = p;
p = c;
c = n;
if (n)
n = n->next;
}
return p;
}
// ListNode* reverse(ListNode* head)
// {
// ListNode* newHead = new ListNode(0);
// ListNode* cur = head;
// while(cur)
// {
// ListNode* next = cur->next;
// cur->next = newHead->next;
// newHead->next = cur;
// cur = next;
// }
// cur = newHead->next;
// delete newHead;
// return cur;
// }
ListNode * addInList(ListNode * head1, ListNode * head2)
{
ListNode * cur1 = Reverse(head1);
ListNode * cur2 = Reverse(head2);
ListNode* ret = nullptr;
ListNode* list = nullptr;
int n = 0;
while (cur1 || cur2 || n)
{
int num = 0;
if (cur1)
{
num += cur1->val;
cur1 = cur1->next;
}
if (cur2)
{
num += cur2->val;
cur2 = cur2->next;
}
num += n;
ListNode *node = new ListNode(num % 10);
if(list != nullptr)
{
list -> next = node;
list = list->next;
}
else
{
list = node;
ret = node;
}
cout << list->val << " ";
n = num / 10;
}
ret = Reverse(ret);
return ret;
}
};
3. 大数乘法
3.1 题目描述
3.2 解题思路
对于大数乘法,我们采用的是无进位相加,也就是计算出一个结果后,先不进行进位,当所有结构计算出来后,在进行相加:
我们可以将所有的结果使用一个数据保存起来,保存的位置就是两个数相乘的下标之和。(这个例子是建立在字符串逆置之后的结果之上的,因为我们是从个位开始相乘的)例如:7的下标为0,9 的下标也为0,那么它俩的乘积就放到0 + 0 = 0下标为0的地方,对于6和9来说就是,1+0 = 1,放到下标为1的地方,对于7和8,就是0 + 1 = 1,放到下标为1的地方。
也就是说,最终数据中存放的是图中处理进位那一行的数据。需要注意的是,在循环中,我们要使用+=,而不能使用=,因我们从图中也可以看到,有的结果是存放的位置是相同的,所以需要+=。
3.3 代码实现
class Solution {
public:
string solve(string s, string t)
{
string ret;
reverse(s.begin(), s.end());
reverse(t.begin(),t.end());
int m = s.size(), n = t.size();
vector<int> nums(m + n);
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
{
nums[i+j] += (s[i] - '0') * (t[j] - '0');
}
n = 0;
for(int i = 0; i < nums.size(); i++)
{
nums[i] += n;
ret += nums[i] % 10 + '0';
n = nums[i] / 10;
}
while(n)
{
ret += n + '0';
n /= 10;
}
while(ret.size() > 1 && ret.back() == '0') ret.pop_back();
reverse(ret.begin(), ret.end());
return ret;
}
};
总结
对于大数加法这部分的知识来说,我觉得还是比较重要的,因为在现实中总会出现很大的数字,仅靠long long是无法存储的,那么就需要使用这种方式来处理数据。
那么第六天的内容就到此结束了,如果大家发现有什么错误的地方,可以私信或者评论区指出喔。我会继续坚持训练的,希望能与大家共同进步!!!那么本期就到此结束,让我们下期再见!!觉得不错可以点个赞以示鼓励!