简体   繁体   English

javascript hackerranks sherlock and array performance issue

[英]javascript hackerranks sherlock and array performance issue

Watson gives Sherlock an array A of length N. Then he asks him to determine if there exists an element in the array such that the sum of the elements on its left is equal to the sum of the elements on its right. Watson给Sherlock一个长度为N的数组A。然后,他要求他确定数组中是否存在一个元素,以使左边的元素之和等于右边的元素之和。 If there are no elements to the left/right, then the sum is considered to be zero. 如果左右没有元素,则总和为零。 Formally, find an i, such that, 正式地找到一个i

Input Format 输入格式

The first line contains T, the number of test cases. 第一行包含T,即测试用例的数量。 For each test case, the first line contains N, the number of elements in the array A. The second line for each test case contains N space-separated integers, denoting the array A. 对于每个测试用例,第一行包含N,即数组A中的元素数。每个测试用例的第二行包含N个以空格分隔的整数,表示数组A。

Constraints 约束

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

Output Format 输出格式

For each test case print YES if there exists an element in the array, such that the sum of the elements on its left is equal to the sum of the elements on its right; 对于每个测试用例,如果数组中存在一个元素,则打印YES,以便其左侧的元素之和等于其右侧的元素之和。 otherwise print NO. 否则打印NO。

Sample Input 样本输入

 2 3 1 2 3 4 1 2 3 3 

Sample Output 样本输出

 NO YES 

Explanation 说明

For the first test case, no such index exists. 对于第一个测试用例,不存在这样的索引。 For the second test case, 对于第二个测试用例,

therefore index 3 satisfies the given conditions. 因此索引3满足给定条件。

I'm having timeout issues on 3 of the test cases 我有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);
});

Loop over the array once to find the sum. 循环遍历一次数组即可找到总和。 Declare two variables: sumLeft and sumRight. 声明两个变量:sumLeft和sumRight。 sumLeft should have an initial value of 0 and sumRight should be totalSum-arr[0]. sumLeft的初始值应为0,sumRight的值应为totalSum-arr [0]。

Iterate over the array again and increment sumLeft by the (n-1) element and decrement sumRight by the nth element. 再次遍历数组,并通过(n-1)元素使sumLeft递增,并通过第n个元素将sumRight递减。 Keep comparing the two variables to check if they equal each other. 继续比较两个变量以检查它们是否彼此相等。 You cut your time complexity down to O(n) 您将时间复杂度降低到O(n)

The below code passed the test on https://www.hackerrank.com/challenges/sherlock-and-array . 以下代码在https://www.hackerrank.com/challenges/sherlock-and-array上通过了测试。 The tricky part was setting up default responses for when the array length was 1. I will admit that @trincot 's answer was more efficient (n as opposed to 2n) for arrays containing only positive integers. 棘手的部分是设置数组长度为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);
});

You could go through the array from both ends in inwards direction using two pointers (indices). 您可以使用两个指针(索引)从两端向内遍历数组。 Keep a balance, starting with 0, as follows: 从0开始保持平衡,如下所示:

When the balance is negative move the left pointer one step to the right while increasing the balance with the value you leave behind. 当余额为负数时,将左指针向右移动一步,同时增加余额并保留您留下的值。 When the balance is positive, move the right pointer one step to the left while decreasing the balance with the value you leave behind. 当余额为正时,将右指针向左移动一步,同时用剩下的值减少余额。

When the two pointers meet each other, check the balance. 当两个指针相遇时,请检查天平。 If it is zero, you have success. 如果为零,那么您就成功了。

Here is the algorithm in ES6 code, together with a text area where you can adapt the input according to the required input format: 这是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> 

This algorithm requires your input array to consist of non-negative numbers. 此算法要求您的输入数组由非负数组成。

If you need to support negative numbers in your array, then the algorithm needs to go through the array first to calculate the sum, and then go through the array again to find the point where the balance reaches 0: 如果需要在数组中支持负数,则算法需要先遍历数组以计算总和,然后再次遍历数组以找到余额达到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> 

Given that we have a proper array one might do as follows 假设我们有一个适当的数组,则可以执行以下操作

 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)); 

Of course for randomly populated arrays as above, we can not always get a perfect middle index. 当然,对于上述随机填充的数组,我们不能总是获得理想的中间索引。

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

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