文章目录
两个链表的第一个公共结点
题目链接:两个链表的第一个公共结点
解题思路1:利用路程相同
两个指针从两个链表的头结点出发,以相同的速度开始往前走,走完一条继续走另一条,最后一定会相遇,如果有相同节点,那相遇的节点就是第一个公共节点,如果没有相同节点,那相遇的节点就是nullptr,两个指针此时分别指向两条链表的nullptr
代码如下:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
ListNode* p1 = pHead1;
ListNode* p2 = pHead2;
while(p1 != p2){
p1 = (p1==nullptr) ? pHead2 : p1->next;
p2 = (p2==nullptr) ? pHead1 : p2->next;
}
return p1;
}
解题思路2:哈希
将第一个链表的所有节点放到集合中,再遍历第二个链表,查找集合中是否有第二个链表的元素,如果有,则该元素就是两个链表的第一个公共节点
代码如下:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
set<ListNode*> st;
ListNode* p1 = pHead1;
ListNode* p2 = pHead2;
while(p1 != nullptr){
st.insert(p1);
p1 = p1->next;
}
while(p2 != nullptr){
if(st.count(p2)){
return p2;
}
p2 = p2->next;
}
return nullptr;
}
解题思路3:从长度入手
首先统计两条链表的长度
接着让较长的链表先走,最后达到两条链表走到最后一样长停下
此时接着以相同的速度往后走,最后两个指针一定会相遇,如果有公共节点,相遇的节点就是公共节点,如果没有公共节点,最后两个节点也会指向相同的nullptr.
代码如下:
int LengthLink(ListNode* head){
int length = 0;
while (head != nullptr) {
length++;
head = head->next;
}
return length;
}
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
int len1 = LengthLink(pHead1);
int len2 = LengthLink(pHead2);
while(len1 != len2){
if(len1 > len2){
pHead1 = pHead1->next;
len1--;
}else{
pHead2 = pHead2->next;
len2--;
}
}
while(pHead1 != pHead2){
pHead1 = pHead1->next;
pHead2 = pHead2->next;
}
return pHead1;
}
链表相加(二)
题目链接:链表相加(二)
解题思路1:反转链表再相加
代码如下:
ListNode* Reverse(ListNode* head){
ListNode* res = nullptr;
ListNode* pre = res;
ListNode* cur = head;
while(cur != nullptr){
ListNode* pnext = cur->next;
if(pnext == nullptr) {
res = cur;
}
cur->next = pre;
pre = cur;
cur = pnext;
}
return res;
}
ListNode* addInList(ListNode* head1, ListNode* head2) {
if(head1 == nullptr) return head2;
if(head2 == nullptr) return head1;
//反转两个链表
ListNode* h1 = Reverse(head1);
ListNode* h2 = Reverse(head2);
//添加表头
ListNode* res = new ListNode(-1);
ListNode* head = res;
int carry = 0;//记录进位
while(h1!=nullptr || h2!=nullptr || carry!=0){
int v1 = h1==nullptr ? 0 : h1->val;
int v2 = h2==nullptr ? 0 : h2->val;
int temp = v1 + v2 + carry;
carry = temp / 10;//进位可能是1、0
temp %= 10;
head->next = new ListNode(temp);
head = head->next;
if(h1 != nullptr)
h1 = h1->next;
if(h2 != nullptr)
h2 = h2->next;
}
return Reverse(res->next);
}
解题思路2:利用栈
利用栈先进后出的特性来模拟链表的反转,最后每一个得到的值进行头插法得到最终的链表
代码如下:
ListNode* addInList(ListNode* head1, ListNode* head2) {
if (head1 == nullptr) return head2;
if (head2 == nullptr) return head1;
stack<ListNode*> s1;
stack<ListNode*> s2;
ListNode* p1 = head1;
ListNode* p2 = head2;
while (p1 != nullptr) {
s1.push(p1);
p1 = p1->next;
}
while (p2 != nullptr) {
s2.push(p2);
p2 = p2->next;
}
int carry = 0;//进位
ListNode* res = nullptr;
while (!s1.empty() || !s2.empty()) {
int val = carry;
if (!s1.empty()) {
val += s1.top()->val;
s1.pop();
}
if (!s2.empty()) {
val += s2.top()->val;
s2.pop();
}
carry = val / 10;
ListNode* cur = new ListNode(val % 10);
cur->next = res;
res = cur;
}
if(carry > 0){
ListNode* node = new ListNode(carry);
node->next = res;
res = node;
}
return res;
}