前言
找到了个不错的提纲,做了些反转链表的题目
反转链表
循环和递归,以下三段分别为定义,循环,递归 1,递归 2
function ListBode(val) {
this.val = val;
this.next = null;
}
function reverseList = head => {
if(!head) return head
let cur = head, pre = null
while(cur) {
let next = cur.next;
cur.next = pre
pre = cur
cur = next
}
return pre
}
function reverseList = head => {
if(!head || !head.next) return head
let res = reverseList(head.next)
head.next.next = head
head.next = null
return res
}
function reverseList = head => {
if(!head) return head
let help = (cur, pre) => {
if(!cur) return pre
let next = cur.next
cur.next = pre
return help(next, cur)
}
return help(head)
}
区间反转
同样分别使用循环和递归:
function PartReverseList = (head, m, n) => {
let count = n-m;
let p = dummy = new ListNode()
let start, tail, cur, pre;
p.next = head
for(i = 0; i< m-1; i++) {
p = p.next
}
start = p;
pre = tail = p.next;
cur = pre.next;
while(count){
let next = cur.next;
cur.next = pre
pre = cur
cur = next
count--
}
start.next = pre
tail.next = cur
return dummy.next
}
function PartReverseList = (head, m, n) => {
let help = (cur, pre) => {
if(!cur) return pre
let next = cur.next
cur.next = pre
return help(next, cur)
}
let p = dummy = new ListNode()
p.next = head
let start, end, front, tail;
for(i = 0; i<m-1; i++) {
p = p.next
}
front = p
start = p.next
for(i = m-1; i<n;i++) {
p = p.next
}
end = p
tail = p.next
end.next = null
front.next = help(start)
start.next = tail
return dummy.next
}
两两交换链表中的节点
同样使用循环和递归两种方式来做
function TwoChange(head) {
if (!head||!head.next) return head
let dummy = p = new ListNode()
p.next = head
while(p.next&&p.next.next) {
let node1 = p.next, node2 = p.next.next
node1.next = node2.next
node2.next = node1
p.next = node2
p = node1
}
return dummy.next
}
function TwoChange(head) {
if (!head||!head.next) return head
let node1 = head, node2 = head.next
node1.next = TwoChange(node2.next)
node2.next = node1
return node2
}
环形链表
使用集合 || 使用双指针
function circle(head) {
let dic = new Set();
while (head) {
if (dic.has(head)) return true;
dic.add(head);
head = head.next;
}
return false;
}
function circle(head) {
let fast = head,
slow = head;
while (fast && fast.next && fast.next.next) {
fast = fast.next.next;
slow = slow.next;
if (fast === slow) {
return true;
}
}
return false;
}
链表合并
同样有两种方式,循环和递归,由于递归较为简单,所以放在前面
function merge(l1, l2) {
if (!l1) return l2;
if (!l2) return l1;
if (l1.val > l2.val) {
l2.next = merge(l1, l2.next);
return l2;
} else {
l1.next = merge(l2, l1.next);
return l1;
}
}
function merge(l1, l2) {
if (!l1) return l2;
if (!l2) return l1;
let p = (dummy = new ListNode());
while (l1 && l2) {
if (l1.val > l2.val) {
p.next = l2;
p = p.next;
l2 = l2.next;
} else {
p.next = l1;
p = p.next;
l1 = l1.next;
}
}
if (l1) p.next = l1;
else p.next = l2;
return dummy.next;
}
回文链表
分别使用数组和找链表中点并反转的方式来实现
function isPalindrome(head) {
let res = [];
while (head) {
res.push(head.val);
head = head.next;
}
let str1 = res.join(""),
str2 = res.reverse().join("");
return str1 === str2;
}
function isPalindrome(head) {
let reverse = (cur, pre) => {
if (!cur) return pre;
let next = cur.next;
cur.next = pre;
return reverse(next, cur);
};
let dummy = (slow = fast = new ListNode());
dummy.next = head;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
let next = slow.next;
slow.next = null;
let newStart = reverse(next);
for (let p = head, newP = newStart; newP; p = p.next, newP = newP.next) {
if (p.val != newP.val) {
return false;
}
}
return true;
}