面试必刷算法TOP101之哈希篇 TOP 22

两数相加Ⅱ

题目来源:leetcode

1、问题描述

给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。

2、思路解析

思路一:哈希+反转链表
将俩个链表节点分别存储在hash数据结构中然后从尾部遍历相加,将相加结果保存在sum中,然后申请新节点,将新节点插入到新链表中这样得到的是结果链表的反向链表。最后将链表反转就可以
思路二:反转链表相加+反转链表
先将两个链表反转,这样就比较容易相加,相加后将最后得到的链表也进行反转就行
在这里插入图片描述
思路三:栈+反转链表
先将链表分别入栈,因为栈是先进先出这就导致头节点先进去未结点先出来这就方便运算,每加一次就申请一次新节点,最后将新节点插入到新链表中,最后也需要将新链表反转才能得到结果链表

3、代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    //哈希
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
         // write code here
         vector<int> v1;
        vector<int> v2;
        while(l1){
            v1.push_back(l1->val);
            l1=l1->next;
        }
        while(l2){
            v2.push_back(l2->val);
            l2=l2->next;
        }
        ListNode*proot=new ListNode(-1);
        ListNode*root=proot;
        int end1=v1.size()-1;
        int end2=v2.size()-1;
        int num=0;//进位
        while(end1>=0&&end2>=0){
            int sum=v1[end1]+v2[end2]+num;
            if(sum>=10){
                sum-=10;
                num=1;
            }else{
                num=0;
            }
            root->next=new ListNode(sum);
            root=root->next;
            end1--;
            end2--;
        }
        while(end1>=0){
            int sum=v1[end1]+num;
            if(sum>=10){
                sum-=10;
                num=1;
            }else{
                num=0;
            }
            root->next=new ListNode(sum);
            root=root->next;
            end1--;
        }
        while(end2>=0){
            int sum=v2[end2]+num;
            if(sum>=10){
                sum-=10;
                num=1;
            }else{
                num=0;
            }
            root->next=new ListNode(sum);
            root=root->next;
            end2--;
        }
        //检测进制位是不是为0
        if(num!=0){
            root->next=new ListNode(num);
        }
        //反转链表
        ListNode *cur=proot->next->next;
        ListNode*node=proot->next;
        node->next=NULL;
        while(cur){
            ListNode*node1=cur->next;
            cur->next=node;
            node=cur;
            cur=node1;
        }
        
        return node;

    }
};
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

class Solution {
public:
    /**
     * 
     * @param head1 ListNode类 
     * @param head2 ListNode类 
     * @return ListNode类
     */
    //反转链表
    //相加后再反转
    ListNode* FAN(ListNode*root){
         ListNode*node1=root;
        ListNode*node2=root->next;
        node1->next=NULL;
        while(node2){
            ListNode*node=node2->next;
            node2->next=node1;
            node1=node2;
            node2=node;
            
        }
        return node1;
    }
    ListNode* addInList(ListNode* head1, ListNode* head2) {
        if(head1==NULL&&head2==NULL){
            return NULL;
        }
        if(head1==NULL){
         return head2;
        }else if(head2==NULL){
            return head1;
        }
       //反转林链表
        ListNode*node=FAN(head1);
        ListNode*node1=FAN(head2);
        //链表相加
        ListNode*root=new ListNode(-1);
        ListNode*cur=root;
        int i=0;
        int sum=0;
        while(node&&node1){
            sum=node->val+node1->val+i;
            if(sum>=10){
                sum-=10;
                i=1;
            }else{
                i=0;
            }
            cur->next=new ListNode(sum);
            cur=cur->next;
            node=node->next;
            node1=node1->next;
        }
        while(node){
             sum=node->val+i;
            if(sum>=10){
                sum-=10;
                i=1;
            }else{
                i=0;
            }
            cur->next=new ListNode(sum);
            cur=cur->next;
            node=node->next;
        }
        while(node1){
             sum=node1->val+i;
            if(sum>=10){
                sum-=10;
                i=1;
            }else{
                i=0;
            }
            cur->next=new ListNode(sum);
            cur=cur->next;
            node1=node1->next;
        }
        if(i==1){
            cur->next=new ListNode(i);
        }
        //反转链表
        ListNode*head=FAN(root->next);
       
        return head;
    }
};

四数相加

题目来源:Leetcode

1、问题描述

给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

2、思路解析

思路一:循环暴力破解
该思路简单容易理解,就是四个for循环遍历每中排列,然后判断是不是符合条件,符合条件就将结果保存在数组中。虽然思路简单,但是时间复杂度为O(N^4),随着数据量的增加运算时间也在不断增加。
思路二:哈希
将数组分成两组,数组A和数组B为一组,将A[i]+B[j]=sum结果保存在hashamap中充当键值,其出现次数为values,也就是双for循环遍历A数组和B数组将结果保存在map的键值中,将出现次数保存在values。数组C和数组D为一组,双for循环遍历数组C和数组D,寻找map中是不是存在-(C[i]+D[j])也就是sum,如果存在(也即是说出现sum+C[i]+D[j]0的情况,出现的次数N就是结果为C[i]+D[j]+sum0有N种情况)就将出现次数加起来,最后将次数相加的结果返回就行

3、代码实现

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        int ret=0;
        for(int i=0;i<nums1.size();i++){
            for(int j=0;j<nums2.size();j++){
                for(int n=0;n<nums3.size();n++){
                    for(int m=0;m<nums4.size();m++){
                        if(nums1[i]+nums2[j]+nums3[n]+nums4[m]==0){
                            ret++;
                        }
                    }
                }
            }
        }
        return ret++;
    }
};
class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        unordered_map<int,int> m;
        
        for(int i=0;i<nums1.size();i++){
            for(int j=0;j<nums2.size();j++){
            //结果保存早键值,出现次数保存在values中
                m[nums1[i]+nums2[j]]++;
            }
        }
        int num=0;
        for(int i=0;i<nums3.size();i++){
            for(int j=0;j<nums4.size();j++){
                //找到相反数将对应的次数相加
                if(m.count(-(nums3[i]+nums4[j]))){
                    num+=m[-(nums3[i]+nums4[j])];
                }
            }
        }
        
        return num;

    }
};
  • 21
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自首的小偷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值