沃森给了夏洛克一个长度为N的阵列A.然后他问他 确定数组中是否存在元素的总和 左边的元素等于其元素的总和 对。如果左/右没有元素,则总和为 被认为是零。正式地,找到一个,这样,输入格式
第一行包含T,即测试用例的数量。对于每个测试 case,第一行包含N,即数组中的元素数 答:每个测试用例的第二行包含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);
});
答案 0 :(得分:2)
循环数组一次以找到总和。声明两个变量:sumLeft和sumRight。 sumLeft的初始值应为0,sumRight应为totalSum-arr [0]。
再次遍历数组并通过(n-1)元素递增sumLeft并将sumRight递减第n个元素。继续比较这两个变量,检查它们是否相等。你将时间复杂度降低到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);
});
答案 1 :(得分:1)
你可以使用两个指针(索引)从内向两端穿过数组。保持平衡,从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>
答案 2 :(得分:0)
鉴于我们有一个合适的数组,可以按如下方式执行
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));
当然,对于上面随机填充的数组,我们不能总是得到一个完美的中间索引。