有没有一种方法可以改进此代码,以避免大型数组超时?

时间:2019-03-22 19:04:38

标签: javascript algorithm sorting

我正在处理以下问题:https://www.hackerrank.com/challenges/fraudulent-activity-notifications/

我的代码几乎可以正常工作,但是对于某些测试用例,由于数组很大(超过200000项),它失败了。我花了数小时试图了解如何提高速度,但是我无法给出一个可行的解决方案,因此我的2个测试始终因超时而失败,因此尝试通过此测试感到沮丧。 我认为我无法避免第一个循环以及排序循环,但是无法想到一种更快的方法。

网站中描述的问题是这样的:

HackerLand国家银行有一个简单的政策,用于警告客户可能存在欺诈性帐户活动。如果客户在特定日期花费的金额连续几天都大于或等于客户的中位数支出,则他们会向客户发送有关潜在欺诈的通知。除非客户至少拥有前几天的交易数据尾数,否则银行不会向客户发送任何通知。

我用这段代码解决了

function getMedianNumber(arr) {
  arr.sort((a, b) => a - b);

  let medianNumber = 0;
  const middle = Math.floor(arr.length / 2);

  if (arr.length % 2 === 0) {
    // Is even we get the median number
    medianNumber = (arr[middle] + arr[middle - 1]) / 2;
  } else {
    const index = Math.floor(middle);
    medianNumber = arr[index];
  }

  return medianNumber;
}

function activityNotifications(expenditure, d) {
  let notifications = 0;
  let len = expenditure.length - 1;

  for (let i = len; i > d - 1; i--) {
    let trailingDays = expenditure.slice(i - d, i);
    let dayExpense = expenditure[i];
    let median = getMedianNumber(trailingDays);

    if (expenditure[i] >= median * 2) {
      notifications++;
    }
  }

  return notifications;
}

它仅在2个测试用例中失败,因为传递的数组很大,并且我收到超时错误。

2 个答案:

答案 0 :(得分:0)

expenditure.slice(i - d, i);太昂贵了,您通过在每次迭代中复制数组元素来使其变为O(n ^ 2)。使用原始数组上的索引来计算中位数:getMedianNumber(arr, startIndex, endIndex)

答案 1 :(得分:0)

function copy(a, ind) {
    b = [];
    for(var i = ind; i < a.length; ++i) {
        b.push(a[i]);
    }
    return b;
}
function processData(input) {
    //Enter your code here
    var inputArr = input.split("\n");
    var d = parseInt(inputArr[0].split(" ")[1]);
    var arr = inputArr[1].split(" ").map(Number);
    var countArray = [], sortedArray = [], tempArray = [], notifications = 0, median, count, middle;
    for(var i = 0; i <= 200; ++i) {
        countArray.push(0);
    }
    for(i = 0; i < d; ++i) {
        countArray[arr[i]]++;
    }
    for(var j = 0; i < arr.length; ++i, ++j) {
        tempArray = [], count = 0;
        for(var k = 0; k <= 200; ++k) {
            if(countArray[k] > 0) {
                count += countArray[k];
                tempArray.push({
                    no: k,
                    count: count
                });
            }
        }
        middle = {};
        if((d&1) === 0) {
            middle.index = count / 2;
        } else {
            middle.index = Math.ceil(count / 2);
        }
        var tempCount = 0;
        for(k = 0; k < tempArray.length; ++k) {
            if(tempArray[k].count === middle.index) {
                if((d&1) === 0) {
                    median = (tempArray[k].no + tempArray[k + 1].no) / 2;
                    break;
                } else {
                    median = tempArray[k].no;
                    break;
                }
            } else if(tempArray[k].count > middle.index) {
                median = tempArray[k].no;
                break;
            }
        }

        //console.log(tempArray, median, arr[i]);
        if(arr[i] >= (2 * median)) {
            notifications++;
        }
        countArray[arr[i]]++;
        countArray[arr[j]]--;
    }
    console.log(notifications);
} 

process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function (input) {
    _input += input;
});

process.stdin.on("end", function () {
   processData(_input);
});
相关问题