Reputation: 157
so I'm currently trying to do this scenario: Given a non-empty array, return true if there is a place to split the array so that the sum of the numbers on one side is equal to the sum of the numbers on the other side. Examples:
canBalance([1, 1, 1, 2, 1]) → true
canBalance([2, 1, 1, 2, 1]) → false
canBalance([10, 10]) → true
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Array_Split
{
class Program
{
public static bool Balance(int[] data)
{
int lpoint = 0;
int rpoint = data.Length - 1;
int ltotal = data[lpoint];
int rtotal = data[rpoint];
while (lpoint < rpoint)
{
if (ltotal == rtotal)
{
lpoint++;
rpoint--;
ltotal = ltotal + data[lpoint];
rtotal = rtotal + data[rpoint];
}
else if (ltotal < rtotal)
{
lpoint++;
ltotal = ltotal + data[lpoint];
}
else
{
rpoint--;
rtotal = rtotal + data[rpoint];
}
}
if (ltotal == rtotal)
{
return true;
}
else
{
return false;
}
}
public static void Main(string[] args)
{
int[] data2 = new int[] { 1, 1, 1, 2, 1 }; // T
int[] data3 = new int[] { 2, 1, 1, 2, 1 }; // F
int[] data4 = new int[] { 10, 10 }; // T
Console.WriteLine(Balance(data2));
Console.WriteLine(Balance(data3));
Console.WriteLine(Balance(data4));
Console.ReadKey();
}
}
}
The expected result should be true, false, true. However, it gives out false, true, true
Upvotes: 2
Views: 92
Reputation: 5131
A similar solution: But could offer some benefits:
var sum = balance.ToList().Sum();
if (sum % 2 == 0)
{
var left = 0;
for (int i = 0; left < sum / 2; i++)
{
left+=balance[i];
}
return (left - (sum - left) == 0);
}
return false;
Since in order for a list to be even, it must also have a modulus result of 0, you can save time by skipping those that are obviously not equal on each side.
Sum(5,4,9) % 2 = 0
Sum(5,5,9) % 2 = 1
etc.
And then the code is different, but the algorithm is similar to make certain the left and right match.
Upvotes: 0
Reputation: 20249
When the two values are equal, don't change both lpoint
and rpoint
. Consider what happens in {1,2,1}
- they would both try to "claim" the value 2 at index 1, and you would incorrectly return true for that array. So instead, just change lpoint
(or rpoint
--just not both):
if (ltotal == rtotal)
{
lpoint++;
ltotal = ltotal + data[lpoint];
}
else if ...
Because you're doing the same as whenltotal < rtotal
, you can combine it with that block by checking ltotal <= rtotal
:
if (ltotal <= rtotal)
{
lpoint++;
ltotal = ltotal + data[lpoint];
}
else
{
rpoint--;
rtotal = rtotal + data[rpoint];
}
Also, you shouldn't wait for lpoint
to equal rpoint
to end your loop - that means both sides need to claim some center index/value, which is against the rules. Instead, stop your loop when the points are adjacent:
while (lpoint + 1 < rpoint)
Upvotes: 3
Reputation: 33738
I gave this a shot just for fun.
using System;
using System.Linq;
using System.Collections.Generic;
namespace SO_58400592_array_split {
class Program {
private static List<int[]> _testCases = new List<int[]>() {
{new int[] {1,1,1,2,1}},
{new int[] {2,1,1,2,1}},
{new int[] {10,10}}
};
static void Main(string[] args) {
for (int index = 0; index < _testCases.Count; index++) {
Console.WriteLine(CanSplitArray(_testCases[index]));
}
}
static bool CanSplitArray(int[] model) {
// special case of 2 elements
if(2 == model.Length) {
return model[0] == model[1];
}
// sum the model
int sum = model.Sum();
// caculate the value from each end
int leftSum = 0;
int rightSum = sum;
// start at the first index and end at the penultimate index.
for (int index = 1; index < model.Length - 1; index++) {
leftSum += model[index - 1];
rightSum -= model[index - 1];
if (leftSum == rightSum) {
return true;
}
}
return false;
} // CanSplitArray()
} // Program
} // ns
Upvotes: 1