给定一个单链表的头结点pHead,长度为n,反转该链表后,返回新链表的表头。
方法1:转换数据结构-使用数组栈
链表用next连接,反转起来比较麻烦,但是数组就不一样了,比较简单,其中栈先进后出,正好把顺序给反转了,所以我们就使用数组构造栈来解决。
function ListNode(x){
this.val = x;
this.next = null;
}
function ReverseList(pHead)
{
if(!pHead) return pHead;
let stack = [];
let cur = pHead;
let newHead = new ListNode(-1);
let node = newHead;
while(cur) {
stack.push(cur.val);
cur = cur.next;
}
while(stack.length) {
const top = stack.pop();
node.next = new ListNode(top);
node = node.next;
}
return newHead.next;
}
方法2: 使用循环
比如链表123,以第一个节点12举例,如果反转,需要把2指向1,但是2本来是指向3的,所以我们不能直接改变1指向2,而是先把3存储起来,再把2指向1, 循环每个节点做这样的操作。
function ReverseList(pHead){
if(!pHead || !pHead.next) return pHead;
let pre = null
let cur = pHead;
while(cur) {
const oldNext = cur.next;
cur.next = pre;
pre = cur;
cur = oldNext;
}
return pre;
}
方法3:使用递归
思考递归的时,要试着找出最小问题的解决方式,再推到大问题,而不是尝试一层层的去执行进去。
既然是递归,参数就只有一个,代表某个节点。比如链表123,选取最小问题,反转12来看待,假设1是head, 2就是head.next,把2指向1,就是把head.next的next指向head,代码就是 head.next.next = head;
function ReverseList(head) {
// head是4的时,这里就直接return了
if(head === null || head.next === null) {
return head;
}
/*
按例子执行,最后一次递归执行完head是3,从后往前,依次是2 1
*/
const newHead = reverseList(head.next);
head.next.next = head; // 执行反转的逻辑
head.next = null; // 反转最后一个节点head是1的时,我们上次把2指向了1,但是1还是执向2呢,所以把这个指向给删除掉。
return newHead;
}