Got stuck on quite simple problem in my code. I need to count what I would call a nested sums of an array. Let's take as an example the array:
[1,2,2,3,6]
I want to sum them as:
0 1 = 1
1 2 = 3
1 2 2 = 5
1 2 2 3 = 8
1 2 2 3 6 = 14
sum = 1 3 5 8 14 = 31
Edit: I tried to do it with stack, but it failed
int sums = 0;
Stack<int> sum = new Stack<int>();
for (int i = 0; i < queries.Length; i )
{
sum.Push(queries[i]);
}
for (int i = 0; sum.Count != 0; i )
{
if(i != 0)
{
sums = sum.Pop();
}
}
CodePudding user response:
You can run this task in a single loop considering when you have an array of size 5, the first element is repeating 5 times, second element repeating 4 times and etc.
int[] arr = { 1, 2, 2, 3, 6 };
int mysum = 0;
for (int i = 0; i < arr.Length; i )
mysum = (arr.Length - i) * arr[i];
Console.WriteLine(mysum);
Output:
31
Explanation:
1 = 1
1 2 = 3
1 2 2 = 5
1 2 2 3 = 8
1 2 2 3 6 = 14
========================
5*1 4*2 3*2 2*3 1*6 = 31
CodePudding user response:
You can do this much more efficiently and more easily, by multiplying each value by its reversed index 1
For example, using LINQ
int[] arr = { 1, 2, 2, 3, 6 };
var result = arr.Reverse().Select((val, i) => val * (i 1)).Sum();
Note that .Reverse
on an array (or other Collection<T>
) does not actually move any items, it just reads them backwards. So this is therefore an O(n) operation, as opposed to your original solution which is O(n2 / 2)
You can also do this procedurally, this is almost the same as @aminrd's answer.
int[] arr = { 1, 2, 2, 3, 6 };
var result = 0;
for (var i = arr.Length - 1; i >= 0; i--)
result = arr[i] * (i 1);
CodePudding user response:
Take advantage of Linq! .Sum()
will add up everything in your collection. You run that twice, once per each slice, and once per each subtotal.
var input = new [] { 1, 2, 2, 3, 6 };
var totalSum = Enumerable.Range(1, input.Length).Sum(len => input[0..len].Sum());
// totalSum is 31
Enumerable.Range
gets you a collection of numbers between (and including) 1 and 5 - the possible lengths of each slice of your sub arrays. You then use the range operator [0..#]
to get increasingly larger slices.
Yes, this is not as clever as aminrd's solution - it's doing all the computations manually and you're performing many slices.