Related
I want to make a function that gives an array returns the nearest element to a number.
here is some examples:
int[] arr = new int[] {12, 48, 50, 100};
my_function(1, arr); // returns 12.
my_function(40, arr); // returns 48.
my_function(49, arr); // returns 50; in two element with equal distance, returns greater number
my_function(70, arr); // returns 50.
my_function(10005, arr); // returns 100.
Sorry, I have no idea about how to write this function.
private int GetNearest(int[] array,int number)
{
return array.OrderBy(x => Math.Abs((long)x - number)).FirstOrDefault();
}
If you want to be sure that the larger number is before smaller number when the absolute difference is the same, add .ThenByDescending(a => a) after OrderBy(x => Math.Abs((long)x - number))
private int GetNearest(int[] array,int number)
{
return array.OrderBy(x => Math.Abs((long)x - number)).ThenByDescending(a => a).FirstOrDefault();
}
A different way to get the result expected is to calculate the distance between the value passed and the array elements. Then get the element with the lowest 'distance' and find the matching index in the input array. You need Linq as well here.
int Nearest(int value, int[] arr)
{
var distances = arr.Select(x => Math.Abs(x - value)).ToList();
int min = distances.Min();
// Using LastIndexOf is important
// if you get two equal distances (I.E. 48/50 and passing 49)
return arr[distances.LastIndexOf(min)];
}
This is a solution without using System.Linq and with O(n) complexity. You just go through array in loop and find a number with minimal difference, abs <= diff condition allows you to return the latest number (50 for 49 instead of 48) in sorted array. If difference equals 0, it means that you find the exact number
var arr = new[] { 12, 48, 50, 100 };
int nearest = GetNearest(1, arr);
nearest = GetNearest(40, arr);
nearest = GetNearest(49, arr);
nearest = GetNearest(70, arr);
nearest = GetNearest(1005, arr);
int GetNearest(int number, int[] array)
{
int diff = int.MaxValue;
int result = 0;
foreach (var item in array)
{
var abs = Math.Abs(item - number);
if (abs == 0)
{
result = item;
break;
}
if (abs <= diff)
{
diff = abs;
result = item;
}
}
return result;
}
This works:
public static int my_function(int num, int[] arr)
{
var minDiff = Math.Abs(arr[0] - num);
var nearest = arr[0];
for (int i = 1; i < arr.Length; i++)
{
var diff = Math.Abs(arr[i] - num);
if (diff <= minDiff)
{
minDiff = diff;
nearest = arr[i];
}
}
return nearest;
}
If you know that the array is sorted then you can find the closest value like this in O(log n) time.
public int GetNearest(int value, int[] sortedArray)
{
var index = Array.BinarySearch(sortedArray, value);
// If we found a match then the closest is equal to the value.
if(index >= 0) return value;
// Otherwise it's the bitwise compliment to the index of the value just larger.
var largerIndex = ~index;
// If the index is the length of the array then all numbers are smaller,
//so take the last.
if(largerIndex == sortedArray.Length) return sortedArray[arr.Length - 1];
// If the index is 0 then all numbers are greater so take the first.
if(largerIndex == 0) return sortedArray[0];
// Now get the number that is just larger and just smaller and calculate the
// difference to each.
var larger = sortedArray[largerIndex];
var smaller = sortedArray[largerIndex - 1];
var largerDiff = larger - value;
var smallerDiff = value - smaller;
// If the diff to the smaller number is less then we take the smaller number
// otherwise the larger number is closer or the difference is the same in which
// case we take the larger number.
return smallerDiff < largerDiff ? smaller : larger;
}
I have approached it this way.
private static int nearest(int number, int[] numbers)
{
int min = numbers[0];
int max = numbers.OrderByDescending(a => a).FirstOrDefault();
if (number> max)
{
return max;
}
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i]<number && numbers[i+1]>number)
{
int lower = Math.Abs(numbers[i])-Math.Abs(number);
int upper = Math.Abs(numbers[i+1]) - Math.Abs(number);
if (Math.Abs(upper)>Math.Abs(lower))
{
return numbers[i];
}
else
{
return numbers[i+1];
}
}
}
return min;
}
First i want to say i'm still learning so my programming skills are not very good, and i'm willing to accept any advice you have.
Second i'm still learning english so i want to say sorry for the inconvenience.
Well my problem is this, i need help improving my algorithm or any information about it, i don't know what words use for searching this.
The algorithm is supposed to find all the combinations of numbers that added is equal to a given number. Example: if i have the number 6 my results are supposed to be: [1,5],[2,4],[2,2,2],[3,3]
i have the following:
public List<List<int>> discompose(int number)
{
List<List<int>> discomposedPairs = new List<List<int>>();
if (number <= 3)
return discomposedPairs;
int[] numsForCombine = new int[number-1];
for(int i = 1; i < number;i++){
numsForCombine[i - 1] = i;
}
int ini = 0;
int end = numsForCombine.Length - 1;
while (ini <= end)
{
List<int> pair = new List<int>();
pair.Add(numsForCombine[ini++]);
pair.Add(numsForCombine[end--]);
discomposedPairs.Add(pair);
}
return discomposedPairs;
}
public List<List<int>> discomposePair(List<int> pair)
{
List<List<int>> parDisc = new List<List<int>>();
for (int i = 0; i < pair.Count; i++) {
if (pair[i] > 3)
{
List<List<int>> disc = discomposeList(discompose(pair[i]));
foreach (List<int> item in disc)
{
if (i > 0)
{
var temp = pair.GetRange(0, i);
temp.AddRange(item);
parDisc.Add(temp);
} else {
item.AddRange(pair.GetRange(i+1, pair.Count-(i+1)));
parDisc.Add(item);
}
}
}
}
return parDisc;
}
public List<List<int>> discomposeList(List<List<int>> list)
{
List<List<int>> mainDiscomposedList = new List<List<int>>();
for (int i = 0; i < list.Count; i++)
{
mainDiscomposedList.Add(list[i]);
List<List<int>> discomposedSubset = discomposePair(list[i]);
foreach(List<int> item in discomposedSubset){
mainDiscomposedList.Add(item);
}
}
return mainDiscomposedList;
}
The first method descompose the number given in pairs that added are equal the number given.
The second and the third method are the ugliest they are recursive and have bucles so they don't have any good performance. Between the two generates a List with numbers as i the problem says but there are a few inconvenients:
1) Don't have good performance
2) Gives a lot of repetitive sequences
here is the output for the number 10
[2,8,]
[2,2,6,]
[2,2,2,4,]
[2,2,2,2,2,]
[2,2,3,3,]
[2,3,5,]
[2,3,2,3,]<-------------repeated
[2,4,4,]
[2,2,2,4,]<-------------repeated
[2,4,2,2,]<-------------repeated
[3,7,]
[3,2,5,]<-------------repeated
[3,2,2,3,]<-------------repeated
[3,3,4,]
[3,3,2,2,]
[4,6,]
[2,2,6,]<-------------repeated
[4,2,4,]<-------------repeated
[4,2,2,2,]<-------------repeated
[4,3,3,]<-------------repeated
[5,5,]
[2,3,5,]<-------------repeated
[5,2,3,]<-------------repeated
Finally i want to improve the performance and have the less possible repeated items being a repeated item [1,1,3], [1,3,1], [3,1,1]
[Here is the full project link]1
Here's one approach that first builds the combinations into a tree structure, then arranges them into lists of ints:
internal class Combination
{
internal int Num;
internal IEnumerable<Combination> Combinations;
}
internal static IEnumerable<Combination> GetCombinationTrees(int num, int max)
{
return Enumerable.Range(1, num)
.Where(n => n <= max)
.Select(n =>
new Combination
{
Num = n,
Combinations = GetCombinationTrees(num - n, n)
});
}
internal static IEnumerable<IEnumerable<int>> BuildCombinations(
IEnumerable<Combination> combinations)
{
if (combinations.Count() == 0)
{
return new[] { new int[0] };
}
else
{
return combinations.SelectMany(c =>
BuildCombinations(c.Combinations)
.Select(l => new[] { c.Num }.Concat(l))
);
}
}
public static IEnumerable<IEnumerable<int>> GetCombinations(int num)
{
var combinationsList = GetCombinationTrees(num, num);
return BuildCombinations(combinationsList);
}
public static void PrintCombinations(int num)
{
var allCombinations = GetCombinations(num);
foreach (var c in allCombinations)
{
Console.WriteLine(string.Join(", ", c));
}
}
When run with the input value 6, this produces:
1, 1, 1, 1, 1, 1
2, 1, 1, 1, 1
2, 2, 1, 1
2, 2, 2
3, 1, 1, 1
3, 2, 1
3, 3
4, 1, 1
4, 2
5, 1
6
So I have an unsorted numeric array int[] anArray = { 1, 5, 2, 7 }; and I need to get both the value and the index of the largest value in the array which would be 7 and 3, how would I do this?
This is not the most glamorous way but works.
(must have using System.Linq;)
int maxValue = anArray.Max();
int maxIndex = anArray.ToList().IndexOf(maxValue);
int[] anArray = { 1, 5, 2, 7 };
// Finding max
int m = anArray.Max();
// Positioning max
int p = Array.IndexOf(anArray, m);
If the index is not sorted, you have to iterate through the array at least once to find the highest value. I'd use a simple for loop:
int? maxVal = null; //nullable so this works even if you have all super-low negatives
int index = -1;
for (int i = 0; i < anArray.Length; i++)
{
int thisNum = anArray[i];
if (!maxVal.HasValue || thisNum > maxVal.Value)
{
maxVal = thisNum;
index = i;
}
}
This is more verbose than something using LINQ or other one-line solutions, but it's probably a little faster. There's really no way to make this faster than O(N).
A succinct one-liner:
var (number, index) = anArray.Select((n, i) => (n, i)).Max();
Test case:
var anArray = new int[] { 1, 5, 7, 4, 2 };
var (number, index) = anArray.Select((n, i) => (n, i)).Max();
Console.WriteLine($"Maximum number = {number}, on index {index}.");
// Maximum number = 7, on index 2.
Features:
Uses Linq (not as optimized as vanilla, but the trade-off is less code).
Does not need to sort.
Computational complexity: O(n).
Space complexity: O(n).
Remarks:
Make sure the number (and not the index) is the first element in the tuple because tuple sorting is done by comparing tuple items from left to right.
The obligatory LINQ one[1]-liner:
var max = anArray.Select((value, index) => new {value, index})
.OrderByDescending(vi => vi.value)
.First();
(The sorting is probably a performance hit over the other solutions.)
[1]: For given values of "one".
Here are two approaches. You may want to add handling for when the array is empty.
public static void FindMax()
{
// Advantages:
// * Functional approach
// * Compact code
// Cons:
// * We are indexing into the array twice at each step
// * The Range and IEnumerable add a bit of overhead
// * Many people will find this code harder to understand
int[] array = { 1, 5, 2, 7 };
int maxIndex = Enumerable.Range(0, array.Length).Aggregate((max, i) => array[max] > array[i] ? max : i);
int maxInt = array[maxIndex];
Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");
}
public static void FindMax2()
{
// Advantages:
// * Near-optimal performance
int[] array = { 1, 5, 2, 7 };
int maxIndex = -1;
int maxInt = Int32.MinValue;
// Modern C# compilers optimize the case where we put array.Length in the condition
for (int i = 0; i < array.Length; i++)
{
int value = array[i];
if (value > maxInt)
{
maxInt = value;
maxIndex = i;
}
}
Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");
}
int[] numbers = new int[7]{45,67,23,45,19,85,64};
int smallest = numbers[0];
for (int index = 0; index < numbers.Length; index++)
{
if (numbers[index] < smallest) smallest = numbers[index];
}
Console.WriteLine(smallest);
public static class ArrayExtensions
{
public static int MaxIndexOf<T>(this T[] input)
{
var max = input.Max();
int index = Array.IndexOf(input, max);
return index;
}
}
This works for all variable types...
var array = new int[]{1, 2, 4, 10, 0, 2};
var index = array.MaxIndexOf();
var array = new double[]{1.0, 2.0, 4.0, 10.0, 0.0, 2.0};
var index = array.MaxIndexOf();
this works like a charm, no need for linq or other extensions
int[] anArray = { 1, 5, 2, 7 };
int i, mx;
int j = 0;
mx = anArray[0];
for (i = 1; i < anArray.Length; i++)
{
if (anArray[i] > mx)
{
mx = anArray[i];
j = i;
}
}
Console.Write("The largest value is: {0}, of index: {1}", mx, j);
anArray.Select((n, i) => new { Value = n, Index = i })
.Where(s => s.Value == anArray.Max());
Output for bellow code:
00:00:00.3279270 - max1
00:00:00.2615935 - max2
00:00:00.6010360 - max3 (arr.Max())
With 100000000 ints in array not very big difference but still...
class Program
{
static void Main(string[] args)
{
int[] arr = new int[100000000];
Random randNum = new Random();
for (int i = 0; i < arr.Length; i++)
{
arr[i] = randNum.Next(-100000000, 100000000);
}
Stopwatch stopwatch1 = new Stopwatch();
Stopwatch stopwatch2 = new Stopwatch();
Stopwatch stopwatch3 = new Stopwatch();
stopwatch1.Start();
var max = GetMaxFullIterate(arr);
Debug.WriteLine( stopwatch1.Elapsed.ToString());
stopwatch2.Start();
var max2 = GetMaxPartialIterate(arr);
Debug.WriteLine( stopwatch2.Elapsed.ToString());
stopwatch3.Start();
var max3 = arr.Max();
Debug.WriteLine(stopwatch3.Elapsed.ToString());
}
private static int GetMaxPartialIterate(int[] arr)
{
var max = arr[0];
var idx = 0;
for (int i = arr.Length / 2; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
if (arr[idx] > max)
{
max = arr[idx];
}
idx++;
}
return max;
}
private static int GetMaxFullIterate(int[] arr)
{
var max = arr[0];
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
return max;
}
public static void Main()
{
int a,b=0;
int []arr={1, 2, 2, 3, 3, 4, 5, 6, 5, 7, 7, 7, 100, 8, 1};
for(int i=arr.Length-1 ; i>-1 ; i--)
{
a = arr[i];
if(a > b)
{
b=a;
}
}
Console.WriteLine(b);
}
Old post, but this is super easy with Lists:
For Maximum:
List<int> lst = new List<int>(YourArray);
int Max = lst.OrderByDescending(x => x).First();
For Minimum:
List<int> lst = new List<int>(YourArray);
int Max = lst.OrderBy(x => x).First();
Of course you can substitute "int" data type with any numeric variable type (float, decimal, etc).
This is very high performance BTW and beats any other method (IMHO)
int[] Data= { 1, 212, 333,2,12,3311,122,23 };
int large = Data.Max();
Console.WriteLine(large);
Here is a LINQ solution which is O(n) with decent constant factors:
int[] anArray = { 1, 5, 2, 7, 1 };
int index = 0;
int maxIndex = 0;
var max = anArray.Aggregate(
(oldMax, element) => {
++index;
if (element <= oldMax)
return oldMax;
maxIndex = index;
return element;
}
);
Console.WriteLine("max = {0}, maxIndex = {1}", max, maxIndex);
But you should really write an explicit for lop if you care about performance.
Just another perspective using DataTable. Declare a DataTable with 2 columns called index and val. Add an AutoIncrement option and both AutoIncrementSeed and AutoIncrementStep values 1 to the index column. Then use a foreach loop and insert each array item into the datatable as a row. Then by using Select method, select the row having the maximum value.
Code
int[] anArray = { 1, 5, 2, 7 };
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[2] { new DataColumn("index"), new DataColumn("val")});
dt.Columns["index"].AutoIncrement = true;
dt.Columns["index"].AutoIncrementSeed = 1;
dt.Columns["index"].AutoIncrementStep = 1;
foreach(int i in anArray)
dt.Rows.Add(null, i);
DataRow[] dr = dt.Select("[val] = MAX([val])");
Console.WriteLine("Max Value = {0}, Index = {1}", dr[0][1], dr[0][0]);
Output
Max Value = 7, Index = 4
Find a demo here
If you know max index accessing the max value is immediate. So all you need is max index.
int max=0;
for(int i = 1; i < arr.Length; i++)
if (arr[i] > arr[max]) max = i;
This is a C# Version. It's based on the idea of sort the array.
public int solution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
Array.Sort(A);
var max = A.Max();
if(max < 0)
return 1;
else
for (int i = 1; i < max; i++)
{
if(!A.Contains(i)) {
return i;
}
}
return max + 1;
}
Consider following:
/// <summary>
/// Returns max value
/// </summary>
/// <param name="arr">array to search in</param>
/// <param name="index">index of the max value</param>
/// <returns>max value</returns>
public static int MaxAt(int[] arr, out int index)
{
index = -1;
int max = Int32.MinValue;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
index = i;
}
}
return max;
}
Usage:
int m, at;
m = MaxAt(new int[]{1,2,7,3,4,5,6}, out at);
Console.WriteLine("Max: {0}, found at: {1}", m, at);
This can be done with a bodiless for loop, if we're heading towards golf ;)
//a is the array
int mi = a.Length - 1;
for (int i=-1; ++i<a.Length-1; mi=a[mi]<a[i]?i:mi) ;
The check of ++i<a.Length-1 omits checking the last index. We don't mind this if we set it up as if the max index is the last index to start with.. When the loop runs for the other elements it will finish and one or the other thing is true:
we found a new max value and hence a new max index mi
the last index was the max value all along, so we didn't find a new mi, and we stuck with the initial mi
The real work is done by the post-loop modifiers:
is the max value (a[mi] i.e. array indexed by mi) we found so far, less than the current item?
yes, then store a new mi by remembering i,
no then store the existing mi (no-op)
At the end of the operation you have the index at which the max is to be found. Logically then the max value is a[mi]
I couldn't quite see how the "find max and index of max" really needed to track the max value too, given that if you have an array, and you know the index of the max value, the actual value of the max value is a trivial case of using the index to index the array..
Another answer in this long list, but I think it's worth it, because it provides some benefits that most (or all?) other answers don't:
The method below loops only once through the collection, therefore the order is O(N).
The method finds ALL indices of the maximum values.
The method can be used to find the indices of any comparison: min, max, equals, not equals, etc.
The method can look into objects via a LINQ selector.
Method:
///-------------------------------------------------------------------
/// <summary>
/// Get the indices of all values that meet the condition that is defined by the comparer.
/// </summary>
/// <typeparam name="TSource">The type of the values in the source collection.</typeparam>
/// <typeparam name="TCompare">The type of the values that are compared.</typeparam>
/// <param name="i_collection">The collection of values that is analysed.</param>
/// <param name="i_selector">The selector to retrieve the compare-values from the source-values.</param>
/// <param name="i_comparer">The comparer that is used to compare the values of the collection.</param>
/// <returns>The indices of all values that meet the condition that is defined by the comparer.</returns>
/// Create <see cref="IComparer{T}"/> from comparison function:
/// Comparer{T}.Create ( comparison )
/// Comparison examples:
/// - max: (a, b) => a.CompareTo (b)
/// - min: (a, b) => -(a.CompareTo (b))
/// - == x: (a, b) => a == 4 ? 0 : -1
/// - != x: (a, b) => a != 4 ? 0 : -1
///-------------------------------------------------------------------
public static IEnumerable<int> GetIndices<TSource, TCompare> (this IEnumerable<TSource> i_collection,
Func<TSource, TCompare> i_selector,
IComparer<TCompare> i_comparer)
{
if (i_collection == null)
throw new ArgumentNullException (nameof (i_collection));
if (!i_collection.Any ())
return new int[0];
int index = 0;
var indices = new List<int> ();
TCompare reference = i_selector (i_collection.First ());
foreach (var value in i_collection)
{
var compare = i_selector (value);
int result = i_comparer.Compare (compare, reference);
if (result > 0)
{
reference = compare;
indices.Clear ();
indices.Add (index);
}
else if (result == 0)
indices.Add (index);
index++;
}
return indices;
}
If you don't need the selector, then change the method to
public static IEnumerable<int> GetIndices<TCompare> (this IEnumerable<TCompare> i_collection,
IComparer<TCompare> i_comparer)
and remove all occurences of i_selector.
Proof of concept:
//########## test #1: int array ##########
int[] test = { 1, 5, 4, 9, 2, 7, 4, 6, 5, 9, 4 };
// get indices of maximum:
var indices = test.GetIndices (t => t, Comparer<int>.Create ((a, b) => a.CompareTo (b)));
// indices: { 3, 9 }
// get indices of all '4':
indices = test.GetIndices (t => t, Comparer<int>.Create ((a, b) => a == 4 ? 0 : -1));
// indices: { 2, 6, 10 }
// get indices of all except '4':
indices = test.GetIndices (t => t, Comparer<int>.Create ((a, b) => a != 4 ? 0 : -1));
// indices: { 0, 1, 3, 4, 5, 7, 8, 9 }
// get indices of all '15':
indices = test.GetIndices (t => t, Comparer<int>.Create ((a, b) => a == 15 ? 0 : -1));
// indices: { }
//########## test #2: named tuple array ##########
var datas = new (object anything, double score)[]
{
(999, 0.1),
(new object (), 0.42),
("hello", 0.3),
(new Exception (), 0.16),
("abcde", 0.42)
};
// get indices of highest score:
indices = datas.GetIndices (data => data.score, Comparer<double>.Create ((a, b) => a.CompareTo (b)));
// indices: { 1, 4 }
Enjoy! :-)
Finds the biggest and the smallest number in the array:
int[] arr = new int[] {35,28,20,89,63,45,12};
int big = 0;
int little = 0;
for (int i = 0; i < arr.Length; i++)
{
Console.WriteLine(arr[i]);
if (arr[i] > arr[0])
{
big = arr[i];
}
else
{
little = arr[i];
}
}
Console.WriteLine("most big number inside of array is " + big);
Console.WriteLine("most little number inside of array is " + little);
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
I have an array of ints. I want to get the second highest number in that array. Is there an easy way to do this?
Try this (using LINQ):
int secondHighest = (from number in numbers
orderby number descending
select number).Skip(1).First();
You could sort the array and choose the item at the second index, but the following O(n) loop will be much faster.
int[] myArray = new int[] { 0, 1, 2, 3, 13, 8, 5 };
int largest = int.MinValue;
int second = int.MinValue;
foreach (int i in myArray)
{
if (i > largest)
{
second = largest;
largest = i;
}
else if (i > second)
second = i;
}
System.Console.WriteLine(second);
Yes, have 2 vars (first and second) passthrough the array and each time compair what you get with this two cells (always putting the highest on first and the 2nd highest on second)
with one pass you will get the 2nd higher on the second var.
You don't specify if you want to do this with the minimum complexity.
Assuming your array is unsorted, please see: How to find the kth largest element in an unsorted array of length n in O(n)?
To find Kth largest element in an unsorted array: Build a max heap in O(n). Now remove k elements from the heap; where each removal costs log(n) time to maintain the heap. Total time complexity = O(n + klogn)
To understand building Max heap in O(n) see Binary heap
max1=0;
max2=0;
for( int i=0; i < a.Length; i++)
{
if (arr[i]> max1)
{
max2=max1;
max1=arr[i];
}
else
{
if (a[i]!= max1) && ( a[i] > max2)
max2[i]=arr[i];
}
}
Getting the max number first, once the max is changed do a comparison against the second high number to see if it needs to swapped. The second if statement checks if the value is less than the max and is greater than the second highest value. Because of the short circuit, if the first condition fails then it exits the if and skips
static void Main(string[] args)
{
//int[] arr = new int[10] { 9, 4, 6, 2, 11, 100, 53, 23, 72, 81 };
int[] arr = { 1, 8, 4, 5, 12, 2, 5, 6, 7, 1, 90, 100, 56, 8, 34 };
int MaxNum = 0;
int SecNum = 0;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > MaxNum)
{
if (MaxNum > SecNum) { SecNum = MaxNum; }
MaxNum = arr[i];
}
if (arr[i] < MaxNum && arr[i] > SecNum)
{
SecNum = arr[i];
}
}
Console.WriteLine("Highest Num: {0}. Second Highest Num {1}.", MaxNum, SecNum);
Console.ReadLine();
}
int[] myArray = new int[] { 0, 1, 2, 3, 13, 8, 5 };
int num1=0, temp=0;
for (int i = 0; i < myArray.Length; i++)
{
if (myArray[i] >= num1)
{
num1 = myArray[i];
}
else if ((myArray[i] < num1) && (myArray[i] > temp))
{
temp = myArray[i];
}
}
Console.WriteLine("The Largest Number is: " + num1);
Console.WriteLine("The Second Highest Number is: " + temp);
int[] arr = { 1, 8, 4, 5, 12, 2, 5, 6, 7, 1, 90, 100, 56, 8, 34 };
int first, second;
// Assuming the array has at least one element:
first = second = arr[0];
for(int i = 1; i < arr.Length; ++i)
{
if (first < arr[i])
{
// 'first' now contains the 2nd largest number encountered thus far:
second = first;
first = arr[i];
}
}
MessageBox.Show(second.ToString());
static void Main(string[] args)
{
int[] myArray = new int[] { 0, 1, 2, 3, 13, 8, 5,12,11,14 };
int num1 = 0, temp = 0;
for (int i = 0; i < myArray.Length; i++)
{
if (myArray[i] >= num1)
{
temp = num1;
num1 = myArray[i];
}
else if ((myArray[i] < num1) && (myArray[i] > temp))
{
temp = myArray[i];
}
}
Console.WriteLine("The Largest Number is: " + num1);
Console.WriteLine("The Second Highest Number is: " + temp);
Console.ReadKey();
}
There are two possibilities to find second highest number from an array.
1). Find second max number from an array.
int[] myArray = { 0, 2, 3, 8, 13};
int max = 0;
int second_max = 0;
foreach (int arr in myArray) {
if (arr > max)
{
second_max = max;
max = arr;
}
}
Console.WriteLine("First highest number is: "+max);
Console.WriteLine("Second highest number is: " + second_max);
2). Find second max number with the smallest complexity from an array.
int[] myArray = { 0, 2, 3, 13, 8};//smaller number is given after
larger number
int max = 0;
int second_max = 0;
foreach (int arr in myArray) {
if (arr > max)
{
second_max = max;
max = arr;
}
else if (arr > second_max)
{
second_max = arr;
}
}
Console.WriteLine("First highest number is: "+max);
Console.WriteLine("Second highest number is: " + second_max);