-
Notifications
You must be signed in to change notification settings - Fork 634
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
图解字节&leetcode160:编写一个程序,找到两个单链表相交的起始节点 #17
Comments
方法:遍历
function intersectNode( head1, head2 ) {
var arr1 = [],
arr2 = [],
theValue = null;
transformToArray( head1, arr1 );
transformToArray( head2, arr2 );
for (var i = 0; i < arr1.length; i++) {
if( arr2.indexOf(arr1[i]) !== -1 ){
theValue = arr1[i];
return 'Reference of the node with value = ' + theValue;
}
}
return theValue;
/*
arr1.some( value => {
if ( arr2.includes(value) ){
theValue = value;
return true;
}
})
if( theValue ){
return 'Reference of the node with value = ' + theValue;
}
return null;
*/
}
function transformToArray( head, arr ) {
while( head ){
arr.push(head.val);
head = head.next;
}
} 测试代码: function CreateNode(val){
this.val = val;
this.next = null;
}
function CreateList(...nodes){
this.head = nodes[0];
this.length = nodes.length;
for( var i = 0; i < nodes.length - 1; i++ ){
if( nodes[i+1] ){
nodes[i].next = nodes[i+1];
}
}
}
function intersectNode( head1, head2 ) {
var arr1 = [],
arr2 = [],
theValue = null;
transformToArray( head1, arr1 );
transformToArray( head2, arr2 );
for (var i = 0; i < arr1.length; i++) {
if( arr2.indexOf(arr1[i]) !== -1 ){
theValue = arr1[i];
return 'Reference of the node with value = ' + theValue;
}
}
return theValue;
}
function transformToArray( head, arr ) {
while( head ){
arr.push(head.val);
head = head.next;
}
}
const node1 = new CreateNode(1);
const node2 = new CreateNode(2);
const node3 = new CreateNode(3);
const node4 = new CreateNode(4);
const node5 = new CreateNode(5);
const nodeA = new CreateNode('A');
const nodeB = new CreateNode('B');
const nodeC = new CreateNode('C');
const nodeD = new CreateNode('D');
const nodeE = new CreateNode('E');
const list1 = new CreateList(node1, node2, node3, node4, node5);
const list2 = new CreateList(nodeA, nodeB, node3, nodeC, nodeD);
intersectNode(list1.head, list2.head); |
var getIntersectionNode = function (headA, headB) {
var map = new WeakMap()
while (headA) {
map.set(headA, true)
headA = headA.next
}
while (headB) {
var curr = map.get(headB)
if (curr) return headB
headB = headB.next
}
return null
}; |
解法一:标记法(简单但空间复杂度为O(n),不符合,仅做参考)解题思路: 两次遍历,先遍历一个链表,给链表中的每个节点都增加一个标志位,然后遍历另外一个链表,遍历到第一个已被标志过的节点为两链表相交的起始节点。 若遍历完都没有发现已被标志过的节点,则两链表不相交,返回 const getIntersectionNode = function(headA, headB) {
while(headA) {
headA.flag = true
headA = headA.next
}
while(headB) {
if (headB.flag) return headB
headB = headB.next
}
return null
}; 时间复杂度:O(n) 空间复杂度:O(n) 解法二:双指针法解题思路: 如果 A、B 两链表相交,则 A 、B 自相交点往后的链表是一致的。 我们可以尝试消除 A、B 链表的长度差,同步遍历上图中的方框里的节点,判断是否有相同节点,若有相同则是两链表相交,返回第一个相同节点 即可。否则返回 解题步骤:
画图帮助理解: const getIntersectionNode = function(headA, headB) {
// 清除高度差
let pA = headA, pB = headB
while(pA || pB) {
if(pA === pB) return pA
pA = pA === null ? headB : pA.next
pB = pB === null ? headA : pB.next
}
return null
}; 时间复杂度:O(n) 空间复杂度:O(1) |
想法不错,不过可以进阶一下,使用双指针来做,使之尽量满足空间复杂度O(1) |
你好,我想问一下,if(pA === pB) return pA。这行代码怎么理解?题目表示是两个单独的链表,链表里的节点都是对象,对象的这种===会有效吗?他们两个好像是指向不同的地址空间把。是不是应该比较pA与pB的值才行。改为if(pA.val===pB) return pA;会不会更好一点? |
const getIntersectionNode = (head1, head2) => {
const h1 = head1
const h2 = head2
while (h1 || h2) {
if(h1.data === h2.data) return h1
h1 = h1 === null ? head2 : h1.next
h2 = h2 === null ? head1 : h2.next
}
return null
} |
WeakMapvar getIntersectionNode = function (headA, headB) {
let currenA = headA, currenB = headB;
let map = new WeakMap();
while(currenA) {
map.set(currenA, true);
currenA = currenA.next;
}
while(currenB) {
if(map.has(currenB)) return currenB.val;
currenB = currenB.next;
}
return null;
}; 双指针var getIntersectionNode = function (headA, headB) {
let currentA = headA, currentB = headB;
while(currentA || currentB) {
if(currentB === currentA) return currentA;
currentA = currentA === null ? headB : currentA.next;
currentB = currentB === null ? headA : currentB.next;
}
return null;
}; |
const getIntersectionNode = (headA, headB) => {
if (!headA || !headB) {
return null;
}
let tailA = headA;
let tailB = headB;
let stackA = [];
let stackB = [];
// 获取链表A的尾结点
while (tailA.next) {
stackA.push(tailA);
tailA = tailA.next;
}
// 获取链表B的尾结点
while (tailB.next) {
stackB.push(tailB);
tailB = tailB.next;
}
let count = 1;
while (stackA.length && stackB.length) {
// 如果尾结点相等,往前移动指针
if (tailA === tailB) {
tailA = stackA.pop();
tailB = stackB.pop();
count++;
}
// 否则代表到了不相交初了,终止遍历
else {
break;
}
}
/**
* count为1有两种情况
* 第一种:链表A和链表B都只有一个节点,那么判断他们是否相等即可
* 第二种:遍历俩链表都没有相等的节点,证明俩链表不相交,返回null
*/
if (count === 1) {
return tailA === tailB ? tailA : null;
}
/**
* 同理存在两种情况
* 第一种:遍历完俩链表,每个节点都相等,那么返回头节点
* 第二种:在不相交的节点处循环中断了,相交节点应该等于当前节点的下一个节点
*/
return tailA === tailB ? tailA : tailA.next;
}; |
我觉得 我自己实现了的方案,也是 class Node {
public next: Node | undefined;
constructor (public element: any) {}
}
const getInsersectionNode = (headA: Node, headB: Node) => {
const map = new Map();
if (headA === headB) return headA;
let nextA: Node | undefined = headA;
let nextB: Node | undefined = headB;
while (nextA || nextB) {
if (map.get(nextA)) return nextA;
if (map.get(nextB)) return nextB;
if (nextA) {
map.set(nextA, true);
nextA = nextA.next;
}
if (nextB) {
map.set(nextB, true);
nextB = nextB.next;
}
}
return undefined;
}; |
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
在节点 c1 开始相交。
示例 1:
示例 2:
示例 3:
注意:
附leetcode地址:leetcode
The text was updated successfully, but these errors were encountered: