前言
找到了個不錯的提綱,做了些反轉鏈表的題目
反轉鏈表
循環和遞歸,以下三段分別爲定義,循環,遞歸 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;
}