剑指offer面试题之求两个链表的第一个公共点

来源:互联网 发布:水岛宏 知乎 编辑:程序博客网 时间:2024/06/05 17:12

1,问题:

输入两个链表,找出它们的第一个公共结点。(现在只考虑都是无环的)

2,想法

(1),先求出两个链表的长度,用两个指针,长链表的指针先走长度之差那么多步,然后两个指针一起走,遇到指针相同的就返回。

(2),遍历两个链表,把指针入栈,然后再同时出栈,若遇到不相同的则返回上一个相同的栈元素。

3,编码为:

/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:    ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {        if (pHead1 == NULL || pHead2 == NULL)        {            return NULL;        }        /*int length1 = 0;        int length2 = 0;        ListNode* pNewHead1 = pHead1;        ListNode* pNewHead2 = pHead2;        bool flag = false;        while (pNewHead1 != NULL)        {            length1++;            pNewHead1 = pNewHead1->next;        }        while (pNewHead2 != NULL)        {            length2++;            pNewHead2 = pNewHead2->next;        }        int count = 0;        if (length1 >= length2)        {            count = length1 - length2;            flag = true;        }        else            count = length2 - length1;        pNewHead1 = pHead1;        pNewHead2 = pHead2;        int i;        for (i = 0; i < count; i++)        {            if (flag)            {                pNewHead1 = pNewHead1->next;            }            else                pNewHead2 = pNewHead2->next;        }        while (pNewHead1 != NULL && pNewHead2 != NULL)        {            if (pNewHead1 == pNewHead2)            {                return pNewHead1;            }            else            {                pNewHead1 = pNewHead1->next;                pNewHead2 = pNewHead2->next;            }        }        return NULL;        */        stack<ListNode*> temp1;        stack<ListNode*> temp2;        ListNode* pNewHead1 = pHead1;        ListNode* pNewHead2 = pHead2;        while (pNewHead1)        {            temp1.push(pNewHead1);            pNewHead1 = pNewHead1->next;        }        while (pNewHead2)        {            temp2.push(pNewHead2);            pNewHead2 = pNewHead2->next;        }        pNewHead1 = NULL;        pNewHead2 = NULL;        while (!temp1.empty() && !temp2.empty())        {            if (temp1.top() == temp2.top())            {                pNewHead1 = temp1.top();                pNewHead2 = temp2.top();                temp1.pop();                temp2.pop();            }            else                return pNewHead1;        }        return pNewHead1;    }};
4,若链表有环,怎么找到环的入口?

(1),设两个指针,初始都为头指针,一个slow指针,每次走一步,另一个fast指针,每次走两步,若有环,则必定相遇。找到相遇点后,slow指针重回头指针,而fast指针在相遇点,两个指针同时走,每次都走一步,下次必在入口点相遇。

5,若两个链表都可能有环,怎么计算出第一个公共点?

想法(1):

还是计算两个链表的长度,至于判断重复访问问题,用一个map<node*, int>来判断。若已经访问过了就break,不然就加入到map中。

具体代码:

<pre name="code" class="cpp">// 循环链表第一个公共节点.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <map>#include <iostream>using namespace std;class node{public:int data;node* next;node(){};node(int x):data(x),next(NULL){};};node* FindFirstCommonNode(node* p1, node* p2){if (p1 == NULL || p2 == NULL){return NULL;}map<node*, int> mp1;map<node*, int> mp2;node *p1new = p1;node *p2new = p2;int length1 = 0;int length2 = 0;bool flag = false;while (p1new != NULL){if (mp1.count(p1new))//表示已经访问过了{break;}else{mp1[p1new] = 1;length1++;p1new = p1new->next;}}while (p2new != NULL){if (mp2.count(p2new)){break;}else{mp2[p2new] = 1;length2++;p2new = p2new->next;}}p1new = p1;p2new = p2;int count = 0;if (length1 >= length2){count = length1 - length2;flag = true;}elsecount = length2 - length1;for (int i = 0; i < count; i++){if (flag){p1new = p1new->next;}elsep2new = p2new->next;}while (p1new != NULL && p2new != NULL){if (p1new == p2new){return p1new;}else{p1new = p1new->next;p2new = p2new->next;}}return NULL;}int _tmain(int argc, _TCHAR* argv[]){node* p1Head = NULL;node* p2Head = NULL;//以下代码是随便建立的两个链表,不必深究node* p1 = new node(1);p1Head = p1;int temp = -1;node* dd = NULL;int num;while (temp != 0){cin >> num;temp = num;if (temp != 0){p1->next = new node(temp);p1 = p1->next;if (temp == 4)//节点值为4的为第一个公共节点{dd = p1;}}}p1 = p1Head;while (p1){cout << p1->data << endl;p1 = p1->next;}temp = -1;node* p2 = new node(6);p2Head = p2;while (temp != 0){cin >> num;temp = num;if (temp != 0){p2->next = new node(temp);p2 = p2->next;}}p2->next = dd;//第二个链表从节点值为4的那里开始链接第一个链表的后续结点p2 = p2Head;while (p2){cout << p2->data << endl;p2 = p2->next;}node* c = FindFirstCommonNode(p1Head, p2Head);    cout << c->data << endl;system("pause");return 0;}




1 0
原创粉丝点击