输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
数据范围:
要求:空间复杂度
,时间复杂度 )
要求:空间复杂度
例如,输入{1,2,3},{4,5},{6,7}时,两个无环的单向链表的结构如下图所示:
可以看到它们的第一个公共结点的结点值为6,所以返回结点值为6的结点。
输入分为是3段,第一段是第一个链表的非公共部分,第二段是第二个链表的非公共部分,第三段是第一个链表和第二个链表的公共部分。 后台会将这3个参数组装为两个链表,并将这两个链表对应的头节点传入到函数FindFirstCommonNode里面,用户得到的输入只有pHead1和pHead2。
返回传入的pHead1和pHead2的第一个公共结点,后台会打印以该节点为头节点的链表。
{1,2,3},{4,5},{6,7}{6,7}第一个参数{1,2,3}代表是第一个链表非公共部分,第二个参数{4,5}代表是第二个链表非公共部分,最后的{6,7}表示的是2个链表的公共部分
这3个参数最后在后台会组装成为2个两个无环的单链表,且是有公共节点的 {1},{2,3},{}{}2个链表没有公共节点 ,返回null,后台打印{} /*function ListNode(x){
this.val = x;
this.next = null;
}*/
function FindFirstCommonNode(pHead1, pHead2)
{
// write code here
let set1 = new Set();
while(pHead1){
set1.add(pHead1);
pHead1 = pHead1.next;
}
while(pHead2){
if(set1.has(pHead2)){
return pHead2;
}
pHead2 = pHead2.next;
}
return null;
}
module.exports = {
FindFirstCommonNode : FindFirstCommonNode
}; function FindFirstCommonNode(pHead1, pHead2)
{
let cur1 = pHead1
let cur2 = pHead2
let myset = new Set()
while(cur1!==null){
if(!myset.has(cur1)){
myset.add(cur1)
cur1 = cur1.next
}else{
return cur1
}
}
while(cur2!==null){
if(!myset.has(cur2)){
myset.add(cur2)
cur2 = cur2.next
}else{
return cur2
}
}
return null
}
使用集合做的巧妙解法
function FindFirstCommonNode(pHead11, pHead22)
{
// write code here
let pHead1=pHead11;
let pHead2=pHead22;
while(pHead1!=pHead2){
pHead1=pHead1==null?pHead22:pHead1.next;
pHead2=pHead2==null?pHead11:pHead2.next;
}
return pHead2;
}
module.exports = {
FindFirstCommonNode : FindFirstCommonNode
}; /*function ListNode(x){
this.val = x;
this.next = null;
}*/
function FindFirstCommonNode(pHead1, pHead2)
{
let list = {};
let path = 1;
while(pHead1){
list[pHead1.val] = path;
pHead1 = pHead1.next;
path ++;
}
let min = path;
let result = null;
while(pHead2){
if(list[pHead2.val] && list[pHead2.val] <= min){
result = pHead2;
min = list[pHead2.val];
}
pHead2 = pHead2.next;
}
return result;
} /*function ListNode(x){
this.val = x;
this.next = null;
}*/
/**
* 我的解题思路:
* 1.emmmm,这个问题之前面头条的时候被问到过,没答出来的但是面试官给讲了思路哈哈哈,这次做出来了
* 2.先让两个链表同时开始遍历,直到较短的那个链表所有节点都被遍历
* 3.让较长的链表从头开始遍历,直到第二步中剩余部分遍历完成,此时长链表剩余部分与短链表长度相同
* 4.直接顺序遍历两个链表,找到节点值相同的节点并返回即可,若找不到相同节点,返回null
*
* @param {*} pHead1
* @param {*} pHead2
*/
function FindFirstCommonNode(pHead1, pHead2)
{
// write code here
let temp1 = pHead1;
let temp2 = pHead2;
while (temp1 && temp2) {
temp1 = temp1.next;
temp2 = temp2.next;
}
while (temp1) {
pHead1 = pHead1.next;
temp1 = temp1.next;
}
while (temp2) {
pHead2 = pHead2.next;
temp2 = temp2.next;
}
while (pHead1 && pHead2 && pHead1.val !== pHead2.val) {
pHead1 = pHead1.next;
pHead2 = pHead2.next;
}
return pHead1;
}
/**
* 评论区TOP的解题思路:
* 1.思路还是那个思路,跟我的类似,只不过它采取了更简洁的写法
* 2.遍历两个链表,直到找到相同的节点,结束遍历(在JS中无法直接比较节点,这里采用JSON.stringify转成字符串再比较的方式处理)
* 3.若未找到相同节点,则继续遍历,如果发现短链表遍历结束,那么将短链表指向长链表的头部继续进行遍历,此时遍历的部分为全新的长链表和剩余部分的长链表
* 4.在之前长链表剩余部分遍历完成之后,另一个长链表已经走出了多出的长度,此时让为空的长链表指向短链表的头部,这样得到的两个链表长度就一致了
* 5.继续进行遍历,直到找到相同节点即可
*
* @param {*} pHead1
* @param {*} pHead2
*/
function topFindFirstCommonNode(pHead1, pHead2)
{
// write code here
let temp1 = pHead1;
let temp2 = pHead2;
while (JSON.stringify(temp1) !== JSON.stringify(temp2)) {
temp1 = temp1 ? temp1.next : pHead2;
temp2 = temp2 ? temp2.next : pHead1;
}
return temp1;
}
function ListNode(x){
this.val = x;
this.next = null;
}
function FindFirstCommonNode(pHead1, pHead2)
{
// write code here
var arr1 = [];
var curr1 = pHead1;
var curr2 = pHead2;
while(curr1 != null){
arr1.push(curr1.val);
curr1 = curr1.next;
}
while(curr2 != null){
if(arr1.includes(curr2.val))
return curr2;
curr2 = curr2.next;
}
}
module.exports = {
FindFirstCommonNode : FindFirstCommonNode
}; function ListNode(x){
this.val = x;
this.next = null;
}
function FindFirstCommonNode(pHead1, pHead2)
{
// 让链表成环
let pNode2 = pHead2;
while (pNode2.next) {
pNode2 = pNode2.next;
}
pNode2.next = pHead2;
// 快慢针判断成环链表的环起点
let fast = pHead1;
let slow = pHead1;
while (fast && fast.next) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
fast = pHead1;
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return fast;
}
}
return null;
} /*function ListNode(x){
this.val = x;
this.next = null;
}*/
function FindFirstCommonNode(pHead1, pHead2)
{
// write code here
let len1 = 0;
let len2 = 0;
let curr1 = pHead1;
let curr2 = pHead2;
while(curr1){
len1 ++;
curr1 = curr1.next;
}
while(curr2){
len2 ++;
curr2 = curr2.next;
}
curr1 = pHead1;
curr2 = pHead2;
if(len1 > len2){
let diff = len1 - len2;
while(diff--){
curr1 = curr1.next;
}
}else{
let diff = len2 - len1;
while(diff--){
curr2 = curr2.next;
}
}
while(curr1 !== curr2){
curr1 = curr1.next;
curr2 = curr2.next;
}
return curr1;
} function ListNode(x) {
this.val = x;
this.next = null;
}
function FindFirstCommonNode(pHead1, pHead2) {
// write code here
let myMap = new Map();
let p = pHead1;
let q = pHead2;
while (p) {
myMap.set(p, 1);
p = p.next;
}
while (q) {
if (myMap.has(q)) {
return q;
}
q = q.next;
}
return;
}
var l1 = new ListNode(1);
var l2 = new ListNode(2);
var l3 = new ListNode(3);
var l4 = new ListNode(4);
var l5 = new ListNode(5);
l1.next = l2;
l2.next = l3;
l3.next = l4;
l4.next = l5;
var l6 = new ListNode(6);
var l7 = new ListNode(7);
var l8 = new ListNode(8);
var l9 = new ListNode(9);
l6.next = l7;
l7.next = l8;
l8.next = l3;
let res = FindFirstCommonNode(l1, l6);
console.log(res);
function ListNode(x){
return {
val:x,
next:null
}
}
function FindFirstCommonNode(pHead1, pHead2)
{
// write code here
while(pHead1) {
pHead1.tag = true
pHead1 = pHead1.next
}
while(pHead2) {
if(pHead2.tag) {
pHead2.tag = undefined
return pHead2
} else {
pHead2 = pHead2.next
}
}
return null
} function FindFirstCommonNode(pHead1, pHead2) {
if (!pHead1 || !pHead2) { return null; }
// 获取链表长度
let length1 = getLength(pHead1);
let length2 = getLength(pHead2);
// 长链表先行
let lang, short, interval;
if (length1 > length2) {
lang = pHead1;
short = pHead2;
interval = length1 - length2;
} else {
lang = pHead2;
short = pHead1;
interval = length2 - length1;
}
while (interval--) {
lang = lang.next;
}
// 找相同节点
while (lang) {
if (lang === short) {
return lang;
}
lang = lang.next;
short = short.next;
}
return null;
}
function getLength(head) {
let current = head;
let result = 0;
while (current) {
result++;
current = current.next;
}
return result;
}
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function FindFirstCommonNode(pHead1, pHead2)
{
// write code here
var len1 = 0; //记录pHead1的长度
var len2 = 0; //记录pHead2的长度
var p1=pHead1; //指向pHead1的首节点
var p2=pHead2; //指向pHead2的首节点
//遍历链表pHead1,记录其长度len1
while(p1 != null){
len1++;
p1=p1.next;
}
//遍历链表pHead2,记录其长度len2
while(p2 != null){
len2++;
p2=p2.next;
}
//比较len1和len2大小,对于更长的链表,先指向其第|len1-len2|个节点
p1=pHead1;
p2=pHead2;
if(len1 > len2){
var num = len1-len2;
for(var i=0;i<num; i++){
p1=p1.next;
}
}
if(len1 < len2){
var num = len2-len1;
for(var i=0;i<num; i++){
p2=p2.next;
}
}
//以当前p1,p2所指向的节点为基础,依次比较其指向的节点是否相同,若不相同,则指向next节点;若相同,则该节点为第一个公共节点,返回当前节点。
while(p1 != null){
if(p1 == p2){
return p1;
}
p1=p1.next;
p2=p2.next;
}
return false;
}
/* 找出2个链表的长度,然后让长的先走两个链表的长度差,然后再一起走 (因为2个链表用公共的尾部) */ 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; } };