提交 1b5dc5f8 编写于 作者: L luzhipeng

feat: 部分文件增加内容

上级 8bdef010
/*
* @lc app=leetcode id=152 lang=javascript
*
* [152] Maximum Product Subarray
*
* https://leetcode.com/problems/maximum-product-subarray/description/
*
* algorithms
* Medium (28.61%)
* Total Accepted: 202.8K
* Total Submissions: 700K
* Testcase Example: '[2,3,-2,4]'
*
* Given an integer array nums, find the contiguous subarray within an array
* (containing at least one number) which has the largest product.
*
* Example 1:
*
*
* Input: [2,3,-2,4]
* Output: 6
* Explanation: [2,3] has the largest product 6.
*
*
* Example 2:
*
*
* Input: [-2,0,-1]
* Output: 0
* Explanation: The result cannot be 2, because [-2,-1] is not a subarray.
*
*/
/**
* @param {number[]} nums
* @return {number}
*/
var maxProduct = function(nums) {
// let max = nums[0];
// let temp = null;
// for(let i = 0; i < nums.length; i++) {
// temp = nums[i];
// max = Math.max(temp, max);
// for(let j = i + 1; j < nums.length; j++) {
// temp *= nums[j];
// max = Math.max(temp, max);
// }
// }
// return max;
let max = nums[0];
let min = nums[0];
let res = nums[0];
for (let i = 1; i < nums.length; i++) {
let tmp = min;
min = Math.min(nums[i], Math.min(max * nums[i], min * nums[i])); // 取最小
max = Math.max(nums[i], Math.max(max * nums[i], tmp * nums[i])); /// 取最大
res = Math.max(res, max);
}
return res;
};
/*
* @lc app=leetcode id=189 lang=javascript
*
* [189] Rotate Array
*
* https://leetcode.com/problems/rotate-array/description/
*
* algorithms
* Easy (29.07%)
* Total Accepted: 287.3K
* Total Submissions: 966.9K
* Testcase Example: '[1,2,3,4,5,6,7]\n3'
*
* Given an array, rotate the array to the right by k steps, where k is
* non-negative.
*
* Example 1:
*
*
* Input: [1,2,3,4,5,6,7] and k = 3
* Output: [5,6,7,1,2,3,4]
* Explanation:
* rotate 1 steps to the right: [7,1,2,3,4,5,6]
* rotate 2 steps to the right: [6,7,1,2,3,4,5]
* rotate 3 steps to the right: [5,6,7,1,2,3,4]
*
*
* Example 2:
*
*
* Input: [-1,-100,3,99] and k = 2
* Output: [3,99,-1,-100]
* Explanation:
* rotate 1 steps to the right: [99,-1,-100,3]
* rotate 2 steps to the right: [3,99,-1,-100]
*
*
* Note:
*
*
* Try to come up as many solutions as you can, there are at least 3 different
* ways to solve this problem.
* Could you do it in-place with O(1) extra space?
*
*/
/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums, k) {
// 就像扩容一样操作
k = k % nums.length;
const n = nums.length;
for (let i = nums.length - 1; i >= 0; i--) {
nums[i + k] = nums[i];
}
for (let i = 0; i < k; i++) {
nums[i] = nums[n + i];
}
nums.length = n;
};
/*
* @lc app=leetcode id=217 lang=javascript
*
* [217] Contains Duplicate
*
* https://leetcode.com/problems/contains-duplicate/description/
*
* algorithms
* Easy (50.92%)
* Total Accepted: 324K
* Total Submissions: 628.5K
* Testcase Example: '[1,2,3,1]'
*
* Given an array of integers, find if the array contains any duplicates.
*
* Your function should return true if any value appears at least twice in the
* array, and it should return false if every element is distinct.
*
* Example 1:
*
*
* Input: [1,2,3,1]
* Output: true
*
* Example 2:
*
*
* Input: [1,2,3,4]
* Output: false
*
* Example 3:
*
*
* Input: [1,1,1,3,3,4,3,2,4,2]
* Output: true
*
*/
/**
* @param {number[]} nums
* @return {boolean}
*/
var containsDuplicate = function(nums) {
// 1. 暴力两层循环两两比较, 时间复杂度O(n^2) 空间复杂度O(1)
// 2. 先排序,之后比较前后元素是否一致即可,一层循环即可,如果排序使用的比较排序的话时间复杂度O(nlogn) 空间复杂度O(1)
// 3. 用hashmap ,时间复杂度O(n) 空间复杂度O(n)
const visited = {};
for(let i = 0; i < nums.length; i++) {
if (visited[nums[i]]) return true;
visited[nums[i]] = true;
}
return false;
};
/*
* @lc app=leetcode id=23 lang=javascript
*
* [23] Merge k Sorted Lists
*
* https://leetcode.com/problems/merge-k-sorted-lists/description/
*
* algorithms
* Hard (33.14%)
* Total Accepted: 373.7K
* Total Submissions: 1.1M
* Testcase Example: '[[1,4,5],[1,3,4],[2,6]]'
*
* Merge k sorted linked lists and return it as one sorted list. Analyze and
* describe its complexity.
*
* Example:
*
*
* Input:
* [
* 1->4->5,
* 1->3->4,
* 2->6
* ]
* Output: 1->1->2->3->4->4->5->6
*
*
*/
function mergeTwoLists(l1, l2) {
const dummyHead = {};
let current = dummyHead;
// 1 -> 3 -> 5
// 2 -> 4 -> 6
while (l1 !== null && l2 !== null) {
if (l1.val < l2.val) {
current.next = l1; // 把小的添加到结果链表
current = current.next; // 移动结果链表的指针
l1 = l1.next; // 移动小的那个链表的指针
} else {
current.next = l2;
current = current.next;
l2 = l2.next;
}
}
if (l1 === null) {
current.next = l2;
} else {
current.next = l1;
}
return dummyHead.next;
}
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode[]} lists
* @return {ListNode}
*/
var mergeKLists = function(lists) {
// 图参考: https://zhuanlan.zhihu.com/p/61796021
if (lists.length === 0) return null;
if (lists.length === 1) return lists[0];
if (lists.length === 2) {
return mergeTwoLists(lists[0], lists[1]);
}
const mid = lists.length >> 1;
const l1 = [];
for (let i = 0; i < mid; i++) {
l1[i] = lists[i];
}
const l2 = [];
for (let i = mid, j = 0; i < lists.length; i++, j++) {
l2[j] = lists[i];
}
return mergeTwoLists(mergeKLists(l1), mergeKLists(l2));
};
/*
* @lc app=leetcode id=236 lang=javascript
*
* [236] Lowest Common Ancestor of a Binary Tree
*
* https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/description/
*
* algorithms
* Medium (35.63%)
* Total Accepted: 267.3K
* Total Submissions: 729.2K
* Testcase Example: '[3,5,1,6,2,0,8,null,null,7,4]\n5\n1'
*
* Given a binary tree, find the lowest common ancestor (LCA) of two given
* nodes in the tree.
*
* According to the definition of LCA on Wikipedia: “The lowest common ancestor
* is defined between two nodes p and q as the lowest node in T that has both p
* and q as descendants (where we allow a node to be a descendant of itself).”
*
* Given the following binary tree:  root = [3,5,1,6,2,0,8,null,null,7,4]
*
*
*
* Example 1:
*
*
* Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
* Output: 3
* Explanation: The LCA of nodes 5 and 1 is 3.
*
*
* Example 2:
*
*
* Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
* Output: 5
* Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant
* of itself according to the LCA definition.
*
*
*
*
* Note:
*
*
* All of the nodes' values will be unique.
* p and q are different and both values will exist in the binary tree.
*
*
*/
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
if (!root || root === p || root === q) return root;
const left = lowestCommonAncestor(root.left, p, q);
const right = lowestCommonAncestor(root.right, p, q);
if (!left) return right; // 左子树找不到,返回右子树
if (!right) return left; // 右子树找不到,返回左子树
return root; // 左右子树分别有一个,则返回root
};
/*
* @lc app=leetcode id=238 lang=javascript
*
* [238] Product of Array Except Self
*
* https://leetcode.com/problems/product-of-array-except-self/description/
*
* algorithms
* Medium (53.97%)
* Total Accepted: 246.5K
* Total Submissions: 451.4K
* Testcase Example: '[1,2,3,4]'
*
* Given an array nums of n integers where n > 1,  return an array output such
* that output[i] is equal to the product of all the elements of nums except
* nums[i].
*
* Example:
*
*
* Input: [1,2,3,4]
* Output: [24,12,8,6]
*
*
* Note: Please solve it without division and in O(n).
*
* Follow up:
* Could you solve it with constant space complexity? (The output array does
* not count as extra space for the purpose of space complexity analysis.)
*
*/
/**
* @param {number[]} nums
* @return {number[]}
*/
var productExceptSelf = function(nums) {
const ret = [];
for (let i = 0, temp = 1; i < nums.length; i++) {
ret[i] = temp;
temp *= nums[i];
}
// 此时ret[i]存放的是前i个元素相乘的结果(不包含第i个)
// 如果没有上面的循环的话,
// ret经过下面的循环会变成ret[i]存放的是后i个元素相乘的结果(不包含第i个)
// 我们的目标是ret[i]存放的所有数字相乘的结果(不包含第i个)
// 因此我们只需要对于上述的循环产生的ret[i]基础上运算即可
for (let i = nums.length - 1, temp = 1; i >= 0; i--) {
ret[i] *= temp;
temp *= nums[i];
}
return ret;
};
/*
* @lc app=leetcode id=326 lang=javascript
*
* [326] Power of Three
*
* https://leetcode.com/problems/power-of-three/description/
*
* algorithms
* Easy (41.43%)
* Total Accepted: 178.8K
* Total Submissions: 430.4K
* Testcase Example: '27'
*
* Given an integer, write a function to determine if it is a power of three.
*
* Example 1:
*
*
* Input: 27
* Output: true
*
*
* Example 2:
*
*
* Input: 0
* Output: false
*
* Example 3:
*
*
* Input: 9
* Output: true
*
* Example 4:
*
*
* Input: 45
* Output: false
*
* Follow up:
* Could you do it without using any loop / recursion?
*/
/**
* @param {number} n
* @return {boolean}
*/
var isPowerOfThree = function(n) {
// let i = 0;
// while(Math.pow(3, i) < n) {
// i++;
// }
// return Math.pow(3, i) === n;
// 巧用整除
return n > 0 && Math.pow(3, 19) % n === 0;
};
/*
* @lc app=leetcode id=334 lang=javascript
*
* [334] Increasing Triplet Subsequence
*
* https://leetcode.com/problems/increasing-triplet-subsequence/description/
*
* algorithms
* Medium (39.47%)
* Total Accepted: 89.6K
* Total Submissions: 226.6K
* Testcase Example: '[1,2,3,4,5]'
*
* Given an unsorted array return whether an increasing subsequence of length 3
* exists or not in the array.
*
* Formally the function should:
*
* Return true if there exists i, j, k
* such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return
* false.
*
* Note: Your algorithm should run in O(n) time complexity and O(1) space
* complexity.
*
*
* Example 1:
*
*
* Input: [1,2,3,4,5]
* Output: true
*
*
*
* Example 2:
*
*
* Input: [5,4,3,2,1]
* Output: false
*
*
*
*/
/**
* @param {number[]} nums
* @return {boolean}
*/
var increasingTriplet = function(nums) {
if (nums.length < 3) return false;
let n1 = Number.MAX_VALUE;
let n2 = Number.MAX_VALUE;
for(let i = 0; i < nums.length; i++) {
if (nums[i] <= n1) {
n1 = nums[i]
} else if (nums[i] <= n2) {
n2 = nums[i]
} else {
return true;
}
}
return false;
};
/*
* @lc app=leetcode id=344 lang=javascript
*
* [344] Reverse String
*
* https://leetcode.com/problems/reverse-string/description/
*
* algorithms
* Easy (62.81%)
* Total Accepted: 409.9K
* Total Submissions: 649.5K
* Testcase Example: '["h","e","l","l","o"]'
*
* Write a function that reverses a string. The input string is given as an
* array of characters char[].
*
* Do not allocate extra space for another array, you must do this by modifying
* the input array in-place with O(1) extra memory.
*
* You may assume all the characters consist of printable ascii
* characters.
*
*
*
*
* Example 1:
*
*
* Input: ["h","e","l","l","o"]
* Output: ["o","l","l","e","h"]
*
*
*
* Example 2:
*
*
* Input: ["H","a","n","n","a","h"]
* Output: ["h","a","n","n","a","H"]
*
*
*
*
*/
/**
* @param {character[]} s
* @return {void} Do not return anything, modify s in-place instead.
*/
var reverseString = function(s) {
for(let i = 0; i < s.length >> 1; i++) {
const temp = s[i];
s[i] = s[s.length - i - 1];
s[s.length - i - 1] = temp;
}
};
/*
* @lc app=leetcode id=350 lang=javascript
*
* [350] Intersection of Two Arrays II
*
* https://leetcode.com/problems/intersection-of-two-arrays-ii/description/
*
* algorithms
* Easy (46.84%)
* Total Accepted: 185.1K
* Total Submissions: 393.7K
* Testcase Example: '[1,2,2,1]\n[2,2]'
*
* Given two arrays, write a function to compute their intersection.
*
* Example 1:
*
*
* Input: nums1 = [1,2,2,1], nums2 = [2,2]
* Output: [2,2]
*
*
*
* Example 2:
*
*
* Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
* Output: [4,9]
*
*
* Note:
*
*
* Each element in the result should appear as many times as it shows in both
* arrays.
* The result can be in any order.
*
*
* Follow up:
*
*
* What if the given array is already sorted? How would you optimize your
* algorithm?
* What if nums1's size is small compared to nums2's size? Which algorithm is
* better?
* What if elements of nums2 are stored on disk, and the memory is limited such
* that you cannot load all elements into the memory at once?
*
*
*/
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersect = function(nums1, nums2) {
const res = [];
for (let i = 0; i < nums1.length; i++) {
if (nums2.includes(nums1[i])) { // 这里我们对两个数组排序,然后二分查找, 时间复杂度nlogn
nums2[nums2.indexOf(nums1[i])] = null;
res.push(nums1[i]);
}
}
return res;
};
/*
* @lc app=leetcode id=387 lang=javascript
*
* [387] First Unique Character in a String
*
* https://leetcode.com/problems/first-unique-character-in-a-string/description/
*
* algorithms
* Easy (49.29%)
* Total Accepted: 255.6K
* Total Submissions: 513.8K
* Testcase Example: '"leetcode"'
*
*
* Given a string, find the first non-repeating character in it and return it's
* index. If it doesn't exist, return -1.
*
* Examples:
*
* s = "leetcode"
* return 0.
*
* s = "loveleetcode",
* return 2.
*
*
*
*
* Note: You may assume the string contain only lowercase letters.
*
*/
/**
* @param {string} s
* @return {number}
*/
var firstUniqChar = function(s) {
for (let i = 0; i < s.length; i++) {
if (s.indexOf(s[i]) === s.lastIndexOf(s[i])) {
return i;
}
}
return -1;
};
......@@ -75,7 +75,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
#### 简单难度
- [20. Valid Parentheses](./problems/20.validParentheses.md)
- 🖊 [[20. Valid Parentheses](./problems/20.validParentheses.md)
- [26.remove-duplicates-from-sorted-array](./problems/26.remove-duplicates-from-sorted-array.md)
- 🆕 [88.merge-sorted-array](./problems/88.merge-sorted-array.md)
- [136.single-number](./problems/136.single-number.md)
......@@ -114,7 +114,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [103.binary-tree-zigzag-level-order-traversal](./problems/103.binary-tree-zigzag-level-order-traversal.md)
- [139.word-break](./problems/139.word-breakmd)
- [144.binary-tree-preorder-traversal](./problems/144.binary-tree-preorder-traversal.md)
- [150.evaluate-reverse-polish-notation](./problems/150.evaluate-reverse-polish-notation.md)
- 🖊 [[150.evaluate-reverse-polish-notation](./problems/150.evaluate-reverse-polish-notation.md)
- [199.binary-tree-right-side-view](./problems/199.binary-tree-right-side-view.md)
- [201.bitwise-and-of-numbers-range](./problems/201.bitwise-and-of-numbers-range.md)
- 🆕 [208.implement-trie-prefix-tree](./problems/208.implement-trie-prefix-tree.md)
......@@ -142,9 +142,9 @@ leetcode 题解,记录自己的 leetcode 解题之路。
### 数据结构与算法的总结
- 🖊 [basic-data-structure](./thinkings/basic-data-structure.md)(草稿)
- [binary-tree-traversal](./thinkings/binary-tree-traversal.md)
- [dynamic-programming](./thinkings/dynamic-programming.md)
- 🖊 [数据结构](./thinkings/basic-data-structure.md)(草稿)
- 🖊 [[二叉树的遍历](./thinkings/binary-tree-traversal.md)
- [动态规划](./thinkings/dynamic-programming.md)
- [哈夫曼编码和游程编码](./thinkings/run-length-encode-and-huffman-encode.md)
- [布隆过滤器](./thinkings/bloom-filter.md)
......
......@@ -100,21 +100,28 @@ The given RPN expression is always valid. That means the expression would always
* @return {number}
*/
var evalRPN = function(tokens) {
// 这种算法的前提是 tokens是有效的,
// 当然这由算法来保证
const stack = [];
for (let index = 0; index < tokens.length; index++) {
const token = tokens[index];
// 对于运算数, 我们直接入栈
if (!Number.isNaN(Number(token))) {
stack.push(token);
} else {
// 遇到操作符,我们直接大胆运算,不用考虑算术优先级
// 然后将运算结果入栈即可
// 当然如果题目进一步扩展,允许使用单目等其他运算符,我们的算法需要做微小的调整
const a = Number(stack.pop());
const b = Number(stack.pop());
if (token === "*") {
stack.push(a * b);
stack.push(b * a);
} else if (token === "/") {
stack.push(b / a > 0 ? Math.floor(b / a) : Math.ceil(b / a));
stack.push(b / a >> 0);
} else if (token === "+") {
stack.push(a + b);
stack.push(b + a);
} else if (token === "-") {
stack.push(b - a);
}
......@@ -126,5 +133,10 @@ var evalRPN = function(tokens) {
```
## 扩展
逆波兰表达式中只改变运算符的顺序,并不会改变操作数的相对顺序,这是一个重要的性质。
另外逆波兰表达式完全不关心操作符的优先级,这在中缀表达式中是做不到的,这很有趣,感兴趣的可以私下查找资料研究下为什么会这样。
......@@ -36,6 +36,8 @@ Output: true
## 思路
关于这道题的思路,邓俊辉讲的非常好,没有看过的同学可以看一下, [视频地址](http://www.xuetangx.com/courses/course-v1:TsinghuaX+30240184+sp/courseware/ad1a23c053df4501a3facd66ef6ccfa9/8d6f450e7f7a445098ae1d507fda80f6/)
使用栈,遍历输入字符串
如果当前字符为左半边括号时,则将其压入栈中
......@@ -54,6 +56,11 @@ Output: true
(图片来自: https://github.com/MisterBooo/LeetCodeAnimation)
> 值得注意的是,如果题目要求只有一种括号,那么我们其实可以使用更简洁,更省内存的方式 - 计数器来进行求解,而
不必要使用栈。
> 事实上,这类问题还可以进一步扩展,我们可以去解析类似HTML等标记语法, 比如 <p></p> <body></body>
## 关键点解析
1. 栈的基本特点和操作
......@@ -155,4 +162,7 @@ var isValid = function(s) {
return valid;
};
```
\ No newline at end of file
```
## 扩展
如果让你检查XML标签是否闭合如何检查, 更进一步如果要你实现一个简单的XML的解析器,应该怎么实现?
\ No newline at end of file
......@@ -78,7 +78,7 @@ DP 的代码见代码区。
```js
for (let i = 1; i <= n; i++) {
for (let j = 1; j * j <= i; j++) {
// 选(dp[i]) 还是 不选(dp[i - j * j])
// 不选(dp[i]) 还是 选(dp[i - j * j])
dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
}
}
......@@ -130,7 +130,7 @@ var numSquares = function(n) {
dp[0] = 0;
for (let i = 1; i <= n; i++) {
for (let j = 1; j * j <= i; j++) {
// 选(dp[i]) 还是 不选(dp[i - j * j])
// 不选(dp[i]) 还是 选(dp[i - j * j])
dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
}
}
......
......@@ -9,6 +9,8 @@
数据结构我们可以从逻辑上分为线性结构和非线性结果。线性结构有
数组,栈,链表等, 非线性结构有树,图等。
> 其实我们可以称树为一种半线性结构。
需要注意的是,线性和非线性不代表存储结构是线性的还是非线性的,这两者没有任何关系,它只是一种逻辑上的划分。
比如我们可以用数组去存储二叉树。
### 数组
......@@ -16,6 +18,8 @@
数组是最简单的数据结构了,很多地方都用到它。 比如有一个数据列表等,用它是再合适不过了。
其实后面的数据结构很多都有数组的影子。
我们之后要讲的栈和队列其实都可以看成是一种`受限`的数组, 怎么个受限法呢?我们后面讨论。
我们来讲几个有趣的例子来加深大家对数组这种数据结构的理解。
#### React Hooks
......@@ -69,6 +73,8 @@ React 将`如何确保组件内部hooks保存的状态之间的对应关系`这
开发人员去保证,即你必须保证HOOKS的顺序严格一致,具体可以看React 官网关于 Hooks Rule 部分。
### 队列
队列是一种受限的序列,它只能够操作队尾和队首,并且只能只能在队尾添加元素,在队首删除元素。
队列作为一种最常见的数据结构同样有着非常广泛的应用, 比如消息队列
> "队列"这个名称,可类比为现实生活中排队(不插队的那种)
......@@ -107,6 +113,8 @@ React 将`如何确保组件内部hooks保存的状态之间的对应关系`这
![basic-data-structure-queue-2](../assets/thinkings/basic-data-structure-queue-2.png)
### 栈
栈也是一种受限的序列,它只能够操作栈顶,不管入栈还是出栈,都是在栈顶操作。
在计算机科学中, 一个 栈(stack) 是一种抽象数据类型,用作表示元素的集合,具有两种主要操作:
push, 添加元素到栈的顶端(末尾);
......@@ -155,6 +163,11 @@ foo();
> 社区中有很多“执行上下文中的scope指的是执行栈中父级声明的变量”说法,这是完全错误的, JS是词法作用域,scope指的是函数定义时候的父级,和执行没关系
栈常见的应用有进制转换,括号匹配,栈混洗,中缀表达式(用的很少),后缀表达式(逆波兰表达式)等。
> 合法的栈混洗操作,其实和合法的括号匹配表达式之间存在着一一对应的关系,
也就是说n个元素的栈混洗有多少种,n对括号的合法表达式就有多少种。感兴趣的可以查找相关资料
### 链表
链表是一种最基本数据结构,熟练掌握链表的结构和常见操作是基础中的基础。
......@@ -224,14 +237,66 @@ return, children, sibling也都是一个fiber,因此fiber看起来就是一个
我目前也在写关于《从零开发react系列教程》中关于fiber架构的部分,如果你对具体实现感兴趣,欢迎关注。
### 非线性结构
那么有了线性结果,我们为什么还需要非线性结果呢? 答案是为了高效地兼顾静态操作和动态操作。
大家可以对照各种数据结构的各种操作的复杂度来直观感受一下。
## 树
树的应用同样非常广泛,小到文件系统,大到因特网,组织架构等都可以表示为树结构,
而在我们前端眼中比较熟悉的DOM树也是一种树结构,而HTML作为一种DSL去描述这种树结构的具体表现形式。
树其实是一种特殊的`图`,是一种无环连通图,是一种极大无环图,也是一种极小连通图。
从另一个角度看,树是一种递归的数据结构。而且树的不同表示方法,比如不常用的`长子 + 兄弟`法,对于
你理解树这种数据结构有着很大用处, 说是一种对树的本质的更深刻的理解也不为过。
树的基本算法有前中后序遍历和层次遍历,有的同学对前中后这三个分别具体表现的访问顺序比较模糊,
其实当初我也是一样的,后面我学到了一点,你只需要记住:`所谓的前中后指的是根节点的位置,其他位置按照先左后右排列即可`
比如前序遍历就是`根左右`, 中序就是`左根右`,后序就是`左右根`, 很简单吧?
我刚才提到了树是一种递归的数据结构,因此树的遍历算法使用递归去完成非常简单,
幸运的是树的算法基本上都要依赖于树的遍历。 但是递归在计算机中的性能一直都有问题,
因此掌握不那么容易理解的"命令式地迭代"遍历算法在某些情况下是有用的。
如果你使用迭代式方式去遍历的话,可以借助上面提到的`栈`来进行,可以极大减少代码量。
> 如果使用栈来简化运算,由于栈是FILO的,因此一定要注意左右子树的推入顺序。
树的重要性质:
- 如果树有n个顶点,那么其就有n - 1条边,这说明了树的顶点数和边数是同阶的。
- 任何一个节点到根节点存在`唯一`路径, 路径的长度为节点所处的深度
### 二叉树
二叉树是节点度数不超过二的树,是树的一种特殊子集,有趣的是二叉树这种被限制的树结构却能够表示和实现所有的树,
它背后的原理正是`长子 + 兄弟`法,用邓老师的话说就是`二叉树是多叉树的特例,但在有根且有序时,其描述能力却足以覆盖后者`
> 实际上, 在你使用`长子 + 兄弟`法表示树的同时,进行45度角旋转即可。
相关算法:
- [94.binary-tree-inorder-traversal](../problems/94.binary-tree-inorder-traversal.md)
- [102.binary-tree-level-order-traversal](../problems/102.binary-tree-level-order-traversal.md)
- [103.binary-tree-zigzag-level-order-traversal](../problems/103.binary-tree-zigzag-level-order-traversal.md)
- [144.binary-tree-preorder-traversal](../problems/144.binary-tree-preorder-traversal.md)
- [145.binary-tree-postorder-traversal](../problems/145.binary-tree-postorder-traversal.md)
- [199.binary-tree-right-side-view](../problems/199.binary-tree-right-side-view.md)
相关概念:
- 真二叉树
另外我也专门开设了[二叉树的遍历](./binary-tree-traversal.md)章节, 具体细节和算法可以去那里查看。
#### 堆
优先级队列
堆其实是一种优先级队列,在很多语言都有对应的内置数据结构,很遗憾javascript没有这种原生的数据结构。
不过这对我们理解和运用不会有影响。
相关算法:
- [295.find-median-from-data-stream](../problems/295.find-median-from-data-stream.md)
#### 二叉查找树
### 平衡树
......@@ -244,4 +309,7 @@ database engine
### 字典树(前缀树)
相关算法:
- [208.implement-trie-prefix-tree](../problems/208.implement-trie-prefix-tree.md)
## 图
......@@ -38,6 +38,11 @@ BFS 的关键点在于如何记录每一层次是否遍历完成, 我们可以
总结: 典型的递归数据结构,典型的用栈来简化操作的算法。
其实从宏观上表现为:`自顶向下依次访问左侧链,然后自底向上依次访问右侧链`
如果从这个角度出发去写的话,算法就不一样了。从上向下我们可以直接递归访问即可,从下向上我们只需要借助栈也可以轻易做到。
这种思路解题有点像我总结过的一个解题思路`backtrack` - 回溯法。这种思路有一个好处就是
可以`统一三种遍历的思路`.
## 中序遍历
相关问题[94.binary-tree-inorder-traversal](../problems/94.binary-tree-inorder-traversal.md)
......
/*
* @lc app=leetcode id=324 lang=javascript
*
* [324] Wiggle Sort II
*
* https://leetcode.com/problems/wiggle-sort-ii/description/
*
* algorithms
* Medium (27.53%)
* Total Accepted: 57.5K
* Total Submissions: 206.9K
* Testcase Example: '[1,5,1,1,6,4]'
*
* Given an unsorted array nums, reorder it such that nums[0] < nums[1] >
* nums[2] < nums[3]....
*
* Example 1:
*
*
* Input: nums = [1, 5, 1, 1, 6, 4]
* Output: One possible answer is [1, 4, 1, 5, 1, 6].
*
* Example 2:
*
*
* Input: nums = [1, 3, 2, 2, 3, 1]
* Output: One possible answer is [2, 3, 1, 3, 1, 2].
*
* Note:
* You may assume all input has valid answer.
*
* Follow Up:
* Can you do it in O(n) time and/or in-place with O(1) extra space?
*/
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var wiggleSort = function(nums) {
for(let i = 0; i < nums.length; i++) {}
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册