[链表] 牛客题霸 - NC40 链表相加(二)

题目链接

NC40 链表相加(二)

结题过程

思路一

用2个数组存储head1和head2的节点数值,然后倒序从两个数组取数值,进行相加,把和存到第三个数组。最够根据第三个数组创建结果链表。
虽然写了出来,但是自我感觉十分蠢笨。用数组就罢了,为什么需要第三个数组?
写了一会想到可以用两个栈来替代数组,间思路二

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
#include <vector>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head1 ListNode类 
     * @param head2 ListNode类 
     * @return ListNode类
     */
    ListNode* addInList(ListNode* head1, ListNode* head2) {
        // write code here
        std::vector<int> my_vec1; //把head1的数据存储到数组
        std::vector<int> my_vec2; //把head2的数据存储到数组
        std::vector<int> my_vec3; //用于输出结果的数组
        ListNode* res = nullptr;  //用于指向结果链表的头指针
        ListNode* cur = head1;
        int h1_len = 0, h2_len = 0;
       
        while(cur != nullptr) //把head1的val转移到vector中
        {

            my_vec1.push_back(cur->val);
            cur = cur->next;
   
        }

        cur = head2;
        while(cur != nullptr) //把head2的val转移到vector中
        {
            my_vec2.push_back(cur->val);
            cur = cur->next;
        }

        h1_len = my_vec1.size();
        h2_len = my_vec2.size();

        //确定下面用于计算的循环的次数,也就是输出结果的数组的大小
        //因为可能head1和head2最高位的和大于9,会进位,
        //所以结果数组的大小要比head1或者head2的成员数量最大值 + 1
        int loop = (h1_len > h2_len ? h1_len:h2_len);
        loop++;
        my_vec3.resize(loop);

        //从后往前,依次计算head1和head2成员的和
        bool isNeedAdd = false;
        for(int i = 0; i < loop; i++)
        {
            my_vec3[loop - 1 -i] = 0;
            int tmp  = 0;

            //因为head1和head2的成员数量不一定谁多,所以分开加
            if(h1_len - 1 - i >= 0)
              tmp += my_vec1[h1_len - 1 - i];
            
            if(h2_len - 1 - i >= 0)
                tmp += my_vec2[h2_len - 1 - i];

            //对相加和的判断:
            //情况1: 和大于9,并且有上一次循环的进位
            //情况2:和大于9
            //情况3:和小于等于9. 并且有上一次循环的进位
            //情况4,和小于等于9
            if(tmp > 9)
            {
                tmp = tmp - 10;
                if(isNeedAdd) //情况1:保留tmp - 10,并且 + 1
                {
                    tmp++; //9+9最大是18,保留8,再加1也不会大于9了。    
                    isNeedAdd = false;
                }               
                isNeedAdd = true;  //情况2:保留tmp - 10,并且向下一个循环进位
            }
            else 
            {
                if(isNeedAdd)  //情况3:给tmp + 1,然后判断是否大于9
                {
                    tmp++;
                    isNeedAdd = false;
                    if(tmp > 9)
                    {
                        tmp = tmp - 10;               
                        isNeedAdd = true;
                    }
                }
               
            //情况4:无需对tmp处理
            }
            
            my_vec3[loop - 1 -i] = tmp; //把和放入结果数组
        }
       //从结果数组转移到链表
       bool is_head = true;
       int len3 = my_vec3.size();
       for (int i = 0; i < len3; i++)
       {
            if( i == 0 && my_vec3[i] == 0) //如果结果数组预留的用来进位的最高位没用到,就略过
                continue;
            if(is_head) //为头指针赋值
            {
                res = new ListNode(my_vec3[i]);
                cur = res;
                is_head = false;
                continue;
            }
            cur->next =  new ListNode(my_vec3[i]);
            cur = cur->next;
       }
        return res;
    }
};

用2个栈来存储head1和head2的值。
然后只要不断出2个栈,再进行求和,创建结果数组的节点就好了。这个步骤一直持续到两个栈都为空。
这样代码明显简洁很多。思路也更清晰。

思路二

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
#include <stack>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head1 ListNode类 
     * @param head2 ListNode类 
     * @return ListNode类
     */
    ListNode* addInList(ListNode* head1, ListNode* head2) {
        ListNode* ret = nullptr;
        ListNode* cur = nullptr;
        std::stack<int> s1;
        std::stack<int> s2;
        bool isNeedPlus = false;
        bool isRetHead = true;

        cur = head1;
        while(cur != nullptr) {
            s1.push(cur->val);
            cur = cur->next;
        }

        cur = head2;
        while(cur != nullptr) {
            s2.push(cur->val);
            cur = cur->next;
        }

        while(!s1.empty() || !s2.empty()) {
            int tmp  = 0;
            if(!s1.empty()) {
                tmp += s1.top();
                s1.pop();
            }
            if(!s2.empty()) {
                tmp += s2.top();
                s2.pop();
            }

            if(tmp >= 10) {
                tmp -= 10;
                if(isNeedPlus)
                    tmp++;
                isNeedPlus = true;
            }
            else {
                if(isNeedPlus) {
                    tmp++;
                    if(tmp >= 10) {
                        tmp -= 10;
                        isNeedPlus = true;
                    }
                    else
                        isNeedPlus = false;
                }  
                else {
                    isNeedPlus = false;
                }              
            }

            cur = new ListNode(tmp);
            if(ret == nullptr)
                ret = cur;
            else {
                cur->next = ret;
                ret = cur;
            }          
        }
        if(isNeedPlus)
        {
            cur = new ListNode(1);
            if(ret == nullptr)
                ret = cur;
            else {
                cur->next = ret;
                ret = cur;
            }          
        }
        return ret;
    }
};

思路三

做到思路二以后,自以为不错。
看到答案后,发现反转链表更牛逼,思路及其清晰,而且任何其余容器都不需要创建。
感觉自己依旧很蠢。

而且获取进位只要判断 【和除以10】 是0还是1就好,我还在那判断是否大于10。

修正后的代码

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
#include <stack>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head1 ListNode类 
     * @param head2 ListNode类 
     * @return ListNode类
     */
    ListNode* ReverseListNode(ListNode* head) { //反转链表
        ListNode* rhead = nullptr;
        while(head != nullptr) {
            ListNode* tmp = head;
            head = head->next;
          
            tmp->next = rhead;
            rhead = tmp; 
        }
       return rhead;
    }
    ListNode* addInList(ListNode* head1, ListNode* head2) {
        ListNode* ret = nullptr;
        head1 = ReverseListNode(head1);//反转链表
        head2 = ReverseListNode(head2);//反转链表

        int AddNUm = 0;
        while(head1 != nullptr || head2 != nullptr)
        {
            int tmp= 0;
            if(head1 != nullptr)
            {
                tmp += head1->val;
                head1 = head1->next;
            }
            if(head2 != nullptr)
            {
                tmp += head2->val;
                head2 = head2->next;
            }
            tmp += AddNUm; //因为进位就是加1,所以不管此时tmp是[0,18]中的谁,直接加1
            AddNUm = tmp / 10;//判断下一次的进位0或者1
            tmp = tmp % 10;//判断当前的值[0,9]
            
            auto cur = new ListNode(tmp);
            cur->next = ret;
            ret = cur;
        }
        if(AddNUm == 1) //进位的判断可以整合到上面的while中
        {
            auto cur = new ListNode(1);
            cur->next = ret;
            ret = cur;
        }

        return ret;
    }
};

总结

反转链表牛逼。

相关推荐

  1. [] - NC40 相加()

    2024-03-11 23:48:02       45 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-11 23:48:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-11 23:48:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-11 23:48:02       82 阅读
  4. Python语言-面向对象

    2024-03-11 23:48:02       91 阅读

热门阅读

  1. 基础 | 安全 - [加密]

    2024-03-11 23:48:02       41 阅读
  2. composer require 包时,指定版本

    2024-03-11 23:48:02       37 阅读
  3. AcWing16. 替换空格

    2024-03-11 23:48:02       41 阅读
  4. 安卓基础--application详解

    2024-03-11 23:48:02       46 阅读
  5. js的同步异步

    2024-03-11 23:48:02       41 阅读
  6. Android Selinux详解[一]---整体介绍

    2024-03-11 23:48:02       42 阅读
  7. android:textDirection=“anyRtl“在说什么?

    2024-03-11 23:48:02       44 阅读