[
  {
    "path": "README.md",
    "content": "JavaScript-Algorithms\n=====================\n\nJavaScript 算法与数据结构 精华集\n\n主要收录 以js实现的算法题与数据结构相关的知识，以及国内外相关的js算法面试题\n"
  },
  {
    "path": "coder/linked-lists/add-integers.md",
    "content": "\n"
  },
  {
    "path": "coder/linked-lists/deep-copy-with-arbitrary-pointer.md",
    "content": "Copy linked list with arbitrary pointer\n\nQ: We are given a linked list where the node has two pointers.\n\nFirst one is the regular 'next' pointer . \n\nThe second pointer is called 'arbitrary_pointer' that can point to any node in the linked list.\n\nWrite code to make a deep copy of the given linked list.\n"
  },
  {
    "path": "coder/linked-lists/delete-node.md",
    "content": "### Delete node with a given key\n\nQ: Given head of a linked list and a key,\n\ndelete node with this given key from linked list.\n\nExample:\n\n\n"
  },
  {
    "path": "coder/linked-lists/reverse-linked-list.md",
    "content": "### Reverse a singly linked list\n\nQ: Given the pointer/reference to the head of a singly linked list, \n\nreverse it and return the pointer/reference to the head of reversed linked list.\n"
  },
  {
    "path": "common.md",
    "content": "\n### 1.Fibonacci--斐波那契数列\n\n算法复杂度为[O(2n)](http://stackoverflow.com/questions/360748/computational-complexity-of-fibonacci-sequence/360773#360773)\n\n```js\nfunction fibonacci(n) {\n  return n < 2 ? n : fibonacci(n-1) + fibonacci(n-2); \n}\n```\n\n### 2.求数组中的最大值\n\n```js\nfunction maxInArray(arr) {\n  return Math.max.apply(Math, arr);\n}\n```\n\n### 3. 字符串反转\n\n```js\nString.prototype.reverse = function() {\n  return this.split('').reverse().join('');\n}\n```\nor\n\n```js\nString.prototype.reverse = function() {\n    var str = '';\n    var len = this.length;\n    while (len>0) {\n        str += this.substring(len-1, len);\n        len--;\n    }\n    return str;\n}\n```\n\n注: 在类似'foo 𝌆 bar'这种astral symbol,将展示异。\n\n可以使用[ Esrever](https://github.com/mathiasbynens/esrever) 来处理这种特殊字符的反转。\n\n### 4.反转DOM\n\n上代码：\n\n```js\nfunction reverseDom(el){\n\tvar frag = document.createDocumentFragment();\n\twhile(el.lastChild){\n\t\tfrag.appendChild(el.lastChild);\n\t}\n\tel.appendChild(frag);\n}\n```\n\n注：这里采用的是原生的DOM操作，\n\n采用documentFragment的形式形成一个缓存区，\n\n再采用appendChild，appendChild有个特点：如果被插入的节点已经存在于当前文档的DOM树中,则那个节点会首先从原先的位置移除,然后再插入到新的位置。\n\n利用这个特点可以去除原先位置的节点，再插入新的排序后的节点。\n\n### 5.移除重复字符\n\n注：需问清楚是否关注字母大小写与空格问题。\n\n```js\nfunction removeDuplicateChar(str){\n  var strArr = str.split('');\n  var targetArr = [];\n  strArr.forEach(function(item){\n    if (strArr.indexOf(item) === strArr.lastIndexOf(item)) {\n      targetArr.push(item)\n    }\n  })\n  \n  // 去除空格，区分大小写\n  return targetArr.join('').split(' ').join('');\n\n}\n```\n\n### 6.是否是 回文(palindrome)\n\n回文：从左到右跟从右到左是一样的。\n\nBulid-in Method 内置方法\n```js\nfunction isPalindrom(str) {\n    return str === str.split('').reverse().join('');\n}\n```\n\n原生方法：\n```js\nfunction isPalindrome(str){\n  var i, len = str.length;\n  // 前一半与后一半进行对比，如果有不同的就不是\n  for(i =0; i<len/2; i++){\n    if (str[i]!== str[len -1 -i])\n       return false;\n  }\n  return true;\n}\n```\n\n### 7.数-数字\n\n从0 开始到n总共多少个“什么数字”（0，1，2...）\n\n如从0到2015有多少个0：\n\n```js\nfunction countNumber(n){\n  // 包括0，即单位数都算\n  var count = 1;\n  while(n>0){\n   count += Math.floor(n/10);\n   n = n/10;\n  }\n  return count;\n}\n```\n\n### 8.穷举排列(permutation)\n\n[see](http://www.lifelaf.com/blog/?p=1228)\n\n穷举一个数组中各个元素的排列\n\n策略\n\n减而治之、递归\n\n```js\n/**\n * Created by cshao on 12/23/14.\n */\n\nfunction getPermutation(arr) {\n  if (arr.length == 1) {\n    return [arr];\n  }\n\n  var permutation = [];\n  for (var i=0; i<arr.length; i++) {\n    var firstEle = arr[i];\n    var arrClone = arr.slice(0);\n    arrClone.splice(i, 1);\n    var childPermutation = getPermutation(arrClone);\n    for (var j=0; j<childPermutation.length; j++) {\n      childPermutation[j].unshift(firstEle);\n    }\n    permutation = permutation.concat(childPermutation);\n  }\n  return permutation;\n}\n\nvar permutation = getPermutation(['a','b','c']);\nconsole.dir(permutation);\n```\n"
  },
  {
    "path": "leetcode/contain-duplicate.js",
    "content": "/*\n* Question:\n* Given an array of integers, find if the array contains any duplicates. \n* Your function should return true if any value appears at least twice in the array, \n* and it should return false if every element is distinct.\n*  \n* 注释： 判断一个数组是否有重复元素，如果重复则返回true,反之返回false\n*\n* Runtime: 136 ms\n*/\n\n\n/**\n * @param {number[]} nums\n * @return {boolean}\n */\nvar containsDuplicate = function(nums) {\n    var tempHash = {};\n    var i = nums.length -1;\n    var isDistinct = false;\n    //注意空数组情况，倒序提高速度\n    while (0 <= i){\n        if (!tempHash[nums[i]]){\n            tempHash[nums[i]] = true;\n        } else {\n            isDistinct = true;\n        }\n        i--;\n    }\n    \n    return isDistinct;\n};\n"
  },
  {
    "path": "leetcode/court-primes.js",
    "content": "/**\n *  Qusetion:\n *    Count the number of prime numbers less than a non-negative number, n.\n *  Url and solution:\n *    https://leetcode.com/problems/count-primes/ \n * \n * /\n/**\n * @param {number} n\n * @return {number}\n */\nvar countPrimes = function(n) {\n   var pHash = {};\n   var count = 0;\n   \n   for (var k = 2; k < n; k++) {\n      pHash[k] = true;\n   }\n   // Loop's ending condition is i * i < n instead of i < sqrt(n)\n   // to avoid repeatedly calling an expensive function sqrt().\n   for (var i = 2; i * i < n; i++) {\n      if (!pHash[i]) continue;\n      for (var j = i * i; j < n; j += i) {\n         pHash[j] = false;\n      }\n   }\n   \n   for (var l = 2; l < n; l++) {\n      if (pHash[l]) count++;\n   }\n   \n   return count;\n};\n"
  },
  {
    "path": "leetcode/h-index-ii.js",
    "content": "/*\n* Follow up for H-Index(https://leetcode.com/problems/h-index/):\n*   What if the citations array is sorted in ascending order? \n*   Could you optimize your algorithm?\n*\n*/\n"
  },
  {
    "path": "leetcode/h-index.js",
    "content": "\n/**\n* URL: https://leetcode.com/problems/h-index/\n*\n* 题目：\n* Given an array of citations (each citation is a non-negative integer) of a researcher, \n* write a function to compute the researcher's h-index.\n* According to the definition of h-index on Wikipedia: \n* \"A scientist has index h if h of his/her N papers have at least h citations each, \n* and the other N − h papers have no more than h citations each.\"\n\n *For example, given citations = [3, 0, 6, 1, 5],\n* which means the researcher has 5 papers in total and each of them had received 3, 0, 6, 1, 5 citations respectively. \n* Since the researcher has 3 papers with at least 3 citations each and the remaining two with no more than 3 citations each, \n* his h-index is 3.\n\n* Note: If there are several possible values for h, the maximum one is taken as the h-index.\n*/\n"
  },
  {
    "path": "leetcode/happy-number.js",
    "content": "/**\n * Write an algorithm to determine if a number is \"happy\".\n\n * A happy number is a number defined by the following process: \n * Starting with any positive integer, replace the number by the sum of the squares of its digits, \n * and repeat the process until the number equals 1 (where it will stay), \n * or it loops endlessly in a cycle which does not include 1.\n * Those numbers for which this process ends in 1 are happy numbers.\n\n * Example: 19 is a happy number\n\n * 12 + 92 = 82\n * 82 + 22 = 68\n * 62 + 82 = 100\n * 12 + 02 + 02 = 1\n */\n"
  },
  {
    "path": "leetcode/house-robber.js",
    "content": "/**\n * Question: \n * You are a professional robber planning to rob houses along a street. \n * Each house has a certain amount of money stashed,\n * the only constraint stopping you from robbing each of them is that adjacent houses have security system connected\n * and it will automatically contact the police \n * if two adjacent houses were broken into on the same night.\n\n * Given a list of non-negative integers representing the amount of money of each house, \n * determine the maximum amount of money you can rob tonight without alerting the police.\n * \n * /\n  \n/**动态规划的题\n * \n * 思路：\n *  本质相当于在一列数组中取出一个或多个不相邻数，使其和最大。求极值的问题。\n * 我们维护一个一位数组dp，其中dp[i]表示到i位置时不相邻数能形成的最大和，\n * 经过分析，可得到递推公式dp[i] = max(num[i] + dp[i - 2], dp[i - 1])\n * \n * 分别维护两个变量a和b，然后按奇偶分别来更新a和b，这样就可以保证组成最大和的数字不相邻\n\n\n  \n/**\n * @param {number[]} nums\n * @return {number}\n */\nvar rob = function(nums) {\n     var currMaxPV = 0, //当前最大值：上一轮循环中的最大值加上当前值\n        lastRealMax = 0, //上一轮循环中的真正的最大值\n        i = nums.length -1;\n        \n        while ( 0 <= i) { // eg: [6,3,1,6,1]\n          var tempLastMaxPV = currMaxPV, //0 6 3 7 12\n              tempLastMax = lastRealMax; //0 0 6 6 7\n          currMaxPV = tempLastMax + nums[i];//6 3 7 12 8\n          lastRealMax = Math.max(tempLastMaxPV, tempLastMax);//0 6 6 7 12\n          i--;\n        }\n        return Math.max(currMaxPV, lastRealMax); // 12\n};\n\n"
  },
  {
    "path": "leetcode/implement-strStr.js",
    "content": "\n"
  },
  {
    "path": "leetcode/invert-binary-tree.js",
    "content": "//反转二叉树\n/**\n * Question:\n *  Invert a binary tree.\n\n     4\n   /   \\\n  2     7\n / \\   / \\\n1   3 6   9\n\n* to\n\n     4\n   /   \\\n  7     2\n / \\   / \\\n9   6 3   1\n\n * \n * /\n  \n  \n  \n/**\n * Definition for a binary tree node.\n * function TreeNode(val) {\n *     this.val = val;\n *     this.left = this.right = null;\n * }\n */\n/**\n * @param {TreeNode} root\n * @return {TreeNode}\n */\nvar invertTree = function(root) {\n    if (root){\n        // 遍历节点做交换位置\n        root.left = [invertTree(root.right), root.right = invertTree(root.left)][0];\n    }\n    return root;\n};\n\n\n// 不递归版本\nvar invertTree = function(root) {\n    if (root !== null) {\n        var nodes = [root];\n        while(nodes.length) {\n            //将数组中第一个值抛出来，node做对象引用\n            var node = nodes.shift();\n            if(node === null) continue;\n            \n            //放进数组中继续遍历子节点，全部做左右交换\n            nodes.push(node.left);\n            nodes.push(node.right);\n            \n            //交换左右树\n            node.right = [node.left, node.left = node.right][0];\n    \n        }\n    }\n    \n    return root;\n};\n"
  },
  {
    "path": "leetcode/isomorphic-strings.js",
    "content": "/*\n* Question: 同构同形字符串\n\n* Given two strings s and t, determine if they are isomorphic.\n\n* Two strings are isomorphic if the characters in s can be replaced to get t.\n\n* All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.\n\n*For example,\n*Given \"egg\", \"add\", return true.\n\n*Given \"foo\", \"bar\", return false.\n\n*Given \"paper\", \"title\", return true.\n\n*Note:\n* You may assume both s and t have the same length.\n*/\n\n// 耗时：128ms\n/**\n * @param {string} s\n * @param {string} t\n * @return {boolean}\n */\nvar isIsomorphic = function(s, t) {\n    \n    var i = s.length - 1;\n    var sMap = {};\n    var tMap = {};\n   \n    for (; 0 <= i; i--) {\n        // 两个Hash表，一一交换对应，判断是否一致。\n       var source = sMap[t[i]];\n       var target = tMap[s[i]];\n        if (!source && !target){\n            sMap[t[i]] = s[i];\n            tMap[s[i]] = t[i];\n        } else if(source !== s[i] || target !== t[i]) {\n            return false;\n        }\n    }\n    \n    return true;\n};\n\n// C++最优版本 耗时： 8ms\nclass Solution {  \npublic:  \n    bool isIsomorphic(string s, string t) {  \n        int sTotTable[256];  \n        int tTosTable[256];  \n        int size = s.length();  \n        for (int i = 0; i < 256; i++)  \n        {  \n            sTotTable[i] = 300;  \n            tTosTable[i] = 300;  \n        }  \n  \n        for (int i = 0; i < size; i++)  \n        {  \n            if (sTotTable[s[i]] == 300)  \n            {  \n                if (tTosTable[t[i]] == 300)  \n                {  \n                    sTotTable[s[i]] = t[i];  \n                    tTosTable[t[i]] = s[i];  \n                }  \n                else  \n                {  \n                    return false;  \n                }  \n            }  \n            else if (sTotTable[s[i]] != t[i])  \n            {  \n                return false;  \n            }  \n        }  \n  \n        return true;  \n    }  \n};  \n"
  },
  {
    "path": "leetcode/merge-sorted-array.js",
    "content": "/**\n * 地址：https://leetcode.com/problems/merge-sorted-array/\n\n * Question：Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.\n\n * Note:\n * You may assume that nums1 has enough space (size that is greater or equal to m + n) \n * to hold additional elements from nums2. \n * The number of elements initialized in nums1 and nums2 are m and n respectively.\n * \n * /\n"
  },
  {
    "path": "leetcode/nim-game.md",
    "content": "### 题目:\nYou are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones.\n\nBoth of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap.\n\nFor example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend.\n\nHint:\n\nIf there are 5 stones in the heap, could you figure out a way to remove the stones such that you will always be the winner?\n"
  },
  {
    "path": "leetcode/recover-binary-search-tree.js",
    "content": "\n"
  },
  {
    "path": "leetcode/remove-duplicates-from-sorted-array.js",
    "content": "/**\n * Question:\n * Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.\n * Do not allocate extra space for another array, you must do this in place with constant memory.\n\n * For example,\n * Given input array nums = [1,1,2],\n\n * Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. \n * It doesn't matter what you leave beyond the new length.\n * \n */\n"
  },
  {
    "path": "leetcode/reverse-integer.js",
    "content": "\n"
  },
  {
    "path": "leetcode/roman-to-integer.js",
    "content": "/**\n *  Question:\n *    Given a roman numeral, convert it to an integer.\n *    Input is guaranteed to be within the range from 1 to 3999.\n *  Tag:\n *    Math, String\n * \n *    注： 将罗马数字转为阿拉伯数字 如 'XLV' == 45\n *  罗马数字规则：\n *    1. 重复数次：一个罗马数字重复几次，就表示这个数的几倍。\n *    2. 右加左减,较大的数的右边跟着较小的数，表示大数加小数，反之大减小。\n *        左减的数字有限制，仅限于I、X、C。比如45不可以写成VL，只能是XLV。(此处忽略)\n *        左减数字必须為一位，比如8写成VIII，而非IIX。 （此处忽略)\n * \n * /\n\n //遍历罗马数字，如果某个数比前一个数小，则加上该数。反之，减去前一个数的两倍然后加上该数\n \nvar romanToInt = function(s) {\n    var rToIMap = {\n        'I': 1,\n        'V': 5,\n        'X': 10,\n        'L': 50,\n        'C': 100,\n        'D': 500,\n        'M': 1000\n    }\n    var result = rToIMap[s[s.length-1]];\n    \n    for(var i=s.length-2; i>=0; i--)  {\n      var currNum = rToIMap[s[i]],\n          afterNum = rToIMap[s[i+1]];\n          \n        if (currNum >= afterNum) {\n          result += currNum;  \n        } else {  \n          result -= currNum; \n        }\n    } \n    \n    return result;\n};\n"
  },
  {
    "path": "note/arrays.md",
    "content": "### Binary search:\n\nStep:\n\n1. Find the mid index and set the low and high value;\n2. Compare the mid value and target one, \n\nif the mid value is greater than the target one ,than set the high value to mid -1;\nif no, set the low value to mid +1;\n\n### 数组去重\n\n> Hash中转\n\n\n"
  },
  {
    "path": "note/dynamic-programming.md",
    "content": "Introduction (Beginner)\nWhat is a dynamic programming, how can it be described? \n\nA 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. \n\nNow let's see the base of DP with the help of an example: \n\nGiven 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. \n\nNow let's start constructing a DP solution: \n\nFirst 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. \n\nWhat does a \"state\" stand for? \n\nIt'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 j<i. For finding a state i, we need to first find all smaller states j (j<i) . Having found the minimum number of coins which sum up to i, we can easily find the next state - the solution for i+1. \n\nHow can we find it? \n\nIt is simple - for each coin j, Vj≤i, look at the minimum number of coins found for the i-Vjsum (we have already found it previously). Let this number be m. If m+1 is less than the minimum number of coins already found forcurrent sum i, then we write the new result for it. \n\nFor a better understanding let's take this example:\nGiven coins with values 1, 3, and 5.\nAnd the sum S is set to be 11.\n\nFirst of all we mark that for state 0 (sum 0) we have found a solution with a minimum number of 0 coins. We then go to sum 1. First, we mark that we haven't yet found a solution for this one (a value of Infinity would be fine). Then we see that only coin 1 is less than or equal to the current sum. Analyzing it, we see that for sum 1-V1= 0 we have a solution with 0 coins. Because we add one coin to this solution, we'll have a solution with 1 coin for sum 1. It's the only solution yet found for this sum. We write (save) it. Then we proceed to the next state - sum 2. We again see that the only coin which is less or equal to this sum is the first coin, having a value of 1. The optimal solution found for sum (2-1) = 1 is coin 1. This coin 1 plus the first coin will sum up to 2, and thus make a sum of 2 with the help of only 2 coins. This is the best and only solution for sum 2. Now we proceed to sum 3. We now have 2 coins which are to be analyzed - first and second one, having values of 1 and 3. Let's see the first one. There exists a solution for sum 2 (3 - 1) and therefore we can construct from it a solution for sum 3 by adding the first coin to it. Because the best solution for sum 2 that we found has 2 coins, the new solution for sum 3 will have 3 coins. Now let's take the second coin with value equal to 3. The sum for which this coin needs to be added to make 3 , is 0. We know that sum 0 is made up of 0 coins. Thus we can make a sum of 3 with only one coin - 3. We see that it's better than the previous found solution for sum 3 , which was composed of 3 coins. We update it and mark it as having only 1 coin. The same we do for sum 4, and get a solution of 2 coins - 1+3. And so on. \n\nPseudocode: \n\nSet Min[i] equal to Infinity for all of i\nMin[0]=0\n\nFor i = 1 to S\nFor j = 0 to N - 1\n   If (Vj<=i AND Min[i-Vj]+1<Min[i])\n  Then Min[i]=Min[i-Vj]+1\n\n  Output Min[S]\n  Here are the solutions found for all sums: \n\n  Sum Min. nr. of coins Coin value added to a smaller sum to\n  obtain this sum (it is displayed in brackets)\n  0 0 -\n  1 1 1 (0)\n  2 2 1 (1)\n  3 1 3 (0)\n  4 2 1 (3)\n  5 1 5 (0)\n  6 2 3 (3)\n  7 3 1 (6)\n  8 2 3 (5)\n  9 3 1 (8)\n  10  2 5 (5)\n  11  3 1 (10)\n\n\n  As a result we have found a solution of 3 coins which sum up to 11. \n\n  Additionally, by tracking data about how we got to a certain sum from a previous one, we can find what coins were used in building it. For example: to sum 11 we got by adding the coin with value 1 to a sum of 10. To sum 10 we got from 5. To 5 - from 0. This way we find the coins used: 1, 5 and 5. \n\nFirst of all we mark that for state 0 (sum 0) we have found a solution with a minimum number of 0 coins. We then go to sum 1. First, we mark that we haven't yet found a solution for this one (a value of Infinity would be fine). Then we see that only coin 1 is less than or equal to the current sum. Analyzing it, we see that for sum 1-V1= 0 we have a solution with 0 coins. Because we add one coin to this solution, we'll have a solution with 1 coin for sum 1. It's the only solution yet found for this sum. We write (save) it. Then we proceed to the next state - sum 2. We again see that the only coin which is less or equal to this sum is the first coin, having a value of 1. The optimal solution found for sum (2-1) = 1 is coin 1. This coin 1 plus the first coin will sum up to 2, and thus make a sum of 2 with the help of only 2 coins. This is the best and only solution for sum 2. Now we proceed to sum 3. We now have 2 coins which are to be analyzed - first and second one, having values of 1 and 3. Let's see the first one. There exists a solution for sum 2 (3 - 1) and therefore we can construct from it a solution for sum 3 by adding the first coin to it. Because the best solution for sum 2 that we found has 2 coins, the new solution for sum 3 will have 3 coins. Now let's take the second coin with value equal to 3. The sum for which this coin needs to be added to make 3 , is 0. We know that sum 0 is made up of 0 coins. Thus we can make a sum of 3 with only one coin - 3. We see that it's better than the previous found solution for sum 3 , which was composed of 3 coins. We update it and mark it as having only 1 coin. The same we do for sum 4, and get a solution of 2 coins - 1+3. And so on.\n\nHaving understood the basic way a DP is used, we may now see a slightly different approach to it. It involves the change (update) of best solution yet found for a sum i, whenever a better solution for this sum was found. In this case the states aren't calculated consecutively. Let's consider the problem above. Start with having a solution of 0 coins for sum 0. Now let's try to add first coin (with value 1) to all sums already found. If the resulting sum t will be composed of fewer coins than the one previously found - we'll update the solution for it. Then we do the same thing for the second coin, third coin, and so on for the rest of them. For example, we first add coin 1 to sum 0 and get sum 1. Because we haven't yet found a possible way to make a sum of 1 - this is the best solution yet found, and we mark S[1]=1. By adding the same coin to sum 1, we'll get sum 2, thus making S[2]=2. And so on for the first coin. After the first coin is processed, take coin 2 (having a value of 3) and consecutively try to add it to each of the sums already found. Adding it to 0, a sum 3 made up of 1 coin will result. Till now, S[3] has been equal to 3, thus the new solution is better than the previously found one. We update it and mark S[3]=1. After adding the same coin to sum 1, we'll get a sum 4 composed of 2 coins. Previously we found a sum of 4 composed of 4 coins; having now found a better solution we update S[4] to 2. The same thing is done for next sums - each time a better solution is found, the results are updated. \n\nElementary\nTo this point, very simple examples have been discussed. Now let's see how to find a way for passing from one state to another, for harder problems. For that we will introduce a new term called recurrent relation, which makes a connection between a lower and a greater state. \n\nLet's see how it works: \n\nGiven a sequence of N numbers - A[1] , A[2] , ..., A[N] . Find the length of the longest non-decreasing sequence. \n\nAs described above we must first find how to define a \"state\" which represents a sub-problem and thus we have to find a solution for it. Note that in most cases the states rely on lower states and are independent from greater states. \n\nLet's define a state i as being the longest non-decreasing sequence which has its last number A[i] . This state carries only data about the length of this sequence. Note that for i<j the state i is independent from j, i.e. doesn't change when we calculate state j. Let's see now how these states are connected to each other. Having found the solutions for all states lower than i, we may now look for state i. At first we initialize it with a solution of 1, which consists only of the i-th number itself. Now for each j<i let's see if it's possible to pass from it to state i. This is possible only when A[j]≤A[i] , thus keeping (assuring) the sequence non-decreasing. So if S[j] (the solution found for state j) + 1 (number A[i] added to this sequence which ends with number A[j] ) is better than a solution found for i (ie. S[j]+1>S[i] ), we make S[i]=S[j]+1. This way we consecutively find the best solutions for each i, until last state N. \n\nLet's see what happens for a randomly generated sequence: 5, 3, 4, 8, 6, 7: \n\nI The length of the longest\nnon-decreasing sequence\nof first i numbers  The last sequence i from\nwhich we \"arrived\"\nto this one\n1 1 1 (first number itself)\n  2 1 2 (second number itself)\n  3 2 2\n  4 3 3\n  5 3 3\n  6 4 5\n\nPractice problem:\nGiven an undirected graph G having N (1<N<=1000) vertices and positive weights. Find the shortest path from vertex 1 to vertex N, or state that such path doesn't exist. \n\nHint: At each step, among the vertices which weren't yet checked and for which a path from vertex 1 was found, take the one which has the shortest path, from vertex 1 to it, yet found.\n\n\n\nIntermediate\nLet's see now how to tackle bi-dimensional DP problems. \n\nProblem:\nA table composed of N x M cells, each having a certain quantity of apples, is given. You start from the upper-left corner. At each step you can go down or right one cell. Find the maximum number of apples you can collect. \n\nThis problem is solved in the same way as other DP problems; there is almost no difference. \n\nFirst of all we have to find a state. The first thing that must be observed is that there are at most 2 ways we can come to a cell - from the left (if it's not situated on the first column) and from the top (if it's not situated on the most upper row). Thus to find the best solution for that cell, we have to have already found the best solutions for all of the cells from which we can arrive to the current cell. \n\nFrom above, a recurrent relation can be easily obtained:\nS[i][j]=A[i][j] + max(S[i-1][j], if i>0 ; 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). \n\nS[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. \n\nPseudocode:\nFor i = 0 to N - 1\n   For j = 0 to M - 1\n      S[i][j] = A[i][j] +\n            max(S[i][j-1], if j>0 ; S[i-1][j], if i>0 ; 0)\n\n            Output S[n-1][m-1]\n"
  },
  {
    "path": "note/graphs.md",
    "content": "\n- [图算法领域10大经典算法](http://www.cnblogs.com/v-July-v/archive/2011/02/14/1983678.html)\n"
  },
  {
    "path": "note/hashmap.md",
    "content": "[原理](http://www.importnew.com/16301.html)\n\n[Java函数](http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html)\n"
  },
  {
    "path": "note/listnode.md",
    "content": "\n"
  },
  {
    "path": "note/math.md",
    "content": "\n"
  },
  {
    "path": "note/n-queen.md",
    "content": "\n"
  },
  {
    "path": "note/string.md",
    "content": "\n"
  },
  {
    "path": "note/tree.md",
    "content": "\n"
  },
  {
    "path": "note.md",
    "content": "\n"
  },
  {
    "path": "questions/note.md",
    "content": "#### 反转单链表\n"
  },
  {
    "path": "single-linked-node.js",
    "content": "var SinglyLinkedList = function(){}\n\nSinglyLinkedList.prototype = {\n  addBottom: function(node) {\n    if (this.head == undefined) return this.head = node;\n    var currentNode = this.head;\n    while(currentNode.next !== undefined) {\n      currentNode = currentNode.next;\n    }\n    currentNode.next = node;\n  },\n\n  find: function(data) {\n    var currentNode = this.head;\n    while(currentNode !== undefined) {\n      if(currentNode.data == data) return currentNode;\n      currentNode = currentNode.next;\n    }\n  },\n\n  addTop: function(node) {\n    if (this.head == undefined) return this.head = node;\n    node.next = this.head;\n    this.head = node;\n  },\n\n  remove: function(data) {\n    if (this.head.data == data) return this.head = this.head.next;\n    var prevNode = this.head;\n    var currentNode = this.head.next;\n    while(currentNode !== undefined) {\n      if(currentNode.data == data) {\n        prevNode.next = currentNode.next;\n        return currentNode.next = undefined;\n      }\n      prevNode = currentNode;\n      currentNode = currentNode.next;\n    }\n  }\n}\n\nmodule.exports = SinglyLinkedList;\n"
  },
  {
    "path": "sites.md",
    "content": "[JS: Interview Algorithm](http://www.thatjsdude.com/interview/js1.html)\n"
  },
  {
    "path": "《数据结构与算法JavaScript描述》/习题/第三章/question1.js",
    "content": "/*\r\n *题目：\r\n *  增加一个向列表中插入元素的方法，\r\n *该方法只在待插入元素大于列表中的所有元素时才进行插入操作。\r\n *这里的大于有多重含义，对于数字，它是指数值上的大小；\r\n *对于字母，它是指在字母表中出现的先后顺序。\r\n *\r\n */\r\n\r\n//评注：该题出得有点语义不明，\r\n//对于数字字母混合的情况没有说明\r\n//故暂以都是字母或者数字为例\r\n\r\n\r\n/*\r\n* tools\r\n* a与b的大小比较，\r\n* 若a大于b则返回true\r\n*/\r\nfunction compareSequence(a, b){\r\n    \r\n    //如果是字符串的数字( \"11\" < \"2\" )的处理\r\n    var num1 = parseInt(a, 10),\r\n        num2 = parseInt(b, 10);\r\n    if (typeof(num1) === \"number\" && typeof(num2) === \"number\") {\r\n        if (num1 > num2) {\r\n            return true;\r\n        } else {\r\n            return false;\r\n        }\r\n    }\r\n\r\n    //字母的处理\r\n    if (a.toLowerCase() > b.toLowerCase()) {\r\n        return true;\r\n    } else {\r\n        return false;\r\n    }\r\n}\r\n\r\n\r\n//注这里需配合课本中实现的List列表类来解答\r\nfunction insertBiggest (element) {\r\n    for (var i=0; i < this.dataStore.length; i++) {\r\n\r\n        //需大于列表全部元素\r\n        if ( !compareSequence(element, this.dataStore[i]) ) {\r\n            return false;\r\n        }\r\n    }\r\n\r\n    this.append(element);\r\n    return true;\r\n}\r\n"
  },
  {
    "path": "《数据结构与算法JavaScript描述》/习题/第三章/question2.js",
    "content": "/*\r\n *题目：\r\n *  增加一个向列表中插入元素的方法，\r\n *该方法只在待插入元素小于列表中的所有元素时才进行插入操作。\r\n *\r\n */\r\n\r\n"
  },
  {
    "path": "《数据结构与算法JavaScript描述》/习题/第二章/question2.js",
    "content": "/*\r\n* 题目：将一组单词存储在一个数组中，并按正序和倒序分别显示这些单词\r\n*\r\n*/\r\nvar testArr = [\"this\", \"is\", \"a\", \"test\"],\r\n    testLen = testArr.length,\r\n    i = 0,\r\n    j = testLen - 1;\r\n\r\n// 正序\r\nfor (; i < testLen; i++ ) {\r\n    console.log(testArr[i]);\r\n}\r\n\r\n// 倒序\r\nfor (; j >= 0; j--) {\r\n    console.log(testArr[j])\r\n}\r\n"
  },
  {
    "path": "经典算法/bigNumberAdd.js",
    "content": "function bigNumberAdd(a,b){\n  function addZero(str, length) {\n    return new Array(length - str.length + 1).join(\"0\") + str;             \n  }\n \n  var c = '';\n  var temp = 0;\n  var aLength = a.length;\n  var bLength = b.length;\n  \n  if (aLength > bLength) {\n    b = addZero(b, aLength);\n  } else {\n    a = addZero(a, bLength);\n  }\n  var length = a.length;\n \n  for (var i = length - 1; i >= 0; i--) {\n    temp = parseInt(a.charAt(i)) + parseInt(b.charAt(i)) + parseInt(temp);\n    if (10 < temp) {\n        c = (temp - 10) + c;\n        temp = 1;\n    } else {\n        c = temp + c;\n        temp = 0;\n    }\n  }\n\n  return c;\n}\n"
  },
  {
    "path": "经典算法/knapsack-problem.js",
    "content": "//背包问题\n// https://en.wikipedia.org/wiki/Knapsack_problem\n// 解法参见http://www.importnew.com/13072.html\n"
  },
  {
    "path": "经典算法/shuffle.js",
    "content": "/**\n *  洗牌算法：\n *  1. 从第一张牌开始，将每张牌和随机的一张牌进行交换\n *  2. 更优解法：从第一张牌开始，将每张牌和之前全部牌中随机的一张进行交换\n *  3. C++ 标准库函数 std::random_shuffle (原理与第一点差不多)\n */\n\n//inspired by http://www.cs.princeton.edu/~rs/\nfunction shuffle(arr) {\n  var len = arr.length, i;\n  while (len) {\n    i = Math.random() * len-- | 0; // 0 ≤ i < n\n    arr[len] = [ arr[i], arr[i] = arr[len] ][0];\n  }\n  return arr;\n}\n\n"
  },
  {
    "path": "经典算法/sort.js",
    "content": "/**\n *几种排序算法\n *@TangGuichuan\n *\n */\n\n\n/**\n * @选择排序  http://en.wikipedia.org/wiki/Selection_sort\n *\n * 原理：在未排序的序列中找到最大（小）的元素与第1个元素交换，\n * 在剩余元素中继续找最大（小）的元素与第2个元素交换，\n * 以此类推，直到排序完毕\n */\n\nfunction selectionSort(arr){\n   var \n      i = arr.length - 1,\n      j,\n      buffer,\n      special; //最大或最小值的\u001c\u001c位置\n\n    // 采用倒序，提高查找性能\n    for (; i >= 0;  i--) {\n      special = i;\n      buffer = arr[i];\n\n      for (j = i - 1; j >= 0; j--) {\n\n        // 正序与倒序取决于这里的判断,max or min\n        if(buffer < arr[j]){\n          // 当前的最值位置\n          special = j;\n          buffer = arr[j];\n        }\n      }\n      // 最值与当前位置的值交换位置\n      arr[special] = [ arr[i], arr[i]=buffer ][0];\n    }\n\n    return arr;\n}\n\n\n/**\n *@冒泡排序  http://en.wikipedia.org/wiki/Bubble_sort\n *\n *原理：两两比较顺序,如果顺序错误则交换位置\n */\n\nfunction bubbleSort(arr){\n  var \n      i = arr.length - 1,\n      j;\n\n  for (; i >= 0; i--) {\n\n    for (j = i - 1; j >= 0; j--) {\n      if (arr[j] > arr[j+1]) {\n        arr[j] = [ arr[j+1], arr[j+1]=arr[j] ][0];\n      }\n    }\n\n  }\n\n  return arr;\n}\n\n\n/**\n *@插入排序 http://en.wikipedia.org/wiki/Insertion_sort\n *\n *原理：1.从第二位（当前元素）开始从后向前查找\n *      2.若新元素（当前元素的前面）大于当前元素，将新元素移到下一位置\n *      3.重复2，直到在有序区找到大于或等于新元素的位置\n *      4.将当前元素插到上面找到的位置\n *      5.重复2~4\n */\n\nfunction insertionSort(arr){\n    var \n        len = arr.length,\n        i = 1,\n        j,\n        buffer;\n\n    for (; i < len; i++) {\n        buffer = arr[i];\n\n        //在当前元素从后向前遍历,\n        //一旦找到比当前元素大的就进行“元素加位”\n        for (j = i - 1; j >= 0 && arr[j] > buffer; j--) {\n                arr[j+1] = arr[j];\n        }\n        //找到的位置替换为当前元素，比它大的在上面已经“加位”了\n        arr[j+1] = buffer;\n    }\n    \n    return arr;\n}\n\n/**\n * @二分插入排序\n * 用二分法对插入排序进行优化\n *\n */\n\nfunction binaryInsertSort(arr){\n\n}\n\n/**\n * @归并排序\n * \n * /\n\n"
  },
  {
    "path": "面试题-数组去重.js",
    "content": "// see http://www.cnblogs.com/mackxu/p/array-unique.html\n\n// for循环删除后面重复的 速度最快，可用倒序计算可加快速度\n\nvar uniqueFor = function(arr) {\n    for (var i = 0; i < arr.length - 1; i++) {\n        var item = arr[i];\n        for(var j = i+1; j < arr.length; j++ ) {\n            item === arr[j] && (arr.splice(j, 1), j--);\n        }\n    };\n    return arr;\n};\n\n\n//判断对象属性\n\nvar uniqueObject = function(arr) {\n    var v, r = [], o = {};\n    for(var i = 0; (v = arr[i]) !== undefined; i++) {\n        !o[v] && (r.push(v), o[v] = true);\n    }\n    return r;\n};\n\n\n//数组过滤重复项filter\n\nvar uniqueFilter = function(arr) {\n    return arr.filter(function(elem, pos, self) {\n        // 如果没有重复项，返回true\n        return self.indexOf(elem, pos + 1) === -1;\n    });\n};\n"
  }
]