【发布时间】:2019-03-22 19:04:37
【问题描述】:
我正在解决这个问题:https://www.hackerrank.com/challenges/fraudulent-activity-notifications/
我的代码几乎可以正常工作,但对于某些测试用例,它会失败,因为数组很大(超过 200000 个项目)。我花了几个小时试图了解我可以做些什么来提高速度,但我无法提出一个可行的解决方案,所以我的 2 个测试总是因超时而失败,我对通过这个测试感到沮丧。 我想我无法避免第一个循环以及排序中的循环,但想不出更快的方法。
网站描述的问题是这样的:
HackerLand National Bank 制定了一项简单的政策来警告客户可能存在的欺诈性帐户活动。如果客户在某一天的消费金额大于或等于客户过去几天的平均支出,他们会向客户发送有关潜在欺诈的通知。银行不会向客户发送任何通知,直到他们至少拥有前几天的交易数据。
我用这段代码解决了它
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 个测试用例中失败,因为传递的数组很大,我收到超时错误。
【问题讨论】:
-
计算中位数类似于计算滚动和的方式。见en.wikipedia.org/wiki/Moving_average
-
@berig:你能做到吗?三思而后行。
-
你可以做一个滚动中位数,但它比滚动总和更棘手:stackoverflow.com/a/5970314/10396.
-
@YvesDaoust 是的。当然,添加到窗口,从窗口中删除并计算新的中位数并不像
+、-和id那样简单,但它是可行的。即使你这样做效率相对较低,例如使用窗口的排序数组,这仍然比像 OP 目前正在做的那样对自己的每个切片进行排序要好得多。 -
@Bergi:我想强调的是,不可能像滚动总和那样在恒定时间内实现滚动中位数。不过,恒定时间滚动最小值是可能的。
标签: javascript algorithm sorting