Javascript 如何使此代码运行得更快

Javascript 如何使此代码运行得更快,javascript,binary-search-tree,avl-tree,Javascript,Binary Search Tree,Avl Tree,数组包含数字且未排序。它的长度可能高达100000米。 我需要数一数每个数字右边的较小数字 例如: 100, 10, 10, 10, 10]should return 4, 0, 0, 0, 0 1, 2, 3 should return 0, 0, 0 1, 2, 0 should return 1, 1, 0 1, 2, 1 should return 0, 1, 0 任务:我有1

数组包含数字且未排序。它的长度可能高达100000米。 我需要数一数每个数字右边的较小数字

例如:

    100, 10, 10, 10, 10]should return 4, 0, 0, 0, 0

    1, 2, 3             should return 0, 0, 0

    1, 2, 0             should return 1, 1, 0

    1, 2, 1             should return 0, 1, 0
任务:我有100个测试要执行,目标是在12毫秒内完成所有测试。 以下函数是一个AVL树实现。它完成了任务,但速度不够快

它在12秒内执行100次中的48次

===============

function smaller(arr) {
  function TreeNode(key) {
    this.key    = key;
    this.size   = 1;
    this.height = 1;
    this.left   = null;
    this.right  = null;
    this.count  = 1;
  }
  var size        = (node) => node == null ? 0 : node.size + node.count - 1;
  var height      = (node) => node == null ? 0 : node.height;
  var getBalance  = (node) => node == null ? 0 : height(node.left) - height(node.right);

  var rotateRight = function(root) {
    var newRoot      = root.left;
    var rightSubTree = newRoot.right;
    newRoot.right    = root;
    root.left        = rightSubTree;
    root.height      = Math.max(height(root.left), height(root.right)) + 1;
    newRoot.height   = Math.max(height(newRoot.left), height(newRoot.right)) + 1;
    root.size        = size(root.left) + size(root.right) + 1;
    newRoot.size     = size(newRoot.left) + size(newRoot.right) + 1;
    return newRoot;
  }
  var rotateLeft = function(root) {
    var newRoot     = root.right;
    var leftSubTree = newRoot.left;
    newRoot.left    = root;
    root.right      = leftSubTree;
    root.height     = Math.max(height(root.left), height(root.right)) + 1;
    newRoot.height  = Math.max(height(newRoot.left), height(newRoot.right)) + 1;
    root.size       = size(root.left) + size(root.right) + 1;
    newRoot.size    = size(newRoot.left) + size(newRoot.right) + 1;
    return newRoot;
  }
  var insertIntoAVL = function(node, key, count, index) {
    if(node == null)return new TreeNode(key);
    if(key  <  node.key){node.left    = insertIntoAVL(node.left, key, count, index);}
    if(key  == node.key){count[index] = count[index] + size(node.left); node.count++; return node;}
    if(key  >  node.key){node.right   = insertIntoAVL(node.right, key, count, index); count[index] = count[index] + size(node.left) + node.count;}
    node.height = Math.max(height(node.left), height(node.right)) + 1;
    node.size   = size(node.left) + size(node.right) + 1;
    var balance = getBalance(node);
    if(balance >  1 && key < node.left.key ){return rotateRight(node);}
    if(balance < -1 && key > node.right.key){return rotateLeft(node);}
    if(balance >  1 && key > node.left.key ){node.left = rotateLeft(node.left); return rotateRight(node);}
    if(balance < -1 && key < node.right.key){node.right = rotateRight(node.right); return rotateLeft(node);}
    return node;
  }
  var countSmallerOnRight = function( arr ) {
    var result = new Array(arr.length).fill(0);
    var root   = null;
    for (var i = arr.length; i--;){root = insertIntoAVL(root, arr[i], result, i);}
    return result;
  }
  return countSmallerOnRight(arr);
  }
=================

function smaller(arr) {
  function TreeNode(key) {
    this.key    = key;
    this.size   = 1;
    this.height = 1;
    this.left   = null;
    this.right  = null;
    this.count  = 1;
  }
  var size        = (node) => node == null ? 0 : node.size + node.count - 1;
  var height      = (node) => node == null ? 0 : node.height;
  var getBalance  = (node) => node == null ? 0 : height(node.left) - height(node.right);

  var rotateRight = function(root) {
    var newRoot      = root.left;
    var rightSubTree = newRoot.right;
    newRoot.right    = root;
    root.left        = rightSubTree;
    root.height      = Math.max(height(root.left), height(root.right)) + 1;
    newRoot.height   = Math.max(height(newRoot.left), height(newRoot.right)) + 1;
    root.size        = size(root.left) + size(root.right) + 1;
    newRoot.size     = size(newRoot.left) + size(newRoot.right) + 1;
    return newRoot;
  }
  var rotateLeft = function(root) {
    var newRoot     = root.right;
    var leftSubTree = newRoot.left;
    newRoot.left    = root;
    root.right      = leftSubTree;
    root.height     = Math.max(height(root.left), height(root.right)) + 1;
    newRoot.height  = Math.max(height(newRoot.left), height(newRoot.right)) + 1;
    root.size       = size(root.left) + size(root.right) + 1;
    newRoot.size    = size(newRoot.left) + size(newRoot.right) + 1;
    return newRoot;
  }
  var insertIntoAVL = function(node, key, count, index) {
    if(node == null)return new TreeNode(key);
    if(key  <  node.key){node.left    = insertIntoAVL(node.left, key, count, index);}
    if(key  == node.key){count[index] = count[index] + size(node.left); node.count++; return node;}
    if(key  >  node.key){node.right   = insertIntoAVL(node.right, key, count, index); count[index] = count[index] + size(node.left) + node.count;}
    node.height = Math.max(height(node.left), height(node.right)) + 1;
    node.size   = size(node.left) + size(node.right) + 1;
    var balance = getBalance(node);
    if(balance >  1 && key < node.left.key ){return rotateRight(node);}
    if(balance < -1 && key > node.right.key){return rotateLeft(node);}
    if(balance >  1 && key > node.left.key ){node.left = rotateLeft(node.left); return rotateRight(node);}
    if(balance < -1 && key < node.right.key){node.right = rotateRight(node.right); return rotateLeft(node);}
    return node;
  }
  var countSmallerOnRight = function( arr ) {
    var result = new Array(arr.length).fill(0);
    var root   = null;
    for (var i = arr.length; i--;){root = insertIntoAVL(root, arr[i], result, i);}
    return result;
  }
  return countSmallerOnRight(arr);
  }

我想了解他们为什么没有达到目标,以及我如何改进他们。

这很不错,但我不知道什么是代码战?挑战这是为了,所以我不能测试它。不使用树

function smaller(arr) {
    var out = [0];
    var len = arr.length;
    for (var i=len - 2; i >= 0; i--) {
      var c = 0;
      for (var j = i + 1; j < len; j++) {
        if (arr[i] == arr[j]) {
          c += out[j - i - 1];
          break;
        } else if (arr[i] > arr[j]) {
          c++;
        }
      }
      out.unshift(c);
    }
    return out;
}
var testArr = [1,5,2,7,44,878,1,22,999,222,1,1,1,1,1,1,1,1,1,1,1,1,1];
alert(smaller(testArr).join(","));

我可以不用树,只需一个简单的链表:

函数Nodevalue,下一步{ 这个值=值; this.next=next; 这个.count=1; } 函数小数组{ 返回array.reduceRightfunctionroot,值,i{ var计数=0; forvar prev=root,node;node=prev.next&&node.value+更小的[100,10,10,10,10,10]; console.log1,2,3->+更小的[1,2,3]; console.log1,2,0->+更小的[1,2,0]; console.log1,2,1->+更小的[1,2,1]; var sampleData=Array.from{length:100000},=>0 | Math.random*100; 10万件; 小山羊草;
console.timeEnd100000项 好的,我已经通过做一些重构来加速你的代码

function BSTNode(val) {
    this.dup   = 1;
    this.left  = null;
    this.right = null;
    this.val   = val;
    this.count = 0;
}

var insert = (root, num, result, sum, i) => {
    if (root === null) {
        result[i] = sum;
        return new BSTNode(num);
    }

    if (root.val === num) {
        root.dup++;
        result[i] = sum + root.count;
    } else if (root.val > num) {
        root.count++;
        root.left = insert(root.left, num, result, sum, i);
    } else {
        root.right = insert(root.right, num, result, sum + root.count + root.dup, i);
    }
    return root;
}

function smaller(arr) {
    var result = Array(arr.length).fill(0);
    var root   = null;
    for (var i = arr.length; i--;)
        root = insert(root, arr[i], result, 0, i);
    return result;
}
我很想知道,他们在计算这个函数时花了那么长时间。我们说的是在12秒内完成100次计算,而不是12毫秒。我猜大数组和很多不同的值要么是浮点数,要么是使用整个整数范围,而不仅仅是像8位:0。。。255


仍在尝试不同的方法。

这属于CodeReview,请在更快的计算机上运行。您需要比^2更快的速度。您可以在以下位置进行练习:非常感谢,我真的不认为做这么小的更改会有什么不同。从small中提取BSTNode并插入,这样就不会为small的每次调用创建新的类和函数,因此引擎可以优化一切,因为它们总是使用相同的类型。通过以适当的大小初始化结果数组,并用零填充它,引擎不必调整数组大小,也不必访问未定义的属性/索引,而且由于所有的值都是int,因此它可以在内部对其进行优化,因为数组速度更快,内存效率更高。