版权声明:本文为博主NJU_ChopinXBP原创文章,发表于CSDN,仅供交流学习使用,转载请私信或评论联系,未经博主允许不得转载。感谢您的评论与点赞。 https://blog.csdn.net/qq_20304723/article/details/83240255
2018.10.21
这道题也是属于效率题,实现难度不大,但是要降低复杂度还是需要思考一下。有两个o(n)的做法:
方法一:等长链表法。先计算两条链表的长度,然后先遍历长链表直到两条链表等长,最后依次按奇偶顺序挨个遍历两条链表各个结点。
方法二:辅助栈法(需要开辟栈空间)。注意到链表公共结点后的所有结点都是公共的,可以将两条链表元素分别入栈,依次检验栈顶元素,最后一个相同的栈顶元素为第一个公共结点。
注意几个特殊情况:1.只有一个结点,2.短链表为长链表的子链表,3.没有公共结点
题目描述
输入两个链表,找出它们的第一个公共结点。
Java实现:
/**
*
* @author ChopinXBP
* 输入两个链表,找出它们的第一个公共结点。
*
*/
import java.util.LinkedList;
public class FindFirstCommonNode_35 {
public static class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ListNode Node0 = new ListNode(0);
ListNode Node1 = new ListNode(1);
ListNode Node2 = new ListNode(2);
ListNode Node3 = new ListNode(3);
ListNode Node4 = new ListNode(4);
ListNode Node5 = new ListNode(5);
ListNode Node6 = new ListNode(6);
Node0.next = Node1;
Node1.next = Node2;
Node2.next = Node3;
Node3.next = Node4;
Node4.next = Node5;
Node5.next = Node6;
System.out.println(FindFirstCommonNode(Node0, Node6).val);
System.out.println(FindFirstCommonNode2(Node0, Node6).val);
}
//方法1:等长遍历法(不需要开辟栈空间)
public static ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null) return null;
if(pHead1 == pHead2) return pHead1;
//计算链表1的长度
ListNode plong = pHead1;
int length1 = 1;
while(plong.next != null){
plong = plong.next;
length1++;
}
//计算链表2的长度
ListNode pshort = pHead2;
int length2 = 1;
while(pshort.next != null){
pshort = pshort.next;
length2++;
}
//确定链表长短与差值num
int num;
if(length1 > length2){
plong = pHead1;
pshort = pHead2;
num = length1 - length2;
}else{
plong = pHead2;
pshort = pHead1;
num = length2 - length1;
}
//遍历长链表前num个结点,使两链表等长
while(num-- > 0){
if(plong == pshort)return plong;
plong = plong.next;
}
//依次遍历两个链表的每一个结点,num用于奇偶标志
num = 0;
while(plong.next != null || pshort.next != null){
if(plong == pshort) return plong;
if((num & 0x01) == 0){
plong = plong.next;
}else{
pshort = pshort.next;
}
num++;
}
if(plong == pshort)return plong;
return null;
}
//方法2:辅助栈法
public static ListNode FindFirstCommonNode2(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null) return null;
if(pHead1 == pHead2) return pHead1;
//元素入栈
LinkedList<ListNode> p1stack = new LinkedList<>();
LinkedList<ListNode> p2stack = new LinkedList<>();
ListNode pListNode = pHead1;
while(pListNode != null){
p1stack.add(pListNode);
pListNode = pListNode.next;
}
pListNode = pHead2;
while(pListNode != null){
p2stack.add(pListNode);
pListNode = pListNode.next;
}
//依次检验栈顶元素。如果栈顶元素不想等直接返回初始的pListNode,此时的pListNode为null
while(!p1stack.isEmpty() && !p2stack.isEmpty()){
if(p1stack.getLast() == p2stack.getLast()){
pListNode = p1stack.getLast();
p1stack.pollLast();
p2stack.pollLast();
if(p1stack.isEmpty() || p2stack.isEmpty()) return pListNode;
}else{
return pListNode;
}
}
return null;
}
}
C++实现示例(方法一):
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {
int len1 = findListLenth(pHead1);
int len2 = findListLenth(pHead2);
if(len1 > len2){
pHead1 = walkStep(pHead1,len1 - len2);
}else{
pHead2 = walkStep(pHead2,len2 - len1);
}
while(pHead1 != NULL){
if(pHead1 == pHead2) return pHead1;
pHead1 = pHead1->next;
pHead2 = pHead2->next;
}
return NULL;
}
int findListLenth(ListNode *pHead1){
if(pHead1 == NULL) return 0;
int sum = 1;
while(pHead1 = pHead1->next) sum++;
return sum;
}
ListNode* walkStep(ListNode *pHead1, int step){
while(step--){
pHead1 = pHead1->next;
}
return pHead1;
}
};
测试代码:
// ====================测试代码====================
void DestroyNode(ListNode* pNode);
void Test(char* testName, ListNode* pHead1, ListNode* pHead2, ListNode* pExpected)
{
if(testName != NULL)
printf("%s begins: ", testName);
ListNode* pResult = FindFirstCommonNode(pHead1, pHead2);
if(pResult == pExpected)
printf("Passed.\n");
else
printf("Failed.\n");
}
// 第一个公共结点在链表中间
// 1 - 2 - 3 \
// 6 - 7
// 4 - 5 /
void Test1()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ListNode* pNode6 = CreateListNode(6);
ListNode* pNode7 = CreateListNode(7);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode6);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);
Test("Test1", pNode1, pNode4, pNode6);
DestroyNode(pNode1);
DestroyNode(pNode2);
DestroyNode(pNode3);
DestroyNode(pNode4);
DestroyNode(pNode5);
DestroyNode(pNode6);
DestroyNode(pNode7);
}
// 没有公共结点
// 1 - 2 - 3 - 4
//
// 5 - 6 - 7
void Test2()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ListNode* pNode6 = CreateListNode(6);
ListNode* pNode7 = CreateListNode(7);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);
Test("Test2", pNode1, pNode5, NULL);
DestroyList(pNode1);
DestroyList(pNode5);
}
// 公共结点是最后一个结点
// 1 - 2 - 3 - 4 \
// 7
// 5 - 6 /
void Test3()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ListNode* pNode6 = CreateListNode(6);
ListNode* pNode7 = CreateListNode(7);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode7);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);
Test("Test3", pNode1, pNode5, pNode7);
DestroyNode(pNode1);
DestroyNode(pNode2);
DestroyNode(pNode3);
DestroyNode(pNode4);
DestroyNode(pNode5);
DestroyNode(pNode6);
DestroyNode(pNode7);
}
// 公共结点是第一个结点
// 1 - 2 - 3 - 4 - 5
// 两个链表完全重合
void Test4()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
Test("Test4", pNode1, pNode1, pNode1);
DestroyList(pNode1);
}
// 输入的两个链表有一个空链表
void Test5()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
Test("Test5", NULL, pNode1, NULL);
DestroyList(pNode1);
}
// 输入的两个链表有一个空链表
void Test6()
{
Test("Test6", NULL, NULL, NULL);
}
void DestroyNode(ListNode* pNode)
{
delete pNode;
pNode = NULL;
}
int _tmain(int argc, _TCHAR* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
return 0;
}
#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#