├── README.md ├── coder └── linked-lists │ ├── add-integers.md │ ├── deep-copy-with-arbitrary-pointer.md │ ├── delete-node.md │ └── reverse-linked-list.md ├── common.md ├── leetcode ├── contain-duplicate.js ├── court-primes.js ├── h-index-ii.js ├── h-index.js ├── happy-number.js ├── house-robber.js ├── implement-strStr.js ├── invert-binary-tree.js ├── isomorphic-strings.js ├── merge-sorted-array.js ├── nim-game.md ├── recover-binary-search-tree.js ├── remove-duplicates-from-sorted-array.js ├── reverse-integer.js └── roman-to-integer.js ├── note.md ├── note ├── arrays.md ├── dynamic-programming.md ├── graphs.md ├── hashmap.md ├── listnode.md ├── math.md ├── n-queen.md ├── string.md └── tree.md ├── questions └── note.md ├── single-linked-node.js ├── sites.md ├── 《数据结构与算法JavaScript描述》 └── 习题 │ ├── 第三章 │ ├── question1.js │ └── question2.js │ └── 第二章 │ └── question2.js ├── 经典算法 ├── bigNumberAdd.js ├── knapsack-problem.js ├── shuffle.js └── sort.js └── 面试题-数组去重.js /README.md: -------------------------------------------------------------------------------- 1 | JavaScript-Algorithms 2 | ===================== 3 | 4 | JavaScript 算法与数据结构 精华集 5 | 6 | 主要收录 以js实现的算法题与数据结构相关的知识,以及国内外相关的js算法面试题 7 | -------------------------------------------------------------------------------- /coder/linked-lists/add-integers.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /coder/linked-lists/deep-copy-with-arbitrary-pointer.md: -------------------------------------------------------------------------------- 1 | Copy linked list with arbitrary pointer 2 | 3 | Q: We are given a linked list where the node has two pointers. 4 | 5 | First one is the regular 'next' pointer . 6 | 7 | The second pointer is called 'arbitrary_pointer' that can point to any node in the linked list. 8 | 9 | Write code to make a deep copy of the given linked list. 10 | -------------------------------------------------------------------------------- /coder/linked-lists/delete-node.md: -------------------------------------------------------------------------------- 1 | ### Delete node with a given key 2 | 3 | Q: Given head of a linked list and a key, 4 | 5 | delete node with this given key from linked list. 6 | 7 | Example: 8 | 9 | 10 | -------------------------------------------------------------------------------- /coder/linked-lists/reverse-linked-list.md: -------------------------------------------------------------------------------- 1 | ### Reverse a singly linked list 2 | 3 | Q: Given the pointer/reference to the head of a singly linked list, 4 | 5 | reverse it and return the pointer/reference to the head of reversed linked list. 6 | -------------------------------------------------------------------------------- /common.md: -------------------------------------------------------------------------------- 1 | 2 | ### 1.Fibonacci--斐波那契数列 3 | 4 | 算法复杂度为[O(2n)](http://stackoverflow.com/questions/360748/computational-complexity-of-fibonacci-sequence/360773#360773) 5 | 6 | ```js 7 | function fibonacci(n) { 8 | return n < 2 ? n : fibonacci(n-1) + fibonacci(n-2); 9 | } 10 | ``` 11 | 12 | ### 2.求数组中的最大值 13 | 14 | ```js 15 | function maxInArray(arr) { 16 | return Math.max.apply(Math, arr); 17 | } 18 | ``` 19 | 20 | ### 3. 字符串反转 21 | 22 | ```js 23 | String.prototype.reverse = function() { 24 | return this.split('').reverse().join(''); 25 | } 26 | ``` 27 | or 28 | 29 | ```js 30 | String.prototype.reverse = function() { 31 | var str = ''; 32 | var len = this.length; 33 | while (len>0) { 34 | str += this.substring(len-1, len); 35 | len--; 36 | } 37 | return str; 38 | } 39 | ``` 40 | 41 | 注: 在类似'foo 𝌆 bar'这种astral symbol,将展示异。 42 | 43 | 可以使用[ Esrever](https://github.com/mathiasbynens/esrever) 来处理这种特殊字符的反转。 44 | 45 | ### 4.反转DOM 46 | 47 | 上代码: 48 | 49 | ```js 50 | function reverseDom(el){ 51 | var frag = document.createDocumentFragment(); 52 | while(el.lastChild){ 53 | frag.appendChild(el.lastChild); 54 | } 55 | el.appendChild(frag); 56 | } 57 | ``` 58 | 59 | 注:这里采用的是原生的DOM操作, 60 | 61 | 采用documentFragment的形式形成一个缓存区, 62 | 63 | 再采用appendChild,appendChild有个特点:如果被插入的节点已经存在于当前文档的DOM树中,则那个节点会首先从原先的位置移除,然后再插入到新的位置。 64 | 65 | 利用这个特点可以去除原先位置的节点,再插入新的排序后的节点。 66 | 67 | ### 5.移除重复字符 68 | 69 | 注:需问清楚是否关注字母大小写与空格问题。 70 | 71 | ```js 72 | function removeDuplicateChar(str){ 73 | var strArr = str.split(''); 74 | var targetArr = []; 75 | strArr.forEach(function(item){ 76 | if (strArr.indexOf(item) === strArr.lastIndexOf(item)) { 77 | targetArr.push(item) 78 | } 79 | }) 80 | 81 | // 去除空格,区分大小写 82 | return targetArr.join('').split(' ').join(''); 83 | 84 | } 85 | ``` 86 | 87 | ### 6.是否是 回文(palindrome) 88 | 89 | 回文:从左到右跟从右到左是一样的。 90 | 91 | Bulid-in Method 内置方法 92 | ```js 93 | function isPalindrom(str) { 94 | return str === str.split('').reverse().join(''); 95 | } 96 | ``` 97 | 98 | 原生方法: 99 | ```js 100 | function isPalindrome(str){ 101 | var i, len = str.length; 102 | // 前一半与后一半进行对比,如果有不同的就不是 103 | for(i =0; i0){ 122 | count += Math.floor(n/10); 123 | n = n/10; 124 | } 125 | return count; 126 | } 127 | ``` 128 | 129 | ### 8.穷举排列(permutation) 130 | 131 | [see](http://www.lifelaf.com/blog/?p=1228) 132 | 133 | 穷举一个数组中各个元素的排列 134 | 135 | 策略 136 | 137 | 减而治之、递归 138 | 139 | ```js 140 | /** 141 | * Created by cshao on 12/23/14. 142 | */ 143 | 144 | function getPermutation(arr) { 145 | if (arr.length == 1) { 146 | return [arr]; 147 | } 148 | 149 | var permutation = []; 150 | for (var i=0; i=0; i--) { 32 | var currNum = rToIMap[s[i]], 33 | afterNum = rToIMap[s[i+1]]; 34 | 35 | if (currNum >= afterNum) { 36 | result += currNum; 37 | } else { 38 | result -= currNum; 39 | } 40 | } 41 | 42 | return result; 43 | }; 44 | -------------------------------------------------------------------------------- /note.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /note/arrays.md: -------------------------------------------------------------------------------- 1 | ### Binary search: 2 | 3 | Step: 4 | 5 | 1. Find the mid index and set the low and high value; 6 | 2. Compare the mid value and target one, 7 | 8 | if the mid value is greater than the target one ,than set the high value to mid -1; 9 | if no, set the low value to mid +1; 10 | 11 | ### 数组去重 12 | 13 | > Hash中转 14 | 15 | 16 | -------------------------------------------------------------------------------- /note/dynamic-programming.md: -------------------------------------------------------------------------------- 1 | Introduction (Beginner) 2 | What is a dynamic programming, how can it be described? 3 | 4 | A DP is an algorithmic technique which is usually based on a recurrent formula and one (or some) starting states. A sub-solution of the problem is constructed from previously found ones. DP solutions have a polynomial complexity which assures a much faster running time than other techniques likebacktracking, brute-force etc. 5 | 6 | Now let's see the base of DP with the help of an example: 7 | 8 | Given a list of N coins, their values (V1, V2, ... , VN), and the total sum S. Find the minimum number of coins the sum of which is S (we can use asmany coins of one type as we want), or report that it's not possible to select coins in such a way that they sum up to S. 9 | 10 | Now let's start constructing a DP solution: 11 | 12 | First of all we need to find a state for which an optimal solution is found and with the help of which we can find the optimal solution for the nextstate. 13 | 14 | What does a "state" stand for? 15 | 16 | It's a way to describe a situation, a sub-solution for the problem. For example a state would be the solution for sum i, where i≤S. A smaller state than state i would be the solution for any sum j, where jS[i] ), we make S[i]=S[j]+1. This way we consecutively find the best solutions for each i, until last state N. 75 | 76 | Let's see what happens for a randomly generated sequence: 5, 3, 4, 8, 6, 7: 77 | 78 | I The length of the longest 79 | non-decreasing sequence 80 | of first i numbers The last sequence i from 81 | which we "arrived" 82 | to this one 83 | 1 1 1 (first number itself) 84 | 2 1 2 (second number itself) 85 | 3 2 2 86 | 4 3 3 87 | 5 3 3 88 | 6 4 5 89 | 90 | Practice problem: 91 | Given an undirected graph G having N (10 ; S[i][j-1], if j>0) (where i represents the row and j the column of the table , its left-upper corner having coordinates {0,0} ; and A[i][j] being the number of apples situated in cell i,j). 109 | 110 | S[i][j] must be calculated by going first from left to right in each row and process the rows from top to bottom, or by going first from top to bottom in each column and process the columns from left to right. 111 | 112 | Pseudocode: 113 | For i = 0 to N - 1 114 | For j = 0 to M - 1 115 | S[i][j] = A[i][j] + 116 | max(S[i][j-1], if j>0 ; S[i-1][j], if i>0 ; 0) 117 | 118 | Output S[n-1][m-1] 119 | -------------------------------------------------------------------------------- /note/graphs.md: -------------------------------------------------------------------------------- 1 | 2 | - [图算法领域10大经典算法](http://www.cnblogs.com/v-July-v/archive/2011/02/14/1983678.html) 3 | -------------------------------------------------------------------------------- /note/hashmap.md: -------------------------------------------------------------------------------- 1 | [原理](http://www.importnew.com/16301.html) 2 | 3 | [Java函数](http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html) 4 | -------------------------------------------------------------------------------- /note/listnode.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /note/math.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /note/n-queen.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /note/string.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /note/tree.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /questions/note.md: -------------------------------------------------------------------------------- 1 | #### 反转单链表 2 | -------------------------------------------------------------------------------- /single-linked-node.js: -------------------------------------------------------------------------------- 1 | var SinglyLinkedList = function(){} 2 | 3 | SinglyLinkedList.prototype = { 4 | addBottom: function(node) { 5 | if (this.head == undefined) return this.head = node; 6 | var currentNode = this.head; 7 | while(currentNode.next !== undefined) { 8 | currentNode = currentNode.next; 9 | } 10 | currentNode.next = node; 11 | }, 12 | 13 | find: function(data) { 14 | var currentNode = this.head; 15 | while(currentNode !== undefined) { 16 | if(currentNode.data == data) return currentNode; 17 | currentNode = currentNode.next; 18 | } 19 | }, 20 | 21 | addTop: function(node) { 22 | if (this.head == undefined) return this.head = node; 23 | node.next = this.head; 24 | this.head = node; 25 | }, 26 | 27 | remove: function(data) { 28 | if (this.head.data == data) return this.head = this.head.next; 29 | var prevNode = this.head; 30 | var currentNode = this.head.next; 31 | while(currentNode !== undefined) { 32 | if(currentNode.data == data) { 33 | prevNode.next = currentNode.next; 34 | return currentNode.next = undefined; 35 | } 36 | prevNode = currentNode; 37 | currentNode = currentNode.next; 38 | } 39 | } 40 | } 41 | 42 | module.exports = SinglyLinkedList; 43 | -------------------------------------------------------------------------------- /sites.md: -------------------------------------------------------------------------------- 1 | [JS: Interview Algorithm](http://www.thatjsdude.com/interview/js1.html) 2 | -------------------------------------------------------------------------------- /《数据结构与算法JavaScript描述》/习题/第三章/question1.js: -------------------------------------------------------------------------------- 1 | /* 2 | *题目: 3 | * 增加一个向列表中插入元素的方法, 4 | *该方法只在待插入元素大于列表中的所有元素时才进行插入操作。 5 | *这里的大于有多重含义,对于数字,它是指数值上的大小; 6 | *对于字母,它是指在字母表中出现的先后顺序。 7 | * 8 | */ 9 | 10 | //评注:该题出得有点语义不明, 11 | //对于数字字母混合的情况没有说明 12 | //故暂以都是字母或者数字为例 13 | 14 | 15 | /* 16 | * tools 17 | * a与b的大小比较, 18 | * 若a大于b则返回true 19 | */ 20 | function compareSequence(a, b){ 21 | 22 | //如果是字符串的数字( "11" < "2" )的处理 23 | var num1 = parseInt(a, 10), 24 | num2 = parseInt(b, 10); 25 | if (typeof(num1) === "number" && typeof(num2) === "number") { 26 | if (num1 > num2) { 27 | return true; 28 | } else { 29 | return false; 30 | } 31 | } 32 | 33 | //字母的处理 34 | if (a.toLowerCase() > b.toLowerCase()) { 35 | return true; 36 | } else { 37 | return false; 38 | } 39 | } 40 | 41 | 42 | //注这里需配合课本中实现的List列表类来解答 43 | function insertBiggest (element) { 44 | for (var i=0; i < this.dataStore.length; i++) { 45 | 46 | //需大于列表全部元素 47 | if ( !compareSequence(element, this.dataStore[i]) ) { 48 | return false; 49 | } 50 | } 51 | 52 | this.append(element); 53 | return true; 54 | } 55 | -------------------------------------------------------------------------------- /《数据结构与算法JavaScript描述》/习题/第三章/question2.js: -------------------------------------------------------------------------------- 1 | /* 2 | *题目: 3 | * 增加一个向列表中插入元素的方法, 4 | *该方法只在待插入元素小于列表中的所有元素时才进行插入操作。 5 | * 6 | */ 7 | 8 | -------------------------------------------------------------------------------- /《数据结构与算法JavaScript描述》/习题/第二章/question2.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 题目:将一组单词存储在一个数组中,并按正序和倒序分别显示这些单词 3 | * 4 | */ 5 | var testArr = ["this", "is", "a", "test"], 6 | testLen = testArr.length, 7 | i = 0, 8 | j = testLen - 1; 9 | 10 | // 正序 11 | for (; i < testLen; i++ ) { 12 | console.log(testArr[i]); 13 | } 14 | 15 | // 倒序 16 | for (; j >= 0; j--) { 17 | console.log(testArr[j]) 18 | } 19 | -------------------------------------------------------------------------------- /经典算法/bigNumberAdd.js: -------------------------------------------------------------------------------- 1 | function bigNumberAdd(a,b){ 2 | function addZero(str, length) { 3 | return new Array(length - str.length + 1).join("0") + str; 4 | } 5 | 6 | var c = ''; 7 | var temp = 0; 8 | var aLength = a.length; 9 | var bLength = b.length; 10 | 11 | if (aLength > bLength) { 12 | b = addZero(b, aLength); 13 | } else { 14 | a = addZero(a, bLength); 15 | } 16 | var length = a.length; 17 | 18 | for (var i = length - 1; i >= 0; i--) { 19 | temp = parseInt(a.charAt(i)) + parseInt(b.charAt(i)) + parseInt(temp); 20 | if (10 < temp) { 21 | c = (temp - 10) + c; 22 | temp = 1; 23 | } else { 24 | c = temp + c; 25 | temp = 0; 26 | } 27 | } 28 | 29 | return c; 30 | } 31 | -------------------------------------------------------------------------------- /经典算法/knapsack-problem.js: -------------------------------------------------------------------------------- 1 | //背包问题 2 | // https://en.wikipedia.org/wiki/Knapsack_problem 3 | // 解法参见http://www.importnew.com/13072.html 4 | -------------------------------------------------------------------------------- /经典算法/shuffle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 洗牌算法: 3 | * 1. 从第一张牌开始,将每张牌和随机的一张牌进行交换 4 | * 2. 更优解法:从第一张牌开始,将每张牌和之前全部牌中随机的一张进行交换 5 | * 3. C++ 标准库函数 std::random_shuffle (原理与第一点差不多) 6 | */ 7 | 8 | //inspired by http://www.cs.princeton.edu/~rs/ 9 | function shuffle(arr) { 10 | var len = arr.length, i; 11 | while (len) { 12 | i = Math.random() * len-- | 0; // 0 ≤ i < n 13 | arr[len] = [ arr[i], arr[i] = arr[len] ][0]; 14 | } 15 | return arr; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /经典算法/sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | *几种排序算法 3 | *@TangGuichuan 4 | * 5 | */ 6 | 7 | 8 | /** 9 | * @选择排序 http://en.wikipedia.org/wiki/Selection_sort 10 | * 11 | * 原理:在未排序的序列中找到最大(小)的元素与第1个元素交换, 12 | * 在剩余元素中继续找最大(小)的元素与第2个元素交换, 13 | * 以此类推,直到排序完毕 14 | */ 15 | 16 | function selectionSort(arr){ 17 | var 18 | i = arr.length - 1, 19 | j, 20 | buffer, 21 | special; //最大或最小值的位置 22 | 23 | // 采用倒序,提高查找性能 24 | for (; i >= 0; i--) { 25 | special = i; 26 | buffer = arr[i]; 27 | 28 | for (j = i - 1; j >= 0; j--) { 29 | 30 | // 正序与倒序取决于这里的判断,max or min 31 | if(buffer < arr[j]){ 32 | // 当前的最值位置 33 | special = j; 34 | buffer = arr[j]; 35 | } 36 | } 37 | // 最值与当前位置的值交换位置 38 | arr[special] = [ arr[i], arr[i]=buffer ][0]; 39 | } 40 | 41 | return arr; 42 | } 43 | 44 | 45 | /** 46 | *@冒泡排序 http://en.wikipedia.org/wiki/Bubble_sort 47 | * 48 | *原理:两两比较顺序,如果顺序错误则交换位置 49 | */ 50 | 51 | function bubbleSort(arr){ 52 | var 53 | i = arr.length - 1, 54 | j; 55 | 56 | for (; i >= 0; i--) { 57 | 58 | for (j = i - 1; j >= 0; j--) { 59 | if (arr[j] > arr[j+1]) { 60 | arr[j] = [ arr[j+1], arr[j+1]=arr[j] ][0]; 61 | } 62 | } 63 | 64 | } 65 | 66 | return arr; 67 | } 68 | 69 | 70 | /** 71 | *@插入排序 http://en.wikipedia.org/wiki/Insertion_sort 72 | * 73 | *原理:1.从第二位(当前元素)开始从后向前查找 74 | * 2.若新元素(当前元素的前面)大于当前元素,将新元素移到下一位置 75 | * 3.重复2,直到在有序区找到大于或等于新元素的位置 76 | * 4.将当前元素插到上面找到的位置 77 | * 5.重复2~4 78 | */ 79 | 80 | function insertionSort(arr){ 81 | var 82 | len = arr.length, 83 | i = 1, 84 | j, 85 | buffer; 86 | 87 | for (; i < len; i++) { 88 | buffer = arr[i]; 89 | 90 | //在当前元素从后向前遍历, 91 | //一旦找到比当前元素大的就进行“元素加位” 92 | for (j = i - 1; j >= 0 && arr[j] > buffer; j--) { 93 | arr[j+1] = arr[j]; 94 | } 95 | //找到的位置替换为当前元素,比它大的在上面已经“加位”了 96 | arr[j+1] = buffer; 97 | } 98 | 99 | return arr; 100 | } 101 | 102 | /** 103 | * @二分插入排序 104 | * 用二分法对插入排序进行优化 105 | * 106 | */ 107 | 108 | function binaryInsertSort(arr){ 109 | 110 | } 111 | 112 | /** 113 | * @归并排序 114 | * 115 | * / 116 | 117 | -------------------------------------------------------------------------------- /面试题-数组去重.js: -------------------------------------------------------------------------------- 1 | // see http://www.cnblogs.com/mackxu/p/array-unique.html 2 | 3 | // for循环删除后面重复的 速度最快,可用倒序计算可加快速度 4 | 5 | var uniqueFor = function(arr) { 6 | for (var i = 0; i < arr.length - 1; i++) { 7 | var item = arr[i]; 8 | for(var j = i+1; j < arr.length; j++ ) { 9 | item === arr[j] && (arr.splice(j, 1), j--); 10 | } 11 | }; 12 | return arr; 13 | }; 14 | 15 | 16 | //判断对象属性 17 | 18 | var uniqueObject = function(arr) { 19 | var v, r = [], o = {}; 20 | for(var i = 0; (v = arr[i]) !== undefined; i++) { 21 | !o[v] && (r.push(v), o[v] = true); 22 | } 23 | return r; 24 | }; 25 | 26 | 27 | //数组过滤重复项filter 28 | 29 | var uniqueFilter = function(arr) { 30 | return arr.filter(function(elem, pos, self) { 31 | // 如果没有重复项,返回true 32 | return self.indexOf(elem, pos + 1) === -1; 33 | }); 34 | }; 35 | --------------------------------------------------------------------------------