Есть ли способ улучшить этот код, чтобы избежать тайм-аута с большими массивами? - PullRequest
2 голосов
/ 22 марта 2019

Я работаю с этой проблемой: 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 голосов
/ 22 марта 2019
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);
});
0 голосов
/ 22 марта 2019

expenditure.slice(i - d, i); слишком дорого, вы делаете это O (n ^ 2), копируя элементы массива за каждую итерацию.Используйте индексы для исходного массива для вычисления медианы: getMedianNumber(arr, startIndex, endIndex).

...