基本方法
1.防抖
function debounce(fn, delay) {
let timer = null;
return function () {
const that = this;
const arg = arguments;
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(that, arg);
}, delay)
}
}
2.节流
const trottle = (fn, delay) => {
let timer = null;
return function () {
const that = this;
const arg = arguments;
if (!timer) {
timer = setTimeout(() => {
fn.apply(that, arg);
timer = null;
},delay)
}
}
}
3.call
Function.prototype.customCall = function(thisArg, ...arguments) {
thisArg = thisArg ? Object(thisArg) : window;
let fn = this;
thisArg.fn = fn;
const res = thisArg.fn(...arguments);
delete thisArg.fn;
return res;
}
4.apply
Function.prototype.customApply = function(thisArg, arguments) {
thisArg = thisArg ? Object(thisArg) : window;
let fn = this;
thisArg.fn = fn;
const res = arguments ? thisArg.fn(...arguments) : thisArg.fn();
delete thisArg.fn;
return res;
}
5.bind
Function.prototype.customBind = function(thisArg, ...args) {
thisArg = thisArg ? Object(thisArg) : window;
let fn = this;
return function(...otherArgs) {
thisArg.fn = fn;
const res = thisArg.fn(...args, ...otherArgs);
delete thisArg.fn;
return res;
}
}
a.customBind(this, ...args)(...otherArgs);
6.instanceof
function customInstanceof(s1, s2) {
let s1_proto = Object.getPrototypeOf(s1);
let s2_proto = s2.prototype;
while(true) {
if (!s1_proto) return false;
if (s1_proto === s2_proto) {
return true;
}
s1_proto = Object.getPrototypeOf(s1_proto)
}
}
7.promise
class customPromise {
constructor(excutor) {
this.state = 'pending';
this.value = null;
this.reason = null;
let resolve = (value) => {
if (this.state === 'pending') {
this.pending = 'fulfilled';
this.value = value;
}
}
let reject = (reason) => {
if (this.state === 'pending') {
this.pending = 'rejected';
this.reason = reason;
}
}
try {
excutor(resolve, reject)
} catch (error) {
reject(error);
}
}
}
8.promise.all
Promise.all = function(arr) {
let result = [];
let count = 0;
return new Promise((resolve, reject) => {
for(let i = 0; i < arr.length; i++) {
arr[i].then((res) => {
result[i] = res;
count++;
if(count === arr.length) {
resolve(result);
}
}, reject)
}
})
}
9.promise.race
Promise.race = function(arr) {
return new Promise((resolve, reject) => {
for(let i = 0; i < arr.length; i++) {
arr[i].then(resolve, reject);
}
})
}
Promise.race([p1,p2,p3]).then((res) => {
console.log('res', res);
}).catch((error) => {
console.log('error', error);
})
10.promise异步加载图片
function loadImg(url) {
return new Promise((resolve, reject) => {
const img = new Image()
img.url = url
img.onload = () => {
resolve(img)
}
img.onerror = () => {
reject(`图片加载失败-${url}`)
}
})
}
loadImg('xxx.png')
.then((res) => {
console.log(res)
})
.catch((error) => {
console.log(error)
})
11.Object.create
function(obj){
if (typeof obj !== "object" && typeof obj !== "function") {
throw new TypeError("Object prototype may only be an Object or null.");
}
function F(){}
F.prototype = obj
return new F()
}
12.手写一个new
function myNew(Con, ...arg) {
let obj = Object.create(Con.prototype)
let result = Con.apply(obj, arg)
return typeof result === 'object' ? result : obj
}
13.函数柯里化
const myCurried = (fn, ...args) => {
if (args.length < fn.length) {
return (..._args) => myCurried(fn, ...args, ..._args)
} else {
return fn(...args)
}
}
function add(a, b, c) {
return a + b + c
}
const curriedAdd = myCurried(add)
console.log(curriedAdd(1)(2)(3))
console.log(curriedAdd(1, 2)(3))
console.log(curriedAdd(1)(2, 3))
14.params参数
export default class {
static setUrlParams(url, param, value) {
let result;
let cleanUrl = this.removeParams(param, url);
cleanUrl = cleanUrl[cleanUrl.length - 1] === '?' ? cleanUrl.replace('?', '') : cleanUrl;
if (cleanUrl.indexOf('?') !== -1) {
const p = new RegExp('(\\?|&" + param + ")=[^&]*');
if (p.test(cleanUrl)) {
result = cleanUrl.replace(p, `$1=${value}`);
} else {
result = `${cleanUrl}&${param}=${value}`;
}
} else {
result = `${cleanUrl}?${param}=${value}`;
}
return result;
}
static getParams(keyName, url) {
const urlStr = url || window.location.href;
const name = keyName.replace(/[\[\]]/g, '\\$&');
const regex = new RegExp('[?&]'.concat(name, '(=([^&#]*)|&|#|$)'));
const results = regex.exec(urlStr);
if (!results) {
return undefined;
}
if (!results[2]) {
return undefined;
}
const res = decodeURIComponent(results[2].replace(/\+/g, ' '));
if (res === 'false') {
return false;
}
if (res === 'undefined') {
return undefined;
}
if (res === 'null') {
return null;
}
if (res === 'true') {
return true;
}
return res;
}
static removeParams(keyName, urlStr) {
const name = keyName.replace(/[\]]/g, '\\$&');
const regex = new RegExp(`[?&]${name}(=([^&#]*(&|#|$))|&|#|$)`);
return urlStr.replace(regex, (item) => {
if (/^\?/.test(item)) {
return '?';
} if (/^&.+&$/.test(item)) {
return '&';
} if (/#$/.test(item)) {
return '#';
}
return '';
});
}
}
15.浅拷贝
16.深拷贝
const clone = (originObj) => {
const obj = originObj;
if(obj === null || typeof obj !== 'object') {
return obj;
}
if ('isActive' in obj) {
throw new Error('循环引用警告')
}
let temp;
if (obj instanceof Date) {
temp = new obj.constructor(obj);
} else {
temp = obj.constructor();
}
Object.keys(obj).forEach((key) => {
obj.isActive = null;
temp[key] = clone(obj[key])
delete obj.isActive;
})
return temp;
};
17.深度比较
function isEqual(obj1, obj2) {
if (typeof obj1 !== 'object' || typeof obj2 !== 'object') {
return obj1 === obj2
}
if (obj2 === obj1) return true
let keys1 = Object.keys(obj1)
let keys2 = Object.keys(obj2)
if (keys1.length !== keys2.length) return false
for (let k of keys1) {
let res = isEqual(obj1[k], obj2[k])
if (!res) return false
}
return true
}
18.实现一个定时器
const countTimer = useRef<NodeJs.Timeout>(null);
const [time, setTime] = useState('00:00:00');
const setTimeFlash = (diffTime: any) => {
let s = Math.floor((diffTime / 1000) % 60);
let m = Math.floor((diffTime / 1000 / 60) % 60);
let h = Math.floor((diffTime / 1000 / 60 / 60) % 24);
let arr = [h,m,s].map((item: number) => {
if (item < 10) {
item = `0${item}`
}
return item;
})
return {
hour: arr[0],
minute: arr[1],
second: arr[2],
};
}
const startCountdown = (endTime: any) => {
let diffTime = new Date(endTime).getTime() - new Date().getTime()
if (diffTime > 0) {
countTimer.current = setInterval(() => {
diffTime-=1000;
if (diffTime <= 0) {
clearInterval(countTimer)
}
setTime(setTimeFlash(diffTime));
}, 1000)
}
}
useEffect(() => {
startCountdown('19:00:00');
return () => {
clearInterval(countTimer);
}
}, [])
19.使用setTimeout实现setInterval
function mySetinterval(callback, interval) {
let timeoutId = null
function repeat() {
callback()
timeoutId = setTimeout(repeat, interval)
}
repeat()
return {
cancel: () => clearTimeout(timeoutId),
}
}
20.实现JSONP
function jsonp(url, callbackName, success) {
const script = document.createElement('script')
script.src = `${url}?callback=${callbackName}`
document.body.appendChild(script)
window['callbackName'] = (response) => {
success(response)
document.body.removeChild(script)
}
}
jsonp(url, 'handleResponse', (response) => console.log(response))
handleResponse({
name: '树哥',
age: 18,
})
21.实现ajax
function get() {
let req = new XMLHTTPRequest()
if (req) {
req.open('GET', 'http://test.com/?keywords=手机', true)
req.onreadystatechange = function () {
if (req.readystate === 4) {
if (req.statue === 200) {
console.log('success')
} else {
console.log('error')
}
}
}
req.send()
}
}
22.使用promise封装ajax
function get() {
return new Promise((resolve, reject) => {
let req = new XMLHTTPRequest()
if (req) {
req.open('GET', 'http://test.com/?keywords=手机', true)
req.onreadystatechange = function () {
if (req.readystate === 4) {
if (req.statue === 200) {
reslove('success')
} else {
reject('error')
}
}
}
req.send()
}
})
}
23.数组扁平化
function _flat(arr, depth) {
if (!Array.isArray(arr) || depth <= 0) {
return arr
}
return arr.reduce((prev, cur) => {
if (Array.isArray(cur)) {
return prev.concat(_flat(cur, depth - 1))
} else {
return prev.concat(cur)
}
}, [])
}
24.实现数组的push,map,filter
Array.prototype.myPush = function (...args) {
const length = this.length
for (let i = 0; i < args.length; i++) {
this[this.length + i] = args[i]
}
return this.length
}
Array.prototype.myFilter = function (callback) {
const newArr = []
for (let i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) {
newArr.push(this[i])
}
}
return newArr
}
Array.prototype.myMap = function (callback) {
const newArr = []
for (let i = 0; i < this.length; i++) {
newArr.push(callback(this[i], i, this))
}
return newArr
}
const list = [1, 2, 3, 4, 5]
console.log(list.myPush(6))
console.log(list.myFilter((i) => i > 3))
console.log(list.myMap((i) => i + 1))
25.图片懒加载SDK
function lazyload() {
let viewHeight = document.body.clientHeight
let imgs = document.querySelectorAll('img[data-src]')
imgs.forEach((item, index) => {
if (item.dataset.src === '') return
let rect = item.getBoundingClientRect()
if (rect.bottom >= 0 && rect.top < viewHeight) {
item.src = item.dataset.src
item.removeAttribute('data-src')
}
})
}
window.addEventListener('scroll', lazyload)
26.实现单例模式
let cache
class A {
}
function getInstance() {
if (cache) return cache
return (cache = new A())
}
const x = getInstance()
const y = getInstance()
console.log(x === y)
27.观察者模式
class Subject {
constructor() {
this.observers = []
}
addObserver(observer) {
this.observers.push(observer)
}
removeObserver(observer) {
this.observers = this.observers.filter((item) => item !== observer)
}
notify() {
this.observers.forEach((observer) => observer.update())
}
}
class Observer {
constructor(data) {
this.data = data
}
update() {
console.log('data:', this.data)
}
}
const subject = new Subject()
const observer1 = new Observer('Hello啊,树哥!')
const observer2 = new Observer('Hello')
subject.addObserver(observer1)
subject.addObserver(observer2)
subject.notify()
28.发布订阅模式
class EventEmitter {
constructor() {
this.events = {}
}
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = []
}
this.events[eventName].push(callback)
}
emit(eventName, ...args) {
const callbacks = this.events[eventName] || []
callbacks.forEach((cb) => cb.apply(this, args))
}
off(eventName, callback) {
const callbacks = this.events[eventName] || []
const index = callbacks.indexOf(callback)
if (index !== -1) {
callbacks.splice(index, 1)
}
}
once(eventName, callback) {
const wrapper = (...args) => {
callback.apply(this, args)
this.off(eventName, wrapper)
}
this.on(eventName, wrapper)
}
}
const emitter = new EventEmitter()
emitter.on('event1', function (data) {
console.log(`event1 is triggered with data: ${data}`)
})
emitter.on('event2', function () {
console.log('event2 is triggered')
})
emitter.emit('event1', 'hello world')
emitter.off('event1')
emitter.emit('event1', 'foo bar')
emitter.emit('event2')
const emitter = new EventEmitter()
emitter.once('event1', function (data) {
console.log(`event1 is triggered with data: ${data}`)
})
emitter.emit('event1', 'hello world')
emitter.emit('event1', 'foo bar')
29.koa洋葱模型
function compose(middleware) {
if(!Array.isArray(middleware)) return Promise.reject(new Error(''))
for (const fun of middleware) {
if(typeof fun !== 'function') {
return Promise.reject(new Error(''))
}
}
return function(ctx, next) {
let i = -1;
return dispatch(0)
function dispatch(index) {
if(index < i) return Promise.reject()
i = index;
let fn = middleware[index];
if(index === middleware.length) fn = next;
if(!fn) return Promise.resolve();
try {
return Promise.resolve(fn(ctx, dispatch.bind(null, index+1)));
} catch (error) {
return Promise.reject(error);
}
};
}
}
30.设置请求字段
const http = require('http')
const server = http.createServer((req, res) => {
if(req.url = '/') {
res.writeHead('200', { 'cache-control': 'max-age=10'
res.setHeader('cache-control', 'max-age=10')
res.cookie('user', 'aa');
res.end()
}
})
server.listen(8080, () => {})
Object.defineProperty和proxy
Object.defineProperty(obj, "name", {
enumerable: true,
configurable: true,
get: function () {
console.log("获取,收集依赖");
return demoBute
},
set: function (value) {
console.log("更新,通知用户");
demoBute = value;
}
})
const handler = {
get(target, property, receiver) {
console.log(`正在读取属性:${property}`);
return target[property];
},
set(target, property, value, receiver) {
console.log(`正在设置属性:${property},新值为:${value}`);
target[property] = value;
return true;
}
};
const proxy = new Proxy(obj, handler);
排序
1.冒泡排序
function sort1(arr) {
let len = arr.length;
for(let i=0; i < len; i++) {
for(let j=0; j < len-1-i; j++) {
if (arr[j] > arr[j+1]) {
let temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
2.插入排序
function arr3(arr) {
for(let i=1; i< arr.length; i++) {
let j = i-1;
let current = arr[i];
while(j > -1 && arr[j] > current) {
arr[j+1] = arr[j];
j--
}
arr[j+1] = current;
}
return arr;
}
3.选择排序
function sort2(arr) {
let minIndex = 0;
for(let i=0; i<arr.length; i++) {
minIndex = i;
for(let j=i+1; j< arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (i !== minIndex) {
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
}
}
return arr;
}
4.堆排序
function swap(arr, n, m) {
let temp = arr[n];
arr[n] = arr[m];
arr[m] = temp;
}
function buildHeap(arr) {
let len = arr.length;
let start = Math.floor(len/2) - 1;
for(let i = start; i >=0; i--) {
heapify(arr, i, len)
}
}
function heapify(arr, i, len) {
let cur = i;
let left = 2*i + 1;
let right = 2*i + 2;
if (left < len && arr[cur] < arr[left]) {
cur = left;
}
if (right < len && arr[cur] < arr[right]) {
cur = right;
}
if (cur !== i) {
swap(arr, cur, i);
heapify(arr, cur, len);
}
}
function sortHeap(arr) {
buildHeap(arr);
for(let s = arr.length - 1; s > 0; s--) {
swap(arr, 0, s);
heapify(arr, 0, s);
}
return arr;
}
console.log(sortHeap([9, 3, 5, 1, 6, 8, 4]))
算法
1.最长回文子串
var longestPalindrome = function(s) {
if (s.length < 2) return s;
let res = '';
for(let i=0; i < s.length - 1; i++) {
palindrome(i, i+1)
palindrome(i, i)
}
function palindrome(m, n) {
while(m >=0 && n < s.length && s[n] === s[m]) {
n++;
m--;
}
if ((n-m-1) > res.length) {
res = s.slice(m + 1, n +1 -1);
}
}
return res;
}
2.括号生成
var generateParenthesis = function(n) {
const res = [];
const generate = (str, left, right) => {
if (str.length == 2 * n) {
res.push(str);
return;
}
if (left > 0) {
generate(str + '(', left - 1, right);
}
if (right > left) {
generate(str + ')', left, right - 1);
}
};
generate('', n, n);
return res;
};
3.组合总和
var combinationSum = function(candidates, target) {
const ans = [];
const dfs = (target, combine, idx) => {
if (idx === candidates.length) {
return;
}
if (target === 0) {
ans.push(combine);
return;
}
dfs(target, combine, idx + 1);
if (target - candidates[idx] >= 0) {
dfs(target - candidates[idx], [...combine, candidates[idx]], idx);
}
}
dfs(target, [], 0);
return ans;
};
4.全排列
var permute = function(nums) {
const res = [], path = [];
backtracking(nums, nums.length, []);
return res;
function backtracking(n, k, used) {
if(path.length === k) {
res.push(Array.from(path));
return;
}
for (let i = 0; i < k; i++ ) {
if(used[i]) continue;
path.push(n[i]);
used[i] = true;
backtracking(n, k, used);
path.pop();
used[i] = false;
}
}
};
5.下一个排列
var nextPermutation = function(nums) {
let i = nums.length - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) {
i--;
}
if (i >= 0) {
let j = nums.length - 1;
while (j >= 0 && nums[j] <= nums[i]) {
j--;
}
[nums[i], nums[j]] = [nums[j], nums[i]];
}
let l = i + 1;
let r = nums.length - 1;
while (l < r) {
[nums[l], nums[r]] = [nums[r], nums[l]];
l++;
r--;
}
};
6.两数相除
const MAX = 2147483647, MIN = -2147483648;
var divide = function(dividend, divisor) {
if(dividend == MIN && divisor == -1)
return MAX;
let a = Math.abs(dividend), b = Math.abs(divisor), res = 0;
for(let i=31;i>=0;i--){
if((a>>>i)>=b){
if(i==31){
a -= MAX;
a -= 1;
res -= MIN;
} else{
a -= b<<i;
res += 1<<i;
}
}
}
return (dividend > 0) == (divisor > 0) ? res : -res;
};
7.盛最多水的容器
var maxArea = function(height) {
let maxRes = 0;
let i = 0, j = height.length - 1;
while(i < j) {
const max = Math.min(height[i], height[j]) * (j - i)
maxRes = maxRes > max ? maxRes : max;
if(height[i] <= height[j]) {
i++;
} else {
j--;
}
}
return maxRes;
};
8.三数之和
var threeSum = function(nums) {
if (nums.length < 3) return [];
let res = [];
nums.sort((a, b) => a - b);
for(let i=0; i < nums.length - 2; i++) {
if (nums[i] > 0) return res;
if (i > 0 && nums[i] === nums[i-1]) continue;
let j = i+1;
let k = nums.length - 1;
while(j < k) {
if (nums[i] + nums[j] + nums[k] === 0) {
res.push([nums[i], nums[j], nums[k]]);
while(j < k && nums[j] === nums[j+1]) j++;
while(j < k && nums[k] === nums[k-1]) k--;
j++;
k--;
}
if (nums[i] + nums[j] + nums[k] > 0) {
k--;
}
if (nums[i] + nums[j] + nums[k] < 0) {
j++;
}
}
}
return res;
};
链表
1.环形链表
var hasCycle = function(head) {
let map = new Map();
while(head) {
if(map.has(head)) return true;
map.set(head, true)
head = head.next;
}
return false
};
2.删除链表中的倒数第n个节点
var removeNthFromEnd = function(head, n) {
let slow = head, fast = head;
while(n--) {
fast = fast.next;
}
if(!fast) {
return head.next;
}
while(fast.next) {
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return head;
};
3.合并两个有序链表
var mergeTwoLists = function(list1, list2) {
let resHead = new ListNode(-1);
let prev = resHead;
while(list1 !== null && list2 !== null) {
if(list1.val <= list2.val) {
prev.next = list1;
list1 = list1.next
} else {
prev.next = list2;
list2 = list2.next;
}
prev = prev.next;
}
prev.next = list1 === null ? list2 : list1;
return resHead.next
};
4.两两交换链表中的节点
var swapPairs = function(head) {
const dummyHead = new ListNode(0);
dummyHead.next = head;
let temp = dummyHead;
while (temp.next !== null && temp.next.next !== null) {
const node1 = temp.next;
const node2 = temp.next.next;
temp.next = node2;
node1.next = node2.next;
node2.next = node1;
temp = node1;
}
return dummyHead.next;
};
5.K个一组翻转链表
const myReverse = (head, tail) => {
let prev = tail.next;
let p = head;
while (prev !== tail) {
const nex = p.next;
p.next = prev;
prev = p;
p = nex;
}
return [tail, head];
}
var reverseKGroup = function(head, k) {
const hair = new ListNode(0);
hair.next = head;
let pre = hair;
while (head) {
let tail = pre;
for (let i = 0; i < k; ++i) {
tail = tail.next;
if (!tail) {
return hair.next;
}
}
const nex = tail.next;
[head, tail] = myReverse(head, tail);
pre.next = head;
tail.next = nex;
pre = tail;
head = tail.next;
}
return hair.next;
};
6.删除排序链表中的重复元素
var deleteDuplicates = function(head) {
if (!head) {
return head;
}
const dummy = new ListNode(0, head);
let cur = dummy;
while (cur.next && cur.next.next) {
if (cur.next.val === cur.next.next.val) {
const x = cur.next.val;
while (cur.next && cur.next.val === x) {
cur.next = cur.next.next;
}
} else {
cur = cur.next;
}
}
return dummy.next;
};
7.旋转链表
var rotateRight = function(head, k) {
if (k === 0 || !head || !head.next) {
return head;
}
let n = 1;
let cur = head;
while (cur.next) {
cur = cur.next;
n++;
}
let add = n - k % n;
if (add === n) {
return head;
}
cur.next = head;
while (add) {
cur = cur.next;
add--;
}
const ret = cur.next;
cur.next = null;
return ret;
};
8.反转链表
var reverseList = function(head) {
let prev = null;
let curr = head;
while (curr) {
const next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
};
9.两数相加
var addTwoNumbers = function(l1, l2) {
let head = null, tail = null;
let carry = 0;
while (l1 || l2) {
const n1 = l1 ? l1.val : 0;
const n2 = l2 ? l2.val : 0;
const sum = n1 + n2 + carry;
if (!head) {
head = tail = new ListNode(sum % 10);
} else {
tail.next = new ListNode(sum % 10);
tail = tail.next;
}
carry = Math.floor(sum / 10);
if (l1) {
l1 = l1.next;
}
if (l2) {
l2 = l2.next;
}
}
if (carry > 0) {
tail.next = new ListNode(carry);
}
return head;
};
树
二叉树的中序遍历
var inorderTraversal = function(root) {
const res = [];
const inorder = (root) => {
if (!root) {
return;
}
inorder(root.left);
res.push(root.val);
inorder(root.right);
}
inorder(root);
return res;
};
二叉树的层序遍历
var levelOrder = function(root) {
const ret = [];
if (!root) {
return ret;
}
const q = [];
q.push(root);
while (q.length !== 0) {
const currentLevelSize = q.length;
ret.push([]);
for (let i = 1; i <= currentLevelSize; ++i) {
const node = q.shift();
ret[ret.length - 1].push(node.val);
if (node.left) q.push(node.left);
if (node.right) q.push(node.right);
}
}
return ret;
};
不同的二叉搜索树
var numTrees = function(n) {
var numTrees = function(n) {
const G = new Array(n + 1).fill(0);
G[0] = 1;
G[1] = 1;
for (let i = 2; i <= n; ++i) {
for (let j = 1; j <= i; ++j) {
G[i] += G[j - 1] * G[i - j];
}
}
return G[n];
};
};
验证二叉搜索树
const helper = (root, lower, upper) => {
if (root === null) {
return true;
}
if (root.val <= lower || root.val >= upper) {
return false;
}
return helper(root.left, lower, root.val) && helper(root.right, root.val, upper);
}
var isValidBST = function(root) {
return helper(root, -Infinity, Infinity);
};
恢复二叉搜索树
const swap = (x, y) => {
const temp = x.val;
x.val = y.val;
y.val = temp;
}
var recoverTree = function(root) {
const stack = [];
let x = null, y = null, pred = null;
while (stack.length || root !== null) {
while (root !== null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
if (pred !== null && root.val < pred.val) {
y = root;
if (x === null) {
x = pred;
}
else break;
}
pred = root;
root = root.right;
}
swap(x, y);
};
二叉树展开为链表
var flatten = function(root) {
const list = [];
preorderTraversal(root, list);
const size = list.length;
for (let i = 1; i < size; i++) {
const prev = list[i - 1], curr = list[i];
prev.left = null;
prev.right = curr;
}
};
const preorderTraversal = (root, list) => {
if (root != null) {
list.push(root);
preorderTraversal(root.left, list);
preorderTraversal(root.right, list);
}
}