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;
}
};