开宗明义:本系列基于小象学院林沐老师课程《面试算法 LeetCode 刷题班》,刷题小白,旨在理解和交流,重在记录,望各位大牛指点!
Leetcode学习之链表(2)
1、链表求交点 LeetCode 160
题目来源:
L
e
e
t
C
o
d
e
160.
I
n
t
e
r
s
e
c
t
i
o
n
o
f
T
w
o
L
i
n
k
e
d
L
i
s
t
LeetCode \ 160.\ Intersection \ of \ Two \ Linked \ List
LeetCode 160. Intersection of Two Linked List
题目描述:已知链表A的头节点指针
h
e
a
d
A
head \ A
head A,链表B的头节点指针
h
e
a
d
B
head \ B
head B,两个链表相交,求两链表交点对应的节点。
题目要求:
- 如果两个链表没有交点,则返回 NULL;
- 在求交点的过程中,不可以破坏链表的结构或者修改结构的数据域;
- 可以确保传入的链表A与链表B没有任何环;
- 实现算法尽可能使时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)。
要求描述:
1.1 set的使用
S
T
L
STL
STL里面的
s
e
t
set
set,集合——每个元素最多只出现一次,并且元素已经从小到大排好序。
c
+
+
c++
c++使用时包含
#
i
n
c
l
u
d
e
<
s
e
t
>
\#include \ <set>
#include <set>
小试牛刀:判断两组数组中是否有相同元素,
O
(
n
)
O(n)
O(n)或者
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的复杂度
测试代码:
#include <set>
using namespace std;
int main()
{
set<int> test_set;
const int A_LEN = 7; //测试数组A与B的长度
const int B_LEN = 8;
//a,b中有重复元素
int a[A_LEN] = {5,1,4,8,10,1,3};
int b[B_LEN] = {2,7,6,3,1,6,0,1};
for (int i = 0; i < A_LEN; i++)
{
test_set.insert(a[i]);//将数组a元素插入set中
}
//检查数组b中元素是否存在a中
for (int i = 0; i < B_LEN; i++)
{
if (test_set.find(b[i]) != test_set.end())
//用来查找set中某个元素出现的位置。如果找到,就返回这个元素的迭代器,如果这个元素不存在,则返回 s.end() 。
//(最后一个元素的下一个位置,s为set的变量名)
{
printf("b[%d]=%d in array A.\n",i,b[i]);
}
}
system("pause");
return 0;
}
效果图:
总结:
1.begin():返回set容器的第一个迭代器
2.end():返回set容器的最后一个迭代器
3.clear():删除set容器中的所有的元素
4.empty():判断set容器是否为空
5.max_size():返回set容器可能包含的元素最大个数
6.size():返回当前set容器中的元素个数
7.rbegin:返回的值和end()相同
8.rend():返回的值和rbegin()相同
9..insert(a):插入元素
10..count():用来查找set中某个元素出现的次数。这个函数在set并不是很实用,因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了。
11..find():用来查找set中某个元素出现的位置。如果找到,就返回这个元素的迭代器,如果这个元素不存在,则返回 s.end() 。 (最后一个元素的下一个位置,s为set的变量名)
1.2 思路①
思路①:使用
s
e
t
set
set求交集,
O
(
n
)
O(n)
O(n)或者
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的复杂度
1、遍历链表
A
A
A,将
A
A
A中节点对应的指针(地址),插入
s
e
t
set
set;
2、遍历链表
B
B
B,将
B
B
B中节点对应的指针(地址),在
s
e
t
set
set中查找,在
s
e
t
set
set中的第一个节点地址,即两个链表的交点;
测试代码:
#include <stdio.h>
#include <set>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) :val(x), next(NULL) {}
};
class Solution {
public://A,B的头节点指针
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
set<ListNode *> node_set;//设置查找集合node_set
while (headA)
{
node_set.insert(headA);//将链表A中的节点插入node_set
headA = headA->next;//遍历链表A
}
while (headB)
{
if (node_set.find(headB) != node_set.end())
{
return headB;
}
headB = headB->next;//遍历链表B
}
return NULL;
}
};
int main()
{
ListNode a1(1), a2(2), b1(3), b2(4), b3(5), c1(6), c2(7), c3(8);
a1.next = &a2;
a2.next = &c1;
c1.next = &c2;
c2.next = &c3;
b1.next = &b2;
b2.next = &b3;
b3.next = &c1;
Solution solve;
ListNode *result = solve.getIntersectionNode(&a1, &b1);
printf("%d\n",result->val);
system("pause");
return 0;
}
效果图:
1.3 思路②
空间复杂度
O
(
1
)
O(1)
O(1):
思路②:
- 计算 h e a d A headA headA链表长度,计算 h e a d B headB headB链表长度,得出较长的链表多出的长度;
- 将较长链表的指针移动到和较短链表指针对齐的位置;
- h e a d A headA headA与 h e a d B headB headB同时移动,当两指针指向同一个节点时,即找到了。
cesh测试代码:
#include <stdio.h>
#include <set>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) :val(x), next(NULL) {}
};
//返回链表长度
int get_list_length(ListNode *head)
{
int len = 0;
while (head)
{
len++;
head = head->next;
}
return len;
}
ListNode *forward_long_list(int long_len,int short_len,ListNode *head)
{
int data = long_len - short_len;
while (head && data) {
head = head->next;
data--;
}
return head;
}
class Solution {
public://A,B的头节点指针
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int list_A_len = get_list_length(headA);
int list_B_len = get_list_length(headB);//求链表A、B长度
if (list_A_len > list_B_len) {
headA = forward_long_list(list_A_len, list_B_len, headA);//如果链表A长,移动A到对应位置
}
else{
headB = forward_long_list(list_B_len, list_A_len, headB);
}
while (headA && headB)
{
if (headA == headB) { //当两指针指向同一个节点时候,说明找到了
return headA;
}
headA = headA->next;
headB = headB->next;
}
return NULL;
}
};
int main()
{
ListNode a1(1), a2(2), b1(3), b2(4), b3(5), c1(6), c2(7), c3(8);
a1.next = &a2;
a2.next = &c1;
c1.next = &c2;
c2.next = &c3;
b1.next = &b2;
b2.next = &b3;
b3.next = &c1;
Solution solve;
ListNode *result = solve.getIntersectionNode(&a1, &b1);
printf("%d\n",result->val);
system("pause");
return 0;
}