笔试练习day6


感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接
🐒🐒🐒 个人主页
🥸🥸🥸 C语言
🐿️🐿️🐿️ C语言例题
🐣🐣🐣 python
🐓🐓🐓 数据结构C语言
🐔🐔🐔 C++
🐿️🐿️🐿️ 文章链接目录
🏀🏀🏀 笔试练习题

大数加法

链接大数加法
在这里插入图片描述

题目解析

这道题就是模拟计算的过程
在这里插入图片描述
比如123+789,我们先让各位的相加,因为涉及到进位,所以需要有一个中间变量t保存进位的数
比如3+9=12.需要进1,就用中间变量t=1
计算十位的时候2+8+t=11,再让t=1

解法

因为是以字符串形式去返回的,所以我们需要定义一个string ret
并且计算的过程中需要知道字符串有多少个字符,所以我们用sizes和sizet分别表示字符串s和字符串t有多少个字符
因为从个位开始计算,然后一直进位,所以我们要进行while循环,循环条件即是sizes和sizet的大小大于等于0,且在最后的时候我们还需要保证中间变量tmp为0,因为如果tmp不为0的话就说明还要进位,我们还需要进行一次循环,否则就会丢失数据
循环内部我们要分别对sizes和sizet进行判断,如果sizes已经为负数了,那就不将s[sizes]进行相加
因为是分别判断所以每次判断如果符合条件就和tmp进行相加
在两个判断都结束后,要将tmp的个位通过+=的形式追加到ret的尾部,然后让tmp保留十位的数
最后再用reverse进行逆序

具体过程如下图,s为12,t为89,tmp初始化为0

在这里插入图片描述
在这里插入图片描述
将tmp的个位追加到ret尾部
在这里插入图片描述
让tmp等于他的十位上的数字
在这里插入图片描述
之后重复上面操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最后将ret进行逆序,因为是尾插

代码
class Solution {
public:
  
    string solve(string s, string t) {
        string ret;
  int sizes=s.size()-1,sizet=t.size()-1;
  int tmp=0;
  while(sizes>=0||sizet>=0||tmp)
  {
    if(sizes>=0)
        tmp+=s[sizes--]-'0';
    if(sizet>=0)
        tmp+=t[sizet--]-'0';
        ret+=tmp%10+'0';
        tmp/=10;
  }
reverse(ret.begin(),ret.end());
return ret;
    }
};

链表相加(二)

链接链表相加(二)
在这里插入图片描述

题目解析

这道题和上一道题很相似,只不过这个是链表
链表有个难点就是我们要实现加法的话应该是从后往前加,但是由于是链表,如果我们从后往前加的话会找不到前一个节点
所以我们要先对链表进行逆序

解法

这里的解法会用到一个常用的操作就是创建一个虚拟头节点,有了这个虚拟头结点,我们就不需要考虑链表为空的情况

逆序链表函数
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(0)表示的是val=0,next为空
在这里插入图片描述
将原链表的头结点给到cur去遍历链表,然后头插,在头插的时候要保留cur的下一个节点,否则头插完一次后就找不到下一个节点的地址了
具体过程如下
在这里插入图片描述
cur->next=newHead->next,此时的cur不再指向next
在这里插入图片描述
newHead->next指向cur
在这里插入图片描述
整理一下就变成下面这样了
在这里插入图片描述
重复上面的操作,cur->next指向newHead->next,此时的newHead->next指向的是节点1,所以cur->next指向节点1
在这里插入图片描述
再让newHead->next指向cur
在这里插入图片描述
整理后变成了这样
在这里插入图片描述
让cur指向newHead->next,也就是节点2
在这里插入图片描述
让newHead->next指向cur
在这里插入图片描述
最后整理后变成这样,因为这次的next为空,让cur=next后,cur也就为空,while循环判断的cur是否为空,所以这次会直接跳出循环
在这里插入图片描述

循环跳出后将cur指向newHead->next,再销毁newHead
在这里插入图片描述

代码
  
    ListNode* addInList(ListNode* head1, ListNode* head2) {
        head1 = reverse(head1);
        head2 = reverse(head2);
        int t = 0;
        ListNode* cur1 = head1, *cur2 = head2;
        ListNode* ret = new ListNode(0);
        ListNode* prev = ret;
        while (cur1 || cur2 || t) {
            if (cur1) {
                t += cur1->val;
                cur1 = cur1->next;
            }
            if (cur2) {
                t += cur2->val;
                cur2 = cur2->next;
            }
            prev = prev->next = new ListNode(t % 10);
            t /= 10;

        }
        cur1 = ret->next;
        ret->next = nullptr;
        delete ret;
        return reverse(cur1);
    }
};

将两个链表分别逆序,这样做的目的是可以实现个位和个位相加…
用一个变量t保存进位,并且用两个指针cur1和cur2指向两个逆序链表的头节点
创造出一个链表ret保存两个逆序链表相加的结果,并用一个指针prev指向ret头结点
因为要两个逆序链表一起遍历相加,所以用while循环,while循环的判断是cur1||cur2||t不为0
因为可能会出现已经有一个逆序链表遍历完了,而另一个没有遍历完,所以还需要进行遍历,而t不为0是考虑的进位的问题
在循环内部用if语句去判断cur1和cur2是否为空,如果不为空就让cur的val与t相加,同时让cur走到下一个节点
每进行一次循环后都需要保存他们相加的值到prev->next里面去,但是要注意的是t可能大于10,所以我们保存的值应该为t%10
prev = prev->next = new ListNode(t % 10)可以拆分成
prev->next = new ListNode(t % 10)
prev = prev->next
之后让t=t/10,使t保存进位

大数乘法

链接大数乘法

在这里插入图片描述

题目解析

这里的方法和第一题是一样的,并且顺便说一下为什么要用字符串的形式读入和输出,这是因为有些数字太大了已经超出最大的范围,所以用字符串的形式

解法

这里的解法是无进位相乘然后相加,但是要注意的是这和我们平时计算的方式有一点不同
我们平时计算是进位与计算同时进行的,而这里我们是直接进行计算不进位,在计算完后将进位的数字进行相加
过程如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码
    string solve(string s, string t) {
        reverse(s.begin(), s.end());
        reverse(t.begin(), t.end());
        int m = s.size(), n = t.size();
        vector<int>tmp(m + n);
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                tmp[i + j] += (s[i] - '0') * (t[j] - '0');

            }
        }
        int c = 0;
        string ret;
        for (auto x : tmp) {
            c += x;
            ret += c % 10 + '0';
            c /= 10;
        }
        while (c) {
            ret += c % 10 + '0';
            c /= 10;
        }
        while (ret.size() > 1 && ret.back() == '0')
            ret.pop_back();
        reverse(ret.begin(), ret.end());
        return ret;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值