LeetCode|Intersection of Two Linked Lists

【问题描述】

Write a program to find the node at which the intersection of two singly linked lists begins.


For example, the following two linked lists:

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

begin to intersect at node c1.


Notes:

  • If the two linked lists have no intersection at all, return null.
  • The linked lists must retain their original structure after the function returns.
  • You may assume there are no cycles anywhere in the entire linked structure.
  • Your code should preferably run in O(n) time and use only O(1) memory.
【解答1】

从尾部开始比较,相等则更新rh。否则跳出循环。返回rh即可。

用到了两个栈,来倒序访问list中元素。

时间复杂度:O(n)

空间复杂度:O(n)

class Solution {
public:
	ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
		ListNode* h1 = headA;
		ListNode* h2 = headB;
		ListNode* rh=NULL;
		stack<ListNode*> prev1;
		stack<ListNode*> prev2;

		if (h1 == NULL || h2 == NULL)
			return NULL;
		while (h1 != NULL) {
			prev1.push(h1);
			h1 = h1->next;
		}
		while (h2 != NULL) {
			prev2.push(h2);
			h2 = h2->next;
		}
		while(!prev1.empty() && !prev2.empty())
		{
			if(prev1.top()==prev2.top())
			{
				rh=prev1.top();
				prev1.pop();
				prev2.pop();
			}
			else break;
		}
		return rh;
	}
};
第一次一次性写完就提交成功O(∩_∩)O哈哈~

运行时间48ms,击败了90几%的人,不错~不过空间复杂度可以改进下的。

继续改进~

【解答2】

记录两个链表的长度,求长度差,从两个链表所剩长度相等处,开始进行比较。

时间复杂度:O(n)

空间复杂度:O(1)

class Solution {
public:
	ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
		ListNode* h1 = headA;
		ListNode* h2 = headB;
		ListNode* rh=NULL;
		int len1=0;
		int len2=0;
		int dist=0;

		if (h1 == NULL || h2 == NULL)
			return NULL;
		for(;h1!=NULL;h1=h1->next)
			len1++;
		for(;h2!=NULL;h2=h2->next)
			len2++;
		h1=headA;
		h2=headB;
		dist=abs(len1-len2);//abs在头文件stdlib.h中,不是math.h
		if(len1>=len2)
			while(dist!=0)
			{
				h1=h1->next;
				dist--;
			}
		else
			while(dist!=0)
			{
				h2=h2->next;
				dist--;
			}
		while(h1!=NULL)
		{
			if(h1->val==h2->val)
			{
				rh=h1;
				break;
			}
			h1=h1->next;
			h2=h2->next;
		}
		return rh;
	}
};

运行时间52ms。


【解答3】

参考LeetCode里这道题的答案3,觉得很精妙,尝试编写。

用双指针,遍历,每次一个元素。当到达一个链表的末尾时,就将该指针指向另一个链表表头。这样其实相当于第二种方法中,从长度相同处开始比较。

此方法使用时候,要认真考虑边界的处理。是判断h1==NULL还是h1->next==NULL,要考虑好。如果写成h1->next的话,你会发现,如果两个链表没有交叉,那这就是个死循环啊!!

时间复杂度:O(n)

空间复杂度:O(1)

class Solution {
public:
	ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
		ListNode* h1 = headA;
		ListNode* h2 = headB;
		ListNode* rh=NULL;

		if (h1 == NULL || h2 == NULL)
			return NULL;
		while(h1!=NULL || h2!=NULL)
		{
			if(h1!=NULL && h2!=NULL && h1->val==h2->val)//最开始忘记检测h1和h2是否为空,导致程序崩溃
			{
				rh=h1;
				break;
			}
			h1=h1==NULL?headB:h1->next;
			h2=h2==NULL?headA:h2->next;
			
		}
		return rh;
	}
};
代码变短了,逼格提升了,但运行时间为56ms啊~只击败了10几%的人。是因为这个while进来每次都要判断吗?


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值