How to display all included numbers in KnapSack problem? - c#

I have a problem with displaying used numbers. I'm using KnapSack algorithm and I want to display all numbers that I used to get highest value. So there is my code:
static int max(int a, int b)
{
int c = (a > b) ? a : b;
Console.WriteLine(c);
return (a > b) ? a : b;
}
// Returns the maximum value that can
// be put in a knapsack of capacity W
int knapSack(int[] r, int[] wt, int n, int W)
{
if (W < 0)
return Int32.MinValue;
if (n < 0 || W == 0)
return 0;
int include = r[n] + knapSack(r, wt, n, W - wt[n]);
int exclude = knapSack(r, wt, n - 1, W);
int V = max(include, exclude);
return V;
}
Use:
int[] r = new int[] { 3, 4, 8, 5, 6 };
int[] wt = new int[] { 2, 2, 3, 4, 7 };
int W = 11;
int z = W;
int n1 = r.Length;
stopwatch.Start();
int keik = knapSack(r, wt, n1 - 1, W);
stopwatch.Stop();
answer of this is 28, but I need to display all r numbers that was included in this. I know that for this array used numbers are 8 8 8 and 4, so I need somehow to get these numbers and display to the console.

You could try the approach of letting the function return the list of used items.
You could either return the item values themselves, or the indices of the values, depending on your needs. I used the values in this example.
Here is an implementation:
static int knapSack(int[] r, int[] wt, int n, int W, out List<int> list)
{
if (W < 0) {
list = new List<int>();
return Int32.MinValue;
}
if (n < 0 || W == 0) {
list = new List<int>();
return 0;
}
int include = r[n] + knapSack(r, wt, n, W - wt[n], out List<int> includedList);
int exclude = knapSack(r, wt, n - 1, W, out List<int> excludedList);
if (include > exclude) {
includedList.Add(r[n]);
list = includedList;
return include;
} else {
list = excludedList;
return exclude;
}
}
Call like this:
int keik = knapSack(r, wt, n1 - 1, W, out List<int> list);
Console.WriteLine(string.Join(",", list));
Output:
4,8,8,8

Related

Interpolation Search, finding the closest value

i am trying to use an Interpolation Search algorithm to find a value and return it. (Which is what it does currently). I am trying to modify it so it returns a number which i can use to find the closest values to the inputted item if the item which was searched was not found within the array.
public static int InterSearch(double[] array, double data)
{
int size = array.Length;
int lo = 0;
int mid = -1;
int hi = array.Length - 1;
int index = -1;
int count = 0;
while (lo <= hi)
{
mid = (int)(lo + (((double)(hi - lo) / (array[hi] - array[lo])) * (data - array[lo])));
count++;
if (array[mid] == data)
{
index = mid;
break;
}
else
{
if (array[mid] < data)
lo = mid + 1;
else
hi = mid - 1;
}
}
return index;
}
You can use an aggregate that find the closest value.
this is a custom extension method but you get the idea.
public static double GetValueClosestTo(this List<double> values, double closestTo)
{
return values.Aggregate((x, y) => Math.Abs(x - closestTo) < Math.Abs(y - closestTo) ? x : y);
}
Let's say you have the following array {1, 5, 9.2, 6, 17} and you test the following number {6, 15, 5.2}. You will use the following code
var sourceArray = new [] {1, 5, 9.2, 6, 17}.ToList() // for simplicity i use a list
var closestToX = sourceArray.GetValueClosestTo(6); // this return 6
closestToX = sourceArray.GetValueClosestTo(15); // this return 17
closestToX = sourceArray.GetValueClosestTo(5.2); // this return 5

Generate Gauss numbers

I have this problem with generating Gauss Numbers. The problem is like this :
This is what i coded so far
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SirurileLuiGauss
{
class Program
{
static int[] a = new int[100];
static int[] b = new int[100];
static List<int> list_a = new List<int>();
static List<int> list_b = new List<int>();
static int GaussA(int n)
{
if(n <= 0)
{
int a = 0;
list_a.Add(a);
return a;
}
else
{
int a = (GaussA(n - 1) + GaussB(n - 1))/2;
list_a.Add(a);
return a;
}
}
static int GaussB(int n)
{
if(n <= 0)
{
int b = 0;
list_b.Add(b);
return b;
}
else
{
int b = (int) Math.Sqrt(GaussA(n - 1) * GaussB(n - 1));
list_b.Add(b);
return b;
}
}
static void Main(string[] args)
{
int n = 5;
Console.WriteLine("GAUSS_111");
GaussA(n);
foreach (int element in list_a)
{
Console.WriteLine("GAUSS_A = "+element);
}
foreach (int element in list_b)
{
Console.WriteLine("GAUSS_B = " + element);
}
Console.WriteLine("\n\n");
// Clear the list
list_a = new List<int>();
list_b = new List<int>();
Console.WriteLine("GAUSS_222");
GaussB(n);
foreach (int element in list_a)
{
Console.WriteLine("GAUSS_A = " + element);
}
foreach (int element in list_b)
{
Console.WriteLine("GAUSS_B = " + element);
}
Console.Read();
}
}
}
And is totally wrong, gives me the output like 0 0 0 0 ...
What am i doing wrong?
Can i find this anywhere? Like a library or something?
I thing that the approach of this is by computing the integral and find out what is the peak/max_number of the array. Then try to iterate backwards to find all the numbers until we hit a > 0 and b > 0. The main problem is that you have to keep 2 arrays into memory, and that is hard ... Am i correct?
How do i compute that integral in C# ?
Why do you need epsilon for precision?
Thank you very much.
The problem starts as "let a0 = ... b0 = ..."; so you need a0 as well as b0
being input arguments. Another issue is that you don't need any array or list here
(imagine, that you're asked to find out a millionth itteration), dynamic programming
is a far better choice here:
// I let myselft return the result as Tupple<,>
public static Tuple<Double, Double> Gauss(Double a0, Double b0, int n) {
Double prior_a;
Double prior_b;
Double a = a0;
Double b = b0;
for (int i = 0; i < n; ++i) {
prior_a = a;
prior_b = b;
a = (prior_a + prior_b) / 2.0;
b = Math.Sqrt(prior_a * prior_b);
}
return new Tuple<Double, Double>(a, b);
}
Simple test: let a0 = 1; b0 = 5, so we have
Theory:
itt # a b
0 1 5
1 3 sqrt(5)
2 (3+sqrt(5))/2 sqrt(3*sqrt(5))
Actual:
Gauss(1, 5, 0); // returns (1, 5)
Gauss(1, 5, 1); // -/- (3, 2.23606797749979)
Gauss(1, 5, 2); // -/- (2.61803398874989, 2.59002006411135)
Gauss(1, 5, 3); // -/- (2.60402702643062, 2.60398935469938)
Gauss(1, 5, 10); // -/- (2.60400819053094, 2.60400819053094)
Gauss(1, 5, 100); // -/- (2.60400819053094, 2.60400819053094)
P.S. You can't compute (get, say, double value) an indefinite integral cause it equals F(x) + C where C is arbitrary constant; for definite integtral you may use Simpson algorithm

Rotating right an array of int in c#?

I've got an homework assignment:
need to implement a function (RotateRight) that gets an array of INT and a number:
int[] res = RotateRight(new int[] { 1, 2, 3, 4, 5, 6 }, 2);
//so then res will be {5,6,1,2,3,4}
and return the array after rotating all of the items to the right according to the number that been given, In our case 2.
And I have to do this efficiently in terms of memory space.
my best idea is:
if the number that been given is x, to use a new int[] tmpArray in the size of x to copy all the last x items to it. then with a for loop to shift all the rest of the int to the right.
And in the end to copy the items in the tmpArray to the begining of the original array.
Thanks in advance for any advice or help
You can use the beauty of the Linq langage to return an IEnumerable without dealing with array size:
/// <summary>
/// Get c = a mod (b) with c in [0, b[ like the mathematical definition
/// </summary>
public static int MathMod(int a, int b)
{
int c = ((a % b) + b) % b;
return c;
}
public static IEnumerable<T> ShiftRight<T>(IList<T> values, int shift)
{
for (int index = 0; index < values.Count; index++)
{
yield return values[MathMod(index - shift, values.Count)];
}
}
Usage :
[TestMethod]
public void TestMethod1()
{
var res = ShiftRight(new [] { 1, 2, 3, 4, 5, 6 }, 2).ToArray();
Assert.IsTrue(res.SequenceEqual(new[] { 5, 6, 1, 2, 3, 4 }));
}
Most memory possible makes no sense, you probably mean as little memory as possible? If so you should swap each item in the array using XOR, i.e:
var a = 2096;
var b = 842390;
a ^= b;
b ^= a;
a ^= b;
would swap these numbers.
EDIT
Code to do the whole thing in place:
public static void RotateRight(int[] input, int right)
{
for (var i = 0; i < right; i += 1)
{
RotateRightOne(input);
}
}
public static void RotateRightOne(int[] input)
{
var last = input.Length - 1;
for (var i = 0; i < last; i += 1)
{
input[i] ^= input[last];
input[last] ^= input[i];
input[i] ^= input[last];
}
}
Usage:
var arr = new[] {1, 2, 3, 4, 5, 6};
RotateRight(arr, 2);
As Servy points out, this is only for integers
Don't know C#, but here are two C++ versions, both in place, the first (rotate) does the minimum possible number of element moves by exploiting the cyclic structure of the rotation permutation, the second (rotate_k) just does 2*n moves for an array of length n. In both versions it's used that rotate right by k is the same as rotate left by n - k % n, so they in fact do the equivalent left rotation.
#include <iostream>
#include <vector>
#include <algorithm>
void
rotate (size_t k, std::vector<int> &a) {
size_t n = a.size();
k = n - k % n;
size_t m = n;
size_t i = 0;
while (m > 0) {
int t = a[i];
size_t j = i;
while (i != (j + k) % n) {
a[j] = a[(j + k) % n];
j = (j + k) % n;
--m;
}
a[j] = t;
--m;
++i;
}
}
void
rotate_k (size_t k, std::vector<int> &a) {
size_t n = a.size();
k = n - k % n;
std::reverse (a.begin(), a.end());
std::reverse (a.begin(), a.begin() + n - k);
std::reverse (a.begin() + n - k, a.end());
}
int
main () {
std::vector<int> a = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
rotate (12, a);
for (auto i : a)
std::cout << i << " ";
std::cout << std::endl;
}
You just need to figure out the final index for each element after rotating it k times rather than actually rotating it k times.
This worked for me:
for(int i=0;i<a.Length;i++){
rotated[(k+i)%(a.Length)]=a[i];
}
Here's a quick sample on rotating an array A right K steps:
var splitPoint=A.Length-(K%A.Length);
var result=new int[A.Length];
int idx=0;
for(var pos=0;pos<A.Length;pos++)
{
if(pos<A.Length-splitPoint)
{
result[pos]=A[splitPoint+pos];
}
else
{
result[pos]=A[idx];
idx++;
}
}
return result;
C# 8 now has Indices and Ranges
Rotate Right...
int[] r = t[1..].Concat(t[0..1]).ToArray();
Rotate Left...
int[] r = t[^1..^0].Concat(t[..^1]).ToArray();
in place of the "1" above, a variable can also be used: int[] r = t[amt..].Concat(t[0..amt]).ToArray();

Recursion in place of multiple nested for loops?

Im having some issues with trying to update a nested for loop to use recursion instead. Is it possible to access the a,b and c variables from the earlier for loops when using recursion? Below is a simple example of what im trying to convert into a recursive call.
for(int a= 0; a < 10; a++)
{
for(int b = 0; b < 20; b++)
{
for(int c = 0; c < 10; c++)
{
int[] indexes = new int[3]{a,b,c}
collection.add(indexes);
}
}
}
EDIT: The solution needs to be able to be adjusted at runtime, such that a user can select how many levels are required.
Here's a recursive solution (using a functional programming style):
public static IEnumerable<IEnumerable<int>> GetCombinations(IEnumerable<int> limits)
{
if (limits.Any() == false)
{
// Base case.
yield return Enumerable.Empty<int>();
}
else
{
int first = limits.First();
IEnumerable<int> remaining = limits.Skip(1);
IEnumerable<IEnumerable<int>> tails = GetCombinations(remaining);
for (int i = 0; i < first; ++i)
foreach (IEnumerable<int> tail in tails)
yield return Yield(i).Concat(tail);
}
}
// Per http://stackoverflow.com/q/1577822
public static IEnumerable<T> Yield<T>(T item)
{
yield return item;
}
Sample use:
var sequences = GetCombinations(new [] { 5, 3, 2, 4 /* ... */ });
foreach (var sequence in sequences)
Console.WriteLine(string.Join(", ", sequence));
/* Output:
0, 0, 0, 0
0, 0, 0, 1
0, 0, 0, 2
0, 0, 0, 3
0, 0, 1, 0
0, 0, 1, 1
0, 0, 1, 2
0, 0, 1, 3
0, 1, 0, 0
0, 1, 0, 1
0, 1, 0, 2
... */
For OP's specific scenario (adding arrays to collection):
var sequences = GetCombinations(new [] { 10, 20, 10 });
collection.AddRange(sequences.Select(s => s.ToArray()));
Ok, try with this
static void AddToCollectionRecursive(
List<int[]> collection,
params int[] counts)
{
AddTo(collection, new List<int>(), counts, counts.Length - 1);
}
static void AddTo(
List<int[]> collection,
IEnumerable<int> value,
IEnumerable<int> counts,
int left)
{
for (var i = 0; i < counts.First(); i++)
{
var list = value.ToList();
list.Add(i);
if (left == 0)
{
collection.Add(list.ToArray());
}
else
{
AddTo(collection, list, counts.Skip(1), left - 1);
}
}
}
Usage is like this AddToCollectionRecursive(collection, 10, 20, 10);.
something like this will work:
public void CreateIndexes(int a, int b, int c, Collection collection)
{
if(c == 10) {b++; c = 0;}
if(b == 20) {a++; b = 0;}
if(a == 10) return;
int[] indexes = new int[3]{a,b,c}
collection.add(indexes);
c++;
CreateIndexes(a, b, c, collection);
}
Off the top of my head, i.e. not tested, something like this might work:
List<int[]> collection = new List<int[]>();
private void AddValues(int a, int b, int c)
{
collection.Add(new[] { a, b, c });
if (c < 10)
{
c++;
AddValues(a, b, c);
}
if (b < 20)
{
b++;
c = 0;
AddValues(a, b, c);
}
if (a < 10)
{
a++;
b = 0;
c = 0;
AddValues(a, b, c);
}
}
Start it by calling:
AddValues(0, 0, 0);
Well, i think that if u resolve this problem using recursion, it will consume more memory and other resources!
But there is my suggestion:
private void FunctionName(int a, int b, int c, List<int[]> list)
{
if (a<10)
{
if (b<20)
{
if (c<10)
{
list.Add(new[] { a, b, c });
c++;
FunctionName(a,b,c,list);
}
else
{
c=0;
b++;
FunctionName(a,b,c,list);
}
}
else
{
b=0;
a++;
FunctionName(a,b,c,list);
}
}
}
You call like this : FunctionName(0,0,0,list).
Hope it works! ^^
This solution takes an Action for the work to be done at the leafs:
void ForEachCombo(int from, int to, int nrLevels, Action<int[]> action)
{
int[] d = new int[nrLevels];
InnerFor(from, to, 0);
void InnerFor(int from, int to, int level)
{
if (level == nrLevels)
action(d);
else
for (d[level] = from; d[level] <= to - nrLevels + level + 1; d[level]++)
InnerFor(d[level] + 1, to, level + 1);
}
}
Use like this:
ForEachCombo(0, 9, 3, (d) =>
{
Console.WriteLine(string.Join(", ", d));
});
// Output
0, 1, 2
0, 1, 3
0, 1, 4
0, 1, 5
...
6, 7, 9
6, 8, 9
7, 8, 9
//
If you want to you can save a level of recursion by writing like this:
void ForEachCombo(int from, int to, int nrLevels, Action<int[]> action)
{
int[] d = new int[nrLevels];
InnerFor(from, to, 0);
void InnerFor(int from, int to, int level)
{
if (level == nrLevels - 1)
for (d[level] = from; d[level] <= to - nrLevels + level + 1; d[level]++)
action(d);
else
for (d[level] = from; d[level] <= to - nrLevels + level + 1; d[level]++)
InnerFor(d[level] + 1, to, level + 1);
}
}

Given an array of integers. Find the LARGEST subarray with the MAXIMUM sum

Hi I am preparing for an interview code test and I stumbled across this question. I tried attempting it in C#, below is my embarrasing answer which I don't even know if it's right but mostly I guess not, could someone please kindly provide me with the answer so that when I rework on the solution I can at least have the answer to verify the output. Thanks.
Sample data:
int[] arr = {5, 1, -7, 3, 7};
Code:
int[] LargestsubarrayMaxSum(int[] arr)
{
int temp = 0;
int[] resultArr = new int[arr.Length];
for (int i = 0; i < arr.Length - 1; i++)
{
if (i != 0)
{
foreach (int item in resultArr)
{
temp += item;
}
if (temp + arr[i + 1] > 0)
{
resultArr[i + 1] = temp + arr[i + 1];
}
}
else
{
if ((arr[i] + arr[i + 1]) >= 0)
{
resultArr[i] = arr[i];
resultArr[i + 1] = arr[i] + arr[i + 1];
}
else
{
resultArr[i] = arr[i];
resultArr[i + 1] = 0;
}
}
}
return resultArr;
}
How about this?
var arr = new [] {5, 1, -7, 3, 7};
var xs =
from n in Enumerable.Range(0, arr.Length)
from l in Enumerable.Range(1, arr.Length - n)
let subseq = arr.Skip(n).Take(l)
orderby subseq.Count() descending
orderby subseq.Sum() descending
select subseq;
var maxSumSubseq = xs.First();
EDIT: Added orderby subseq.Count() descending to get maximal length subsequence.
EDIT: Added explanation as per comment.
Select all possible subsequence starting indices:
from n in Enumerable.Range(0, arr.Length)
Select all possible lengths of subsequences given the starting index:
from l in Enumerable.Range(1, arr.Length - n)
Extract the subsequence from the array:
let subseq = arr.Skip(n).Take(l)
Order subsequences by descending length (i.e. longest first) - could order by l instead of subseq.Count() but the latter is more expressive even though the former is more efficient:
orderby subseq.Count() descending
Calculate the sum of each subsequence and order the subsequences so highest valued sums are first:
orderby subseq.Sum() descending
Select the subsequences:
select subseq;
Only select the first subsequence - it's the highest value sum with the greatest length:
xs.First();
Hope this helps.
O(N) time complexity and O(1) space complexity. This is the optimal solution I know:
#include <stdio.h>
#include <limits.h>
int get_max_sum(int* array, int len, int* start, int* end)
{
int max_sum = INT_MIN, sum = 0, i;
int tmp_start = 0;
for(i = 0; i != len; ++i)
{
sum += array[i];
// if the sum is equal, choose the one with more elements
if(sum > max_sum || (sum == max_sum && (end - start) < (i - tmp_start)))
{
max_sum = sum;
*start = tmp_start;
*end = i;
}
if(sum < 0)
{
sum = 0;
tmp_start = i + 1;
}
}
return max_sum;
}
Here are some test cases:
int main(int argc, char **argv)
{
int arr1[] = {5, 1, -7, 3, 7};
int arr2[] = {1};
int arr3[] = {-1, -7, -3, -7};
int arr4[] = {5, 1, -7, 2, 2, 2};
int start, end, sum;
sum = get_max_sum(arr1, 5, &start, &end);
printf("sum: %d, start: %d, end: %d\n", sum, start, end);
sum = get_max_sum(arr2, 1, &start, &end);
printf("sum: %d, start: %d, end: %d\n", sum, start, end);
sum = get_max_sum(arr3, 4, &start, &end);
printf("sum: %d, start: %d, end: %d\n", sum, start, end);
sum = get_max_sum(arr4, 6, &start, &end);
printf("sum: %d, start: %d, end: %d\n", sum, start, end);
return 0;
}
$ ./a.out
sum: 10, start: 3, end: 4
sum: 1, start: 0, end: 0
sum: -1, start: 0, end: 0
sum: 6, start: 3, end: 5
Update1:
Added code to print the index of the subarray.
Update2:
If two sub arrays with the same sum are found, choose the one with more elements.
Update3:
Fix the algorithm for leading negative numbers
You could either use Enigmativity's answer but add the extra order by of subseq.Count() descending
or if you want an insane linq query......
int[] arr = .......
var result = new[]{0}
.Concat(arr.Select((x,i)=>new {x,i})
.Where(a=>a.x<0).Select(a=>a.i+1))
.Select (i => arr.Skip(i).TakeWhile(a => a>=0))
.OrderByDescending(a=>a.Sum())
.OrderByDescending(a=>a.Count()).First();
However usually you want to do these as a single loop..
var result=new List<int>();
var maxResult=new List<int>();
// These next four variables could be calculated on the fly
// but this way prevents reiterating the list each loop.
var count=0;
var sum=0;
var maxCount=0;
var maxSum=0;
foreach (var value in arr) {
if (value >=0) {
result.Add(value);
sum+=value;
count++;
} else {
if (sum>maxSum || (sum==maxSum && count>maxCount)) {
maxSum=sum;
maxCount=count;
maxResult=result;
}
result.Clear();
count=0;
sum=0;
}
}
var returnValue=maxResult.ToArray();
public static int[] FindMaxArrayEx(int[] srcArray)
{
int[] maxArray = new int[1];
int maxTotal = int.MinValue;
int curIndex = 0;
int tmpTotal = 0;
List<int> tmpArray = new List<int>();
if (srcArray.Length != 1)
{
for (int i = 0; i < srcArray.Length; i++)
{
tmpTotal = 0;
curIndex = i;
tmpArray.Clear();
while (curIndex < srcArray.Length)
{
tmpTotal += srcArray[curIndex];
tmpArray.Add(srcArray[curIndex]);
if (tmpTotal > maxTotal)
{
maxTotal = tmpTotal;
maxArray = tmpArray.ToArray();
}
curIndex++;
}
}
}
else
{
maxTotal = srcArray[0];
maxArray = srcArray;
}
Console.WriteLine("FindMaxArrayEx: {0}",maxTotal);
return maxArray;
}
Here is a totally working solution:
using System;
using System.Collections.Generic;
class MaxSumOfSubArray
{
static void Main()
{
//int[] array = { 2, 3, -6, -1, 2, -1, 6, 4, -8, 8 };
//maxSubSum(array);
int digits;
List<int> array = new List<int>();
Console.WriteLine("Please enter array of integer values. To exit, enter eny key different than 0..9");
while (int.TryParse(Console.ReadLine(), out digits))
{
array.Add(digits);
}
maxSubSum(array);
}
public static void maxSubSum(List<int> arr)
{
int maxSum = 0;
int currentSum = 0;
int i = 0;
int j = 0;
int seqStart=0;
int seqEnd=0;
while (j < arr.Count)
{
currentSum = currentSum + arr[j];
if (currentSum > maxSum)
{
maxSum = currentSum;
seqStart = i;
seqEnd = j;
}
else if (currentSum < 0)
{
i = j + 1;
currentSum = 0;
}
j++;
}
Console.Write("The sequence of maximal sum in given array is: {");
for (int seq = seqStart; seq <= seqEnd; seq++)
{
Console.Write(arr[seq] + " ");
}
Console.WriteLine("\b}");
Console.WriteLine("The maximum sum of subarray is: {0}", maxSum);
}
}
/// <summary>
/// given an non-empty input array of integers, this method returns the largest contiguous sum
/// </summary>
/// <param name="inputArray">the non-empty input array of integeres</param>
/// <returns>int, the largest contiguous sum</returns>
/// <remarks>time complexity O(n)</remarks>
static int GetLargestContiguousSum(int[] inputArray)
{
//find length of the string, if empty throw an exception
if (inputArray.Length == 0)
throw new ArgumentException("the input parameter cannot be an empty array");
int maxSum = 0;
int currentSum = 0;
maxSum = currentSum = inputArray[0];
for (int i = 1; i < inputArray.Length; i++) //skip i=0 as currentSum=inputArray[0].
{
currentSum = Math.Max(currentSum + inputArray[i], inputArray[i]);
maxSum = Math.Max(currentSum, maxSum);
}
return maxSum;
}
/*--This was the algorithum I found on Wiki to calculate sum, however to get the actual subarray
* I really had to think. After spending few hours I was able to solve it using startIndex and
* endIndex int variables and then by adding a if clause if (max_ending_here == array[i])
{ startIndex = i; }
* dang this was very tough. I hope you all will refactor as needed to make some improvements.*/
/* Initialize:
max_so_far = 0
max_ending_here = 0
Loop for each element of the array
(a) max_ending_here = max_ending_here + a[i]
(b) if(max_ending_here < 0)
max_ending_here = 0
(c) if(max_so_far < max_ending_here)
max_so_far = max_ending_here
return max_so_far*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
int[] array = { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
int[] largestSubArray;
largestSubArray = Max_Array(array);
Console.WriteLine();
Console.WriteLine("Subarray is :");
foreach (int numb in largestSubArray)
Console.WriteLine(numb);
Console.ReadKey();
}
//Max_Array function will calculate the largest contigent array
//sum and then find out startIndex and endIndex of sub array
//within for loop.Using this startIndex and endIndex new subarray
//is created with the name of largestSubArray and values are copied
//from original array.
public static int[] Max_Array(int[] array)
{
int[] largestSubArray;
int max_so_far = 0, max_ending_here = 0, startIndex = 0,
endIndex = 0;
for (int i = 0, j = 0; i < array.Length; i++)
{
max_ending_here += array[i];
if (max_ending_here <= 0)
{
max_ending_here = 0;
}
if (max_ending_here == array[i])
{ startIndex = i; }
if (max_so_far < max_ending_here)
{
max_so_far = max_ending_here;
endIndex = i;
}
}
Console.WriteLine("Largest sum is: {0}", max_so_far);
largestSubArray = new int[(endIndex - startIndex) + 1];
Array.Copy(array, startIndex, largestSubArray, 0, (endIndex - startIndex) + 1);
return largestSubArray;
}
}
}
Output
Largest sum is: 6
'Subarray is:
4,
-1,
2,
1'
It's not that complicated once you go over it. I thought about it going backwards at first, that helped for some reason.
If all numbers are positive (or 0), the entire array would be the largest subarray with max sum.
Now, we can take this fact and apply it over positive or negative arrays and instead say that we want to include all subarrays that are positive (or 0).
Start at the end and sum as you go left. When you find a negative number, you think, did that negative number make the rest of my sums worthless? if not, you keep going.. but you also mark that point right there as the current max sum (if it's greater than the last current max sum).
If they are worthless, (ie sum is now less than 0), you know that everything to the right of your index is now worthless. You still keep your current max sum in case thats the highest though.
start from 3 with your new index. Keep track of the indexes for your current max sum and end.
The SubArray with Maximum Sum in an Array is the Array without the Minimum most element element. So sort it. and remove the minimum element. thats it.
Thats applicable if Its Only Positive Integer Array. Otherwise the subarray of Positive elements only is the answer
below code working for me :
static void Main(string[] args)
{
string str = Console.ReadLine();
int [] arr = Array.ConvertAll(str.Split(' '),int.Parse);
int curSum = 0, maxSum = 0;
curSum = maxSum = arr[0];
for (int i = 1; i < arr.Length; i++)
{
curSum = Math.Max(curSum + arr[i], arr[i]);
maxSum = Math.Max(curSum, maxSum);
}
Console.WriteLine("{0}", maxSum);
Console.ReadKey();
}
Input : -2 1 -3 4 -1 2 1 -5 4
O/P: 6

Categories

Resources