C/C++每日一练6
1.大数加法题目大意输入两个很大的非负整数长度超出普通整型、long long 范围以字符串形式输入输出相加结果。核心思路模拟手工竖式加法从低位往高位逐位相加保存进位。C 完整代码cpp运行#include iostream #include string #include algorithm using namespace std; int main() { string a, b; cin a b; // 反转字符串方便从低位开始运算 reverse(a.begin(), a.end()); reverse(b.begin(), b.end()); string res; int carry 0; // 进位 int i 0; // 只要还有数字或者还有进位就继续循环 while (i a.size() || i b.size() || carry) { int sum carry; if (i a.size()) sum a[i] - 0; if (i b.size()) sum b[i] - 0; carry sum / 10; res.push_back(sum % 10 0); i; } // 反转回来得到正确顺序 reverse(res.begin(), res.end()); cout res endl; return 0; }思路详解反转字符串数字字符串123反转成321下标 0 对应个位方便统一处理低位。逐位求和取出两个数当前位置数字 进位sum % 10→ 当前位结果sum / 10→ 更新进位。循环终止条件两个字符串遍历完并且进位为 0防止最高位产生新进位被漏掉如 999 1。最后反转结果输出测试样例输入plaintext999 1输出plaintext1000输入plaintext123456789 987654321输出plaintext11111111102.链表相加二题目描述给定两个链表链表每个节点代表数字一位高位在前。 例如9-3-7代表 9376-3代表 63 相加937 63 1000 输出链表1-0-0-0区别于普通链表相加低位在前本题高位在前无法直接从表头遍历相加。思路方案反转链表 → 低位在前正常相加 → 反转结果链表反转 l1、l2变成低位在前逐位相加处理进位生成新链表反转结果链表恢复高位在前输出C 完整 AC 代码cpp运行#include iostream using namespace std; struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(nullptr) {} }; // 反转链表 ListNode* reverseList(ListNode* head) { ListNode* pre nullptr; ListNode* cur head; while(cur) { ListNode* nxt cur-next; cur-next pre; pre cur; cur nxt; } return pre; } class Solution { public: ListNode* addInList(ListNode* head1, ListNode* head2) { ListNode* l1 reverseList(head1); ListNode* l2 reverseList(head2); ListNode dummy(0); ListNode* cur dummy; int carry 0; while(l1 || l2 || carry) { int sum carry; if(l1) { sum l1-val; l1 l1-next; } if(l2) { sum l2-val; l2 l2-next; } carry sum / 10; cur-next new ListNode(sum % 10); cur cur-next; } // 结果现在低位在前反转回来 return reverseList(dummy.next); } };另一种不反转链表方案栈原理利用栈后进先出把节点压栈依次取出低位相加最后头插法构建结果链表cpp运行#include stack ListNode* addInList(ListNode* head1, ListNode* head2) { stackint st1, st2; while(head1) { st1.push(head1-val); head1 head1-next; } while(head2) { st2.push(head2-val); head2 head2-next; } ListNode* res nullptr; int carry 0; while(!st1.empty() || !st2.empty() || carry) { int sum carry; if(!st1.empty()) { sum st1.top(); st1.pop(); } if(!st2.empty()) { sum st2.top(); st2.pop(); } carry sum / 10; // 头插 ListNode* node new ListNode(sum % 10); node-next res; res node; } return res; }两种方案对比反转链表空间复杂度 O (1)只新建结果节点推荐面试手写。栈空间 O (nm)代码直观不需要写反转函数。易错点不要忘记循环条件carry最高位进位9991结果链表最后一定要反转头插法构建链表时注意指针顺序3.大数乘法原理普通int/long long存不下超大数字用字符串存储。 模拟竖式乘法num1[i] × num2[j]的结果落在乘积数组ij和ij1位置。规律核心plaintextnum1 下标 i从右往左 num2 下标 j从右往左 乘积低位pos ij1 乘积高位pos ijC AC 代码cpp运行#include iostream #include string #include vector #include algorithm using namespace std; string multiply(string num1, string num2) { // 处理0特判 if (num1 0 || num2 0) return 0; int n num1.size(), m num2.size(); // 两数相乘最多 nm 位 vectorint res(n m, 0); // 逆序遍历 for (int i n - 1; i 0; --i) { int a num1[i] - 0; for (int j m - 1; j 0; --j) { int b num2[j] - 0; int mul a * b; // 对应位置 int p1 i j; int p2 i j 1; int sum mul res[p2]; res[p2] sum % 10; res[p1] sum / 10; } } // 转字符串跳过前导0 string ans; for (int x : res) { if (!(ans.empty() x 0)) { ans.push_back(x 0); } } return ans; } int main() { string a, b; cin a b; cout multiply(a, b) endl; return 0; }执行示例输入plaintext999 999输出plaintext998001输入plaintext123456789 987654321输出plaintext121932631112635269关键点梳理最大长度长度 n × m 的两个数乘积最多nm位数组开nm。位置映射num1[i] * num2[j]→res[ij]、res[ij1]先累加再取进位不要直接赋值要加上该位置原有数值plaintextint sum a*b res[p2]; res[p2] sum %10; res[p1] sum /10;前导 0 清除数组开头可能存在 0拼接字符串时跳过。边界特判任意一个数字为0直接返回0否则会出现空串或者多个前导 0。谢谢