基础算法篇

数组、链表

/* 快排 */
function quickSort (arr) {
    if(arr.length <= 0) return arr;
    var temp = arr[0];
    var left = [];
    var right = [];
    for(var i = 1; i < arr.length; i++){
        if(compare(temp, arr[i])){
            left.push(arr[i]);
        }else{
            right.push(arr[i]);
        }
    }
    return quickSort(left).concat(temp, quickSort(right));
}
/* 链表逆置 */
function nizhi (root) {
    if(root.next.next == null){
        root.next.next = root;
        return root.next;
    }else{
        var result = nizhi(root.next);
        root.next.next = root;
        root.next = null;
        return result;
    }
}

二叉树

/* 二叉树的遍历(前序) */
function beforeOrder (root) {
    if(root == null) return;
    console.log(root.value);
    beforeOrder(root.left);
    beforeOrder(root.right);
}

/* 根据前序中序, 还原二叉树 */
function restoreTree1 (before, middle) {
    if(before == null || middle == null || before.length == 0 || middle.length == 0 || before.length != middle.length) return null;
    var root = new Node(before[0]);
    var index = middle.indexOf(root.value);
    var beforeLeft = before.slice(1, index + 1);
    var beforeRight = before.slice(index + 1);
    var middleLeft = middle.slice(0, index);
    var middleRight = middle.slice(index + 1);
    root.left = restoreTree1(beforeLeft, middleLeft);
    root.right = restoreTree1(beforeRight, middleRight);
    return root;
}
/* 二叉树深度优先搜索 */
function deepSearch (root, target) {
    if(root == null) return false;
    if(root.value == target) return true;
    var left = deepSearch(root.left, target);
    var right = deepSearch(root.right, target);
    return left || right;
}

/* 二叉树广度优先搜索 */
function scopeSearch (rootList, target) {
    if(rootList == null || rootList.length == 0) return false;
    var childList = [];
    for(var i = 0; i < rootList.length; i++){
        if(rootList[i] != null && rootList[i].value == target){
            return true;
        }else{
            childList.push(rootList[i].left);
            childList.push(rootList[i].right);
        }
    }
    return scopeSearch(childList, target);
}
/* 二叉树的比较: 不可互换子树的算法 */
function compareTree (root1, root2) {
    if(root1 == root2) return true;
    if(root1 == null && root2 != null || root1 != null && root2 == null) return false;
    if(root1.value != root2.value) return false;
    var left = compareTree(root1.left, root2.left);
    var right = compareTree(root1.right, root2.right);
    return left && right;
}
/* diff算法 */
function diffTree (root1, root2, diffList) {
    if(root1 == root2) return diffList;
    if(root1 == null && root2 != null){
        diffList.push({type: '新增', oldRoot: null, newRoot: root2});
    }else if(root1 != null && root2 == null){
        diffList.push({type: '删除', oldRoot: root1, newRoot: null});
    }else if(root1.value != root2.value){
        diffList.push({type: '修改', oldRoot: root1, newRoot: root2});
        diffTree(root1.left, root2.left, diffList);
        diffTree(root1.right, root2.right, diffList);
    }else{
        diffTree(root1.left, root2.left, diffList);
        diffTree(root1.right, root2.right, diffList);
    }
}
/* 创建二叉搜索树 */
function addNode (root, num) {
    if(root == null) return;
    if(root.value == num) return;
    if(root.value < num){
        if(root.right == null) root.right = new Node(num);
        else addNode(root.right, num);
    }else{
        if(root.left == null) root.left = new Node(num);
        else addNode(root.left, num);
    }
}
function buildSearchTree (arr) {
    if(arr == null || arr.length == 0) return null;
    var root = new Node(arr[0]);
    for(var i = 0; i < arr.length; i++){
        addNode(root, arr[i]);
    }
    return root;
}
/* 判断是否为平衡二叉树 */
function getDeep (root) {
    if(root == null) return 0;
    var leftDeep = getDeep(root.left);
    var rightDeep = getDeep(root.right);
    return Math.max(leftDeep, rightDeep) + 1;
}
function isBalance (root) {
    if(root == null) return true;
    var leftDeep = getDeep(root.left);
    var rightDeep = getDeep(root.right);
    if(Math.abs(leftDeep - rightDeep) > 1){
        return false;
    }else{
        return isBalance(root.left) && isBalance(root.right);
    }
}
/* 单旋双旋 */
function changeBalance (root) {
    if(isBalance(root)) return root;
    if(root.left != null) root.left = changeBalance(root.left);
    if(root.right != null) root.right = changeBalance(root.right);
    var leftDeep = getDeep(root.left);
    var rightDeep = getDeep(root.right);
    if(Math.abs(leftDeep - rightDeep) < 2){
        return root;
    }else if(leftDeep > rightDeep){
        var changeTreeDeep = getDeep(root.left.right);
        var noChangeTreeDeep = getDeep(root.left.left);
        if(changeTreeDeep > noChangeTreeDeep){
            root.left = leftRotate(root.left);
        }
        var newRoot = rightRotate(root);
        newRoot.right = changeBalance(newRoot.right);
        newRoot = changeBalance(newRoot);
        return newRoot;
    }else{
        var changeTreeDeep = getDeep(root.right.left);
        var noChangeTreeDeep = getDeep(root.right.right);
        if(changeTreeDeep > noChangeTreeDeep){
            root.right = rightRotate(root.right);
        }
        var newRoot = leftRotate(root);
        newRoot.left = changeBalance(root.left);
        newRoot = changeBalance(newRoot);
        return newRoot;
    }
}

树与图的搜索

/* 树的深度优先搜索 */
function deepSearch (root, target) {
    if(root == null) return false;
    if(root.value == target) return true;
    for(var i = 0; i < root.child.length; i++){
        if(deepSearch(root.child[i], target)) return true;
    }
    return false;
}
console.log(deepSearch(A, 'G'));

/* 树的广度优先搜索 */
function scopeSearch (roots, target) {
    if(roots == null || roots.length == 0) return false;
    var childList = [];
    for(var i = 0; i < roots.length; i++){
        if(roots[i] != null && roots[i].value == target) {
            return true;
        }else {
            childList = childList.concat(roots[i].child);
        }
    }
    return scopeSearch(childList, target);
}

/* 图的深度优先搜索 */
function deepSearch (root, target, path) {
    if(root == null) return false;
    if(path.indexOf(root) > -1) return;
    if(root.value == target) return true;
    path.push(root);
    for(var i = 0; i < root.neighbor.length; i++){
        if(deepSearch(root.neighbor[i], target, path)) return true;
    }
    return false;
}
// console.log(deepSearch(b, 'd', []));

/* 图的深度优先搜索 */
function scopeSearch (roots, target, path) {
    if(roots == null || roots.length == 0) return false;
    var neighborList = [];
    for(var i = 0; i < roots.length; i++){
        if(path.indexOf(roots[i]) > -1) continue;
        path.push(roots[i]);
        if(roots[i].value == target){
            return true;
        }else {
            neighborList = neighborList.concat(roots[i].neighbor);
        }
    }
    return scopeSearch(neighborList, target, path);
}

剑指offer

// 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
function Find(target, array){
    var lenX = array.length;
    var lenY = array[0].length;
    for(var i = 0, j = lenY - 1; i < lenX && j >= 0;){
        if(target > array[i][j]) i++;
        else if(target < array[i][j]) j--;
        else return true
    }
    return false;
}

// 青蛙变态跳台阶
function jumpFloorII(number){
    if(number == 1) return 1;
    else return 2 * jumpFloorII(number - 1);
}

// 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
function Power(base, exp){
	// 1. return Math.pow(base, exp);
	 if(base == 0){
	         if(exp >= 0) return 0;
	         else throw new Error('error');
	 }else{
	         if(exp == 0) return 1;
	         if(exp > 0) return power(base, exp);
	         else return 1 / power(base, -exp);
	 }
}
function power(base, exp){
	if(exp == 1) return base;
	if(exp % 2 == 0){
	        var res = power(base, exp/2);
	        return res * res;
	}else{
	        return power(base, exp-1) * base;
	}
}

// 输入一个链表,输出该链表中倒数第k个结点
function FindKthToTail(head, k){
        var stack = [];
        while(head){
                stack.push(head);
                head = head.next;
        }
        return stack[stack.length - k];
}

// 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则
function Merge(pHead1, pHead2){
        if(pHead1 == null || pHead2 == null) return pHead1 || pHead2;
        var root = null
        if(pHead1.val <= pHead2.val){
                root = pHead1;
                root.next = Merge(pHead1.next, pHead2);
        }else{
                root = pHead2;
                root.next = Merge(pHead1, pHead2.next);
        }
        return root;
}

// 输入两棵二叉树A,B,判断B是不是A的子结构
function HasSubtree(pRoot1, pRoot2){
    if(pRoot2 == null || pRoot1 == null) return false;
    return isSubtree(pRoot1,pRoot2)||
           HasSubtree(pRoot1.left,pRoot2) ||
           HasSubtree(pRoot1.right,pRoot2);
}
function isSubtree(pRoot1,pRoot2){
    if(pRoot2 == null) return true;
    if(pRoot1 == null) return false;
     if(pRoot1.val == pRoot2.val){
         return isSubtree(pRoot1.left,pRoot2.left) &&
                isSubtree(pRoot1.right,pRoot2.right);
     }else{
         return false;
     }
}

// 操作给定的二叉树,将其变换为源二叉树的镜像
function Mirror(root){
        if(root == null) return;
        var temp = root.left;
        root.left = root.right;
        root.right = temp;
        Mirror(root.left);
        Mirror(root.right);
}

// 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10
function printMatrix(matrix){
        var row = matrix.length;
        var col = matrix[0].length;
        var result = [];
        if(row == 0 || col == 0) return result;
        var left = 0, right = col - 1, top = 0, bottom = row - 1;
        while(left <= right && top <= bottom){
                for(var i = left; i <= right; i++){
                        result.push(matrix[top][i]);
                }
                for(var i = top + 1; i <= bottom; i++){
                        result.push(matrix[i][right]);
                }
                if(top != bottom){
                        for(var i = right - 1; i >= left; i--){
                                result.push(matrix[bottom][i]);
                        }
                }
                if(left != right){
                        for(var i = bottom - 1; i > top; i--){
                                result.push(matrix[i][left]);
                        }
                }
                left++;
                right--;
                top++;
                bottom--;
        }
        return result;
}

// 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
function VerifySquenceOfBST(sequence){
    if(!sequence.length) return false;
    return BST(sequence, 0, sequence.length - 1);
}
function BST (sequence, start, end) {
        if(start >= end) return true;
        var i = start;
        while(i < end && sequence[i++] < sequence[end]);
        for(var j = i; j < end; j++){
                if(sequence[j] < sequence[end]) return false;
        }
        return BST(sequence, start, i - 1) && BST(sequence, i, end - 1);
}

// 输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径
function FindPath(root, expectNumber){
        var result = [];
        if(root == null) return result;
        getPath(root, expectNumber, result, 0, []);
        return result;
}
function getPath(root, expectNum, result, curNum, path){
        if(root == null) return;
        curNum += root.val;
        path.push(root.val);
        if(curNum == expectNum && root.left == null && root.right == null){
                result.push(path.slice(0));
        }
        getPath(root.left, expectNum, result, curNum, path);
        getPath(root.right, expectNum, result, curNum, path);
        path.pop();
}

// 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向
function Convert(root){
    // write code here
    if(root == null) return;
    var head = null;
    var realHead = null;
    function getConvert(root){
        if(root == null) return null;
        getConvert(root.left);
        if(head == null){
            head = root;
            realHead = root;
        }else{
            head.right = root;
            root.left = head;
            head = root;
        }
        getConvert(root.right);
    }
    getConvert(root);
    return realHead;
}

// 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba
function Permutation(str){
    var len = str.length;
    var result = [];
    if(len == 0) {return [];}
    if(len == 1) {result.push(str);}
    else {
        var obj = {};
        for(var i = 0; i < len; i++){
            if(!obj[str[i]]){
                var temp = str[i];
                var newStr = str.substring(0,i) + str.substring(i+1);
                var ret = Permutation(newStr);
                for(var j = 0; j < ret.length; j++){
                    result.push(temp + ret[j]);
                }
                obj[str[i]] = true;
            }
       }
    }
    return result;
}

// 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0
function MoreThanHalfNum_Solution(numbers){
    var len = numbers.length;
    if(len == 0) return 0;
    var cache = {};
    numbers.forEach(function (val) {
        if(cache[val]){
            cache[val]++;
        }else{
            cache[val] = 1;
        }
    });
    for(var p in cache){
        if(cache[p] > Math.floor(len / 2)){
            return p;
        }
    }
    return 0;
}

// 例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)
function FindGreatestSumOfSubArray(array){
    if(array.length <= 0) return 0;
    var max = array[0];
    var res = array[0];
    for(var i = 1; i < array.length; i++){
        max = Math.max(max + array[i], array[i]);
        res = Math.max(max, res);
    }
    return res;
}

// 从1 到 n 中1出现的次数
function NumberOf1Between1AndN_Solution(n){
    if(n < 1) return 0;
    var count = 0, num;
    for(var i = 1; i <= n; i++){
        num = i;
        while(num > 0){
            if(num % 10 == 1) count++;
            num = Math.floor(num / 10);
        }
    }
    return count;
}

// 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323
function PrintMinNumber(numbers){
    var result = '';
    numbers.sort(function (a, b) {
        var str1 = '' + a + b;
        var str2 = '' + b + a;
        for(var i = 0; i < str1.length; i++){
            if(str1.charAt(i) > str2.charAt(i)){
                return 1;
            }
            if(str1.charAt(i) < str2.charAt(i)){
                return -1;
            }
        }
        return -1;
    });
    for(var i = 0; i < numbers.length; i++){
        result += numbers[i];
    }
    return result;
}

// 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数
function GetUglyNumber_Solution(index){
    if(index <= 0) return 0;
    var uglyNum = [1];
    var num2 = 0,
        num3 = 0,
        num5 = 0;
    for(var i = 1; i < index; i++){
        uglyNum[i] = Math.min(uglyNum[num2] * 2, uglyNum[num3] * 3, uglyNum[num5] * 5);
        if(uglyNum[i] == uglyNum[num2] * 2) num2++;
        if(uglyNum[i] == uglyNum[num3] * 3) num3++;
        if(uglyNum[i] == uglyNum[num5] * 5) num5++;
    }
    return uglyNum[index - 1];
}

// 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写)
function FirstNotRepeatingChar(str){
    for(var i = 0; i < str.length; i++){
        if(str.indexOf(str[i]) == str.lastIndexOf(str[i])){
            return i;
            break;
        }
    }
    return -1;
}

// 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
function InversePairs(data){
    if(!data || data.length < 2) return 0;
    var sum = 0;
    var copy = data.slice();
    sum = findReverse(data, copy, 0, data.length - 1);
    return (sum % 1000000007);
}

function findReverse(data, copy, start, end){
    if(start == end) return 0;
    var mid = parseInt((end - start) / 2);
    var left = findReverse(copy, data, start, start + mid);
    var right = findReverse(copy, data, start + mid + 1, end);
    var count = 0;
    var i = start + mid;
    var j = end;
    var index = end;
    while(i >= start && j >= start + mid + 1){
        if(data[i] > data[j]){
            count += j - start - mid;
            copy[index--] = data[i--];
             
        }else{
            copy[index--] = data[j--];
        }
    }
    while(i >= start){
        copy[index--] = data[i--];
    }
    while(j >= start + mid + 1){
        copy[index--] = data[j--];
    }
    return left + count + right;
}

// 输入两个链表,找出它们的第一个公共结点
function FindFirstCommonNode(pHead1, pHead2){
    var p1 = pHead1;
    var p2 = pHead2;
    while(p1 != p2){
        p1 = p1 == null ? pHead2 : p1.next;
        p2 = p2 == null ? pHead1 : p2.next;
    }
    return p1;
}

// 和为S的连续正数序列
function FindContinuousSequence(sum){
    if(sum < 2) return [];
    var result = [];
    var temp = [];
    var start = 1;
    var num = 0;
    var end = Math.ceil(sum / 2);
    while(start <= end){
        num += end;
        temp.unshift(end);
        if(num == sum){
            result.unshift(temp.slice());
            num = num - temp.pop();
        }
        else if(num > sum){
            num = num - temp.pop();
        }
        end--;
    }
    return result;
}

// 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的
function FindNumbersWithSum(array, sum){
    var result = [];
    var index;
    for(var i = 0; i < array.length - 1; i++){
        index = array.indexOf(sum - array[i], i + 1);
        if(index != -1) return [array[i], array[index]]
    }
    return result;
}

// 如果牌能组成顺子就输出true,否则就输出false
function IsContinuous(numbers){
    var len = numbers.length;
    if(len != 5) return false;
    var temp = [];
    for(var i = 0; i < 14; i++){
        temp.push(0);
    }
    var min = 14,
        max = -1;
    for(var i = 0; i < len; i++){
        temp[numbers[i]]++;
        if(numbers[i] == 0) continue;
        if(temp[numbers[i]] > 1) return false;
        if(numbers[i] > max) max = numbers[i];
        if(numbers[i] < min) min = numbers[i]; 
    }
    return max - min < 5
}

// 每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友
function LastRemaining_Solution(n, m){
    if(n < 1) return -1;
    if(n == 1) return 0;
    return (LastRemaining_Solution(n - 1, m) + m) % n;
}

// 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * ... * A[n-1],B[n-1] = A[0] * A[1] * ... * A[n-2];)
function multiply(array){
    if(array == null || array.length == 0) return [];
    var result = [];
    var tempArr, temp;
    for(var i = 0; i < array.length; i++){
        tempArr = array.filter(function (e, index) {
            return index != i;
        });
        temp = 1;
        tempArr.map(function (e, index) {
            temp *= e;
        });
        result[i] = temp;
    }
    return result;
}

// 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
function isNumeric(s){
    // +str -> 强制转为数字类型 返回NaN或数值
    // return !!+s;
    var reg = /[+-]?\d*(\.\d*)?([eE][+-]?\d+)?/g;
    return s.match(reg)[0] == s;
}

// 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
function EntryNodeOfLoop(pHead){
    if(pHead == null || pHead.next == null || pHead.next.next == null) return null;
    var p1 = pHead;
    var p2 = pHead;
    while(true){
        p1 = p1.next;
        p2 = p2.next.next;
        if(p1 == p2) break;
    }
    p1 = pHead;
    while(true){
        if(p1 == p2) return p1;
        else{
            p1 = p1.next;
            p2 = p2.next;
        }
    }
}

// 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
function deleteDuplication(pHead){
    var newHead = new ListNode('head');
    newHead.next = pHead;
    var pHead = newHead;
    var qHead = pHead.next;
    while(qHead){
        while((qHead.next != null) && (qHead.val == qHead.next.val)){
            qHead = qHead.next;
        }
        if(pHead.next == qHead){
            pHead = qHead;
            qHead = qHead.next;
        }
        else{
            qHead = qHead.next;
            pHead.next = qHead;
        }
    }
    return newHead.next;
}

// 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针
function GetNext(pNode){
    if (!pNode) return null;
    if (pNode.right) {
        pNode = pNode.right
        while(pNode.left){
            pNode = pNode.left
        }
    } else {
        while (pNode) {
            if (!pNode.next) return null;
            if (pNode.next.left === pNode) return pNode.next;
            pNode = pNode.next;
        }
    }
    return pNode;
}

// 请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
function isSymmetrical(pRoot){
    if(pRoot == null) return true;
    return getSymmetrical(pRoot.left, pRoot.right);
}
function getSymmetrical (rootLeft, rootRight){
    if(rootLeft == null) return rootRight == null;
    if(rootRight == null) return false;
    if(rootLeft.val != rootRight.val) return false;
    return getSymmetrical(rootLeft.left, rootRight.right) && getSymmetrical(rootLeft.right, rootRight.left);
}

// 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
function Print(pRoot){
    if(!pRoot) return [];
    var stack = [];
    var result = [];
    var flag = true;
    stack.push(pRoot);
    var len, tempArr;
    while(stack.length){
        len = stack.length;
        tempArr = [];
        for(var i = 0; i < len; i++){
            var temp = stack.shift();
            tempArr.push(temp.val);
            if(temp.left) stack.push(temp.left);
            if(temp.right) stack.push(temp.right);
        }
        if(!flag) tempArr.reverse();
        flag = !flag;
        result.push(tempArr);
    }
    return result;
}

// 给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4。 
function KthNode(root, k){
    if(k <= 0 || !root) return;
    var tempArr = [];
    getNode(root, tempArr);
    return tempArr[k - 1];
}
function getNode (root, res) {
    if(!root) return;
    getNode(root.left, res);
    res.push(root);
    getNode(root.right, res);
}

// 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
var arr = [];
function Insert(num)
{
    if(arr.length == 0) arr.push(num);
    else{
        var len = arr.length;
        while(len >= 0 && num < arr[len - 1]){
            arr[len] = arr[len - 1];
            len--;
        }
        arr[len] = num;
    }
}
function GetMedian(){
	var len = arr.length;
        odd = len % 2 == 1;
        index = Math.ceil(len / 2);
    if(odd){
        return arr[index - 1];
    }else{
        return (arr[index] + arr[index - 1]) / 2;
    }
}

// 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值
function maxInWindows(num, size){
    if(size <= 0) return [];
    var tempArr;
    var result = [];
    var start = 0;
    var end = num.length - size;
    for(var i = 0; i <= end; i++){
        tempArr = num.slice(i, i + size);
        result.push(Math.max(...tempArr));
    }
    return result;
}

// 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子
function hasPath(matrix, rows, cols, path){
    if(!rows || !cols || rows * cols < path.length) return false;
    for(var i = 0; i < rows; i++){
        for(var j = 0; j < cols; j++){
            if(getPath(matrix, i, j, rows, cols, path, 0, [])) return true;
        }
    }
    return false;
}
function getPath (matrix, i, j, rows, cols, path, k, flag){
    var index = i * cols + j;
    if(i < 0 || j < 0 || i >= rows || j >= cols || matrix[index] != path[k] || flag[index] == true) return false;
    if(k == path.length -1 ) return true;
    flag[index] = true;
    if(getPath(matrix, i - 1, j, rows, cols, path, k + 1, flag) ||
       getPath(matrix, i + 1, j, rows, cols, path, k + 1, flag) ||
       getPath(matrix, i, j - 1, rows, cols, path, k + 1, flag) ||
       getPath(matrix, i, j + 1, rows, cols, path, k + 1, flag)
      ) return true;
    flag[index] = false;
    return false;
}

// 地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
function movingCount(threshold, rows, cols){
    var flag = [];
    for(var i = 0; i < rows; i++){
        flag.push([]);
        for(var j = 0; j < cols; j++){
            flag[i][j] = false;
        }
    }
    return moveCount(threshold, rows, cols, 0, 0, flag);
}
function moveCount (threshold, rows, cols, i, j, flag) {
    if(i < 0 || j < 0 || i >= rows || j >= cols || flag[i][j] || sum(i, j) > threshold) return 0;
    flag[i][j] = true;
    return moveCount(threshold, rows, cols, i - 1, j, flag) +
           moveCount(threshold, rows, cols, i + 1, j, flag) +
           moveCount(threshold, rows, cols, i, j - 1, flag) +
           moveCount(threshold, rows, cols, i, j + 1, flag) + 1;
}
function sum(i, j) {
    var sum = 0;
    var temp = '' + i + j;
    for(var i = 0; i < temp.length; i++){
        sum += +(temp[i]);
    }
    return sum;
}

// 给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
function cutRope(number){
    var ans = [0, 0, 1, 2, 4];
    var result = [];
    if(number < 5) return ans[number];
    while(number > 0){
        if(number - 3 >= 0){
            result.push(3);
            number -= 3;
        }
        if(number - 2 >= 0){
            result.push(2);
            number -= 2;
        }
    }
    return result.reduce((m, n) => m * n);
}

总结难题

// 获取最长子序列问题 (分治法 + 动态规划)
function LCS2 (str1, str2) {
    var cache = [];
    var tempCache;
    function _lcs (str1, str2) {
        if(!str1 || !str2) return '';
        for(var i = 0; i < cache.length; i++){
            if(cache[i].str1 == str1 && cache[i].str2 == str2) return cache[i].result;
        }
        if(str1[0] == str2[0]){
            tempCache = str1[0] + _lcs(str1.substr(1), str2.substr(1));
        }else{
            var s1 = _lcs(str1, str2.substr(1));
            var s2 = _lcs(str1.substr(1), str2);
            tempCache = s1.length > s2.length ? s1 : s2;
        }
        cache.push({
            str1: str1,
            str2, str2,
            result: tempCache
        });
        return tempCache;
    }
    return _lcs(str1, str2);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值