8.9 哈希表简单&中等 160 Intersection of Two Linked Lists 17 Letter Combinations of a Phone Number

160 Intersection of Two Linked Lists

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 注意:力扣中一般给的输入是不带头结点的除非题目中明确给出。
  • 使用哈希表解题:时间复杂度 O ( m + n ) O(m+n) O(m+n)空间复杂度O(m)
  • 不使用哈希表,就需要这个指针对齐,我自己是计数
  • 题解中的核心思路:当一个指针遍历完自己所属的链表时,跳转到另一个链表的头节点继续遍历。这样就保证了两个指针在第二次遍历时同步地对齐长度较长的部分。无论链表的长度如何,最终两个指针会同时遍历到相交节点或都到达末尾。【代码更简洁更巧妙】
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //找相交🍌node
        //无环 , 不能改变list ,不带头结点的
        int intersectVal = 0 , skipA = 0 ,skipB = 0;//🍌值,🍌点在A 和B 中的位置,他前面有几个结点。
        ListNode *p1 = headA;
        ListNode *p2 = headB;
        //肯定是要将A 和 B全都遍历的 时间复杂度最低都是m+n
        //多会判定两个指针指向相同结点? 
        //哈希表解题:O(m+n),将一个链表全部存储到哈希表中,再遍历另一个链表进行判断
        unordered_map<ListNode*,int> hash;
        while(p1){
            hash[p1] = skipA++;
            p1 = p1->next;
        }
        while(p2){
            if(hash.find(p2) != hash.end()){
                //找到了
                skipA = hash[p2];
                intersectVal = p2->val;
                return p2;
            }
            skipB++;
            p2 = p2->next;
        }
        return p2;
    }
};
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //找相交🍌node
        //无环 , 不能改变list ,不带头结点的
        int intersectVal = 0 , skipA = 0 ,skipB = 0;//🍌值,🍌点在A 和B 中的位置,他前面有几个结点。
        ListNode *p1 = headA;
        ListNode *p2 = headB;
        //肯定是要将A 和 B全都遍历的 时间复杂度最低都是m+n
        //多会判定两个指针指向相同结点? 
        //不使用哈希表,消除长度差值,使较长的提前移动到与较短链表的同样位置(距链表长度一致)
        int m = 0 , n = 0;
        while(p1){
            m++;
            p1 = p1->next;
        }
        while(p2){
            n++;
            p2 = p2->next;
        }
        //让较大的那个多走m-n步
        p1 = headA ; p2 = headB;
        for(int i = 0 ; i < abs(m-n) ; i++){
            if(m - n > 0){
                p1 = p1->next;
                skipA++;
            }else{
                p2 = p2->next;
                skipB++;
            }
        }
        int len = 0;
         while (p1 && p2) {
            if (p1 == p2) {
                skipA += len;
                skipB += len;
                intersectVal = p1->val;
                return p1;
            }
            p1 = p1->next;
            p2 = p2->next;
            len++;
        }
        return nullptr;
    }
};

优化:指针对齐

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == nullptr || headB == nullptr) return nullptr;
        ListNode *p1 =headA , *p2 = headB;
        while(p1 != p2){
           p1 = p1 == nullptr? headB : p1->next;
           p2 = p2 == nullptr? headA : p2->next;
        }
        return p1 == nullptr? p2: p1;
    }
};

17 Letter Combinations of a Phone Number

在这里插入图片描述
在这里插入图片描述

匹配没写出来,所以 积累!! 多数组匹配

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        int n = digits.size();
        if (n == 0) return {}; // 如果输入为空,返回空的结果集
        
        unordered_map<char, vector<char>> digitAndLetters = {
            {'2', {'a', 'b', 'c'}},
            {'3', {'d', 'e', 'f'}},
            {'4', {'g', 'h', 'i'}},
            {'5', {'j', 'k', 'l'}},
            {'6', {'m', 'n', 'o'}},
            {'7', {'p', 'q', 'r', 's'}},
            {'8', {'t', 'u', 'v'}},
            {'9', {'w', 'x', 'y', 'z'}}
        };

        // 用来存储最后的结果
        vector<string> res;
        // 初始化结果集,开始时为空字符串
        res.push_back("");

        // 遍历每一个数字
        for (char digit : digits) {
            vector<string> temp; // 用来临时存储每一轮的组合
            for (string s : res) {
                for (char letter : digitAndLetters[digit]) {
                    temp.push_back(s + letter); // 将每一个可能的字母加入当前的组合
                }
            }
            res.swap(temp); // 将临时结果赋值给res
        }
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值