繁体   English   中英

javascript hackerranks sherlock and array performance issue

[英]javascript hackerranks sherlock and array performance issue

Watson给Sherlock一个长度为N的数组A。然后,他要求他确定数组中是否存在一个元素,以使左边的元素之和等于右边的元素之和。 如果左右没有元素,则总和为零。 正式地找到一个i

输入格式

第一行包含T,即测试用例的数量。 对于每个测试用例,第一行包含N,即数组A中的元素数。每个测试用例的第二行包含N个以空格分隔的整数,表示数组A。

约束

 1<=T<=10 1<=N<=10^5 1<=Ai<=2*10^4 1<=i<=N 

输出格式

对于每个测试用例,如果数组中存在一个元素,则打印YES,以便其左侧的元素之和等于其右侧的元素之和。 否则打印NO。

样本输入

 2 3 1 2 3 4 1 2 3 3 

样本输出

 NO YES 

说明

对于第一个测试用例,不存在这样的索引。 对于第二个测试用例,

因此索引3满足给定条件。

我有3个测试用例存在超时问题

 function check(input) {
    var result = "NO";
    var sum=0;
    input.map(function(data){
        sum=sum+(+data);
    })
    sumLeft=0;
    sumRight=sum-(+input[0]);

    for(var i=1;i<input.length;i++){
        sumLeft=sumLeft+(+input[i-1]);
        sumRight=sumRight-(+input[i])
        if(sumLeft==sumRight)
        {
            console.log("YES");
            return;
        }
    }
    console.log("NO");
}

function processData(input) {
    //Enter your code here
    var lines = input.split("\r\n");
    for (var m = 2; m < lines.length; m = m + 2) {
        check(lines[m].split(" "));
    }
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function(input) {
    _input += input;
});
process.stdin.on("end", function() {
    processData(_input);
});

循环遍历一次数组即可找到总和。 声明两个变量:sumLeft和sumRight。 sumLeft的初始值应为0,sumRight的值应为totalSum-arr [0]。

再次遍历数组,并通过(n-1)元素使sumLeft递增,并通过第n个元素将sumRight递减。 继续比较两个变量以检查它们是否彼此相等。 您将时间复杂度降低到O(n)

以下代码在https://www.hackerrank.com/challenges/sherlock-and-array上通过了测试。 棘手的部分是设置数组长度为1时的默认响应。我将承认@trincot的答案对于仅包含正整数的数组更有效(n而不是2n)。

 function check(input) {
    var result = "NO";
    var sum=0;

     if(input.length == 1){
        console.log("YES");
        return;
     }

    input.map(function(data){
        sum=sum+(+data);
    })
    sumLeft=0;
    sumRight=sum-(+input[0]);

    for(var i=1;i<input.length-1;i++){
        sumLeft=sumLeft+(+input[i-1]);
        sumRight=sumRight-(+input[i])
        if(sumLeft==sumRight)
        {
            console.log("YES");
            return;
        }else if (sumLeft>sumRight) {  ///worked both with and without this optimization
            console.log("NO"); 
            return;
        }
    }
    console.log("NO");
}



function processData(input) {

    //var lines = input.split("\r\n");
    var lines = input.split(/\r|\n/)
    for (var m = 2; m < lines.length; m = m + 2) {
        check(lines[m].split(" "));
    }
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function(input) {
    _input += input;
});
process.stdin.on("end", function() {
    processData(_input);
});

您可以使用两个指针(索引)从两端向内遍历数组。 从0开始保持平衡,如下所示:

当余额为负数时,将左指针向右移动一步,同时增加余额并保留您留下的值。 当余额为正时,将右指针向左移动一步,同时用剩下的值减少余额。

当两个指针相遇时,请检查天平。 如果为零,那么您就成功了。

这是ES6代码中的算法,以及一个文本区域,您可以在其中根据所需的输入格式来调整输入:

 function hasMiddle(a) { var balance = 0, i = 0, j = a.length-1; while (i < j) balance += balance > 0 ? -a[j--] : a[i++]; return !balance; } // I/O: event handling, parsing input, formatting output var input = document.querySelector('textarea'); var output = document.querySelector('pre'); input.oninput = function() { var lines = this.value.trim().split(/[\\r\\n]+/).filter(s => s.trim().length); // Strip the case count and array element counts: lines = lines.slice(1).filter( (s, i) => i % 2 ); // Call function for each test case, returning array of booleans: var results = lines.map( line => hasMiddle(line.match(/\\d+/g).map(Number)) ); // Output results output.textContent = results.map( pos => pos ? 'YES' : 'NO' ).join('\\n'); } // Evaluate input immediately input.oninput(); 
 Input:<br> <textarea style="width:100%; height:120px">2 3 1 2 3 4 1 2 3 3 </textarea> <pre></pre> 

此算法要求您的输入数组由非负数组成。

如果需要在数组中支持负数,则算法需要先遍历数组以计算总和,然后再次遍历数组以找到余额达到0的点:

 function hasMiddle(a) { var balance = a.reduce( (sum, v) => sum + v ); return !a.every ( (v, i) => balance -= v + (i ? a[i-1] : 0) ); } // I/O for snippet var input = document.querySelector('textarea'); var output = document.querySelector('pre'); input.oninput = function() { var lines = this.value.trim().split(/[\\r\\n]+/).filter(s => s.trim().length); // Strip the case count and array element counts: lines = lines.slice(1).filter( (s, i) => i % 2 ); // Call function for each test case, returning array of booleans: var results = lines.map( line => hasMiddle(line.match(/[\\d-]+/g).map(Number))); // Output results output.textContent = results.map( pos => pos ? 'YES' : 'NO' ).join('\\n'); } // Evaluate input immediately input.oninput(); 
 Input:<br> <textarea style="width:100%; height:120px">2 3 1 2 3 4 1 2 3 3 </textarea> <pre></pre> 

假设我们有一个适当的数组,则可以执行以下操作

 var arr = [...Array(35)].map(_ => ~~(Math.random()*10)+1), sum = arr.reduce((p,c) => p+c), half = Math.floor(sum/2), ix; console.log(JSON.stringify(arr)); midix = arr.reduce((p,c,i,a) => { (p+=c) < half ? p : !ix && (ix = i); return i < a.length - 1 ? p : ix; },0); console.log("best possible item in the middle @ index", midix,": with value:",arr[midix]); console.log("sums around midix:", arr.slice(0,midix) .reduce((p,c) => p+c), ":", arr.slice(midix+1) .reduce((p,c) => p+c)); 

当然,对于上述随机填充的数组,我们不能总是获得理想的中间索引。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM