/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
if(head===null||head.next===null){ //用于[],[1]的情况
return head;
}
let pre=head; //图1,设置虚拟头结点
let cur=head.next;
let nhead=new ListNode(0,head)
nhead.next=cur //图2,不改变节点内的值的前提下,交换节点2和节点1,并且交换二者的指向
pre.next=cur.next
cur.next=pre
head=cur//记录头结点,所以在while循环外先进行第一次交换
while(cur!==null){
if(pre.next===null||pre.next.next===null) //判断结束,图1(2、3)和图4两种状态,并解决了undefined的问题
break //退出
else{ //到图3的状态,因为之前先判断了一次,所以先变换位置
nhead=pre
pre=pre.next
cur=pre.next
}
nhead.next=cur //和上面第一轮一样,此次把前面的【2,1】节点接住
pre.next=cur.next
cur.next=pre
}
return head
};
/*
//随想录的简洁版,思路差不多,他解决了我的返回head的问题,他在while内部定义pre,他的temp相当于我的uhead
var swapPairs = function (head) {
let ret = new ListNode(0, head), temp = ret;
while (temp.next && temp.next.next) {
let cur = temp.next.next, pre = temp.next;
pre.next = cur.next;
cur.next = pre;
temp.next = cur;
temp = pre;
}
return ret.next;
};
*/
第一想法
不能变节点的val,就只能变节点的next了
思路
结合此图和注释
困难
- 无返回值
在while外做一轮,记录head
- 最后只有[4,3]——虚拟头节点的作用
图三,nhead.next=cur,把前面一轮的成果接住了
此类问题终于懂了~,如图一,4后面是有一个null的,所以可以用于head.next===null判断之类的,但比如我把pre赋值到了最后一个null节点,null节点就没有val也没有next节点了,所以null或undefined
if(pre.next=== null || pre.next.next = ==null) 这个判断,节点4后面是null或者4的后面的后面是null
收获
- 对链表的理解
链表是一个一个节点构成的
谈谈理解,例如
let cur=head.next; //next指向的也是一个节点,也可以理解为next就是一个节点,不过是我家后面的家,cur指向head的节点,cur是这个val=2节点的别名,这个节点可以有很多名字,但我可以调用他的val和next,但并不是新造一个节点
let nhead=new ListNode(0,head) //新造一个节点,val是0,next是head
nhead.next=cur //nhead这个家带地皮一整个搬到cur前面去了,节点还是那个节点,那个节点还是叫nhead,不过搬家了
nhead=pre,pre代表的节点又有了一个名字nhead,两者就是一个节点
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
//快慢节点,就可以之遍历一次
let f=head;
let m=new ListNode(-1,head)
for(let i=1;i<=n;i++) //2次
f=f.next
while(f){
f=f.next;
m=m.next
}
if(m.val===-1)
return m.next.next
m.next=m.next.next;
return head
};
第一想法
快慢指针
思路
如图
困难
- 开始把m.val设置为0,结果有正常val的也是0
设为-1
- while和for的边界
画一遍图理解思路和加一个虚拟节点就很容易解决
- head =[1],n =1的例子
因为只是m.next=m.next.next;,没有吧原先的m.next=null消除.
if(m.val===-1)
return m.next.next//我的(m)是可以动的,没有一个可以直接
或者学代码随想录专门设置一个数来记录虚拟头结点
收获
- 我的(m)是可以动的,以后专门设置一个数来记录虚拟头结点
var getListLen = function(head) {
let len = 0, cur = head;
while(cur) {
len++;
cur = cur.next;
}
return len;
}
var getIntersectionNode = function(headA, headB) {
let curA = headA,curB = headB,
lenA = getListLen(headA),
lenB = getListLen(headB);
if(lenA < lenB) {
// 下面交换变量注意加 “分号” ,两个数组交换变量在同一个作用域下时
// 如果不加分号,下面两条代码等同于一条代码: [curA, curB] = [lenB, lenA]
[curA, curB] = [curB, curA];
[lenA, lenB] = [lenB, lenA];
}
let i = lenA - lenB;
while(i-- > 0) {
curA = curA.next;
}
while(curA && curA !== curB) {
curA = curA.next;
curB = curB.next;
}
return curA;
};
//双指针
var getIntersectionNode = function(headA, headB) {
let A = headA
let B = headB
while(A !== B){
A = A !== null ? A.next : headB
B = B !== null ? B.next : headA
}
return A
};
第一想法
看不懂题,直接看代码
思想
普通:看代码
双指针:
最后一定重合
收获
- 交换
let a = 123,
b = 456;
[a,b] = [b,a];
console.log(a, b);
[curA, curB] = [curB, curA];
[lenA, lenB] = [lenB, lenA];
// 两种循环实现方式
/**
* @param {ListNode} head
* @return {ListNode}
*/
// 先判断是否是环形链表
var detectCycle = function(head) {
if(!head || !head.next) return null;
let slow =head.next, fast = head.next.next;
while(fast && fast.next && fast!== slow) {
slow = slow.next;
fast = fast.next.next;
}
if(!fast || !fast.next ) return null;
slow = head;
while (fast !== slow) {
slow = slow.next;
fast = fast.next;
}
return slow;
};
var detectCycle = function(head) {
if(!head || !head.next) return null;
let slow =head.next, fast = head.next.next;
while(fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
if(fast == slow) {
slow = head;
while (fast !== slow) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
return null;
};
第一想法
for+while,暴力
困难
- 1.理解为什么一定会相遇
相对,fast相对slow走一步
- x怎么找到
x = (n - 1) (y + z) + z,具体看代码随想录文档
收获
Floyd判圈算法(龟兔赛跑算法)