How to solve Randomize in place algorithm in C#? - c#

I'm reading Introduction to Algorithms - Third edition and now, I have to implement RANDOMIZE-IN-PLACE algorithm which must permute each value from the current array.
The pseudocode provided by the book looks like this:
n = A.length
for i = 1 to n
swap A[i] with A[Random(i, n)]
I tried to implement that on C#, but I'm receiving an IndexOutOfRangeException sometimes (only in some cases). I used to debug the algorithm and found that when
randomValue = array[randomNumber.Next(index, upperBound)];
index is equal to array.Length - 1 and upperBound is array.Length - 1 (in other words the index and upperBound are the same values and the .Next looks like this .Next(9, 9) for example), the random generator is able to produce number 10 (lower bound / upper bound + 1) which is exactly my array.Length. If someone has any idea how to fix that will be very helpful for me. Thank again. Here is my C# code.
namespace RandomizedAlgorithms
{
using System;
class RandomizeInPlace
{
static void Main()
{
int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Randomize(array);
for (int index = 0; index <= array.Length - 1 ; index++)
{
Console.WriteLine(array[index]);
}
}
private static void Randomize(int[] array)
{
Random randomNumber = new Random();
int swapVariable = 0;
int randomValue = 0;
int upperBound = array.Length - 1;
for (int index = 0; index <= array.Length - 1 ; index++)
{
randomValue = array[randomNumber.Next(index, upperBound)];
swapVariable = array[randomValue];
array[randomValue] = array[index];
array[index] = swapVariable;
}
}
}
}

You need to store the random index of the element you are going to swap, rather than the array value itself:
private static void Randomize(int[] array)
{
Random randomNumber = new Random();
int swapVariable = 0;
int randomIndex; // <-- renamed this
int upperBound = array.Length; // <-- See the comments
for(int index = 0; index < array.Length; index++)
{
// Note: besides the minor changes above, the real fix is removing array[...]
randomIndex = randomNumber.Next(index + 1, upperBound);
swapVariable = array[randomIndex];
array[randomIndex] = array[index];
array[index] = swapVariable;
}
}
I've changed your code as little as possible, other improvements are possible. Note that this version allows an element to be "swapped" with itself, which may or may not be what you want.

You are using the array values as indices, via the variable randomValue:
randomValue = array[randomNumber.Next(index, upperBound)];
swapVariable = array[randomValue];
Your array values go from 1 to 10:
int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
But arrays in c# are 0-based. Change the array values to go from 0 to 9:
int[] array = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Update
OK, as commenters have pointed out, you're using the Fisher–Yates shuffle. Here's a direct translation of that algorithm. Note the weird asymmetry in the arguments to Random.Next(int minValue, int maxValue) which returns (minValue <= value < maxValue)
public interface IRandomizer
{
void RandomizeInPlace<T>(T[] array);
}
public class FisherYatesShuffle : IRandomizer
{
readonly Random randomNumber = new Random();
public void RandomizeInPlace<T>(T[] array)
{
// http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm , second version.
for (int i = 0; i < array.Length; i++)
{
// http://msdn.microsoft.com/en-us/library/2dx6wyd4%28v=vs.110%29.aspx
var j = randomNumber.Next(i, array.Length); // i = inclusive lower bound; array.Length = The exclusive upper bound of the random number returned
array.Swap(i, j);
}
}
}
public static class ListHelper
{
public static void Swap<T>(this T[] list, int i, int j)
{
if (list == null)
throw new ArgumentNullException();
if (i != j)
{
T temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}

Related

Write a program to find an index of Max item in an array

Write a console app in C# to find an index i in an array that is the maximum number in the array.
If the maximum element in the array occurs several times, you need to display the minimum index.
If the array is empty, output -1.
Please let me know what is wrong in my code?
If I input the array a = { 1, 2, 46, 14, 64, 64 };, for instance, it returns 0, while it should be returning 4.
public static void Main()
{
double[] a = { 1, 9, 9, 8, 9, 2, 2 };
Console.WriteLine(MaxIndex(a));
}
public static double MaxIndex(double[] array)
{
var max = double.MinValue;
int maxInd = 0, maxCount = 0;
int minIndex = 0;
var min = double.MaxValue;
for (var i = 0; i < array.Length; i++)
{
if (min > array[i])
{
min = array[i];
minIndex = i;
}
if (max == array[i])
maxCount++;
if (max < array[i])
{
maxCount = 1;
max = array[i];
maxInd = i;
}
}
if (array.Length == 0)
return -1;
if (maxCount > 1)
return minIndex;
return maxInd;
}
Your calculation is correct, but you return the wrong variable minIndex instead of maxIndex. Don't do more than necessary in a method. This calculates also the min-index and the count how often it appears, then it does nothing with the results. Here is a compact version:
public static int MaxIndex(double[] array)
{
var max = double.MinValue;
int maxInd = -1;
for (int i = 0; i < array.Length; i++)
{
if (max < array[i])
{
max = array[i];
maxInd = i;
}
}
return maxInd;
}
It also sets maxInd = -1 which was part of your requirement. Since MatthewWatson had an objection regarding repeating double.MinValue in the array, here is an optimized version:
public static int MaxIndex(double[] array)
{
if(array.Length == 0)
return -1;
else if (array.Length == 1)
return 0;
double max = array[0];
int maxInd = 0;
for (int i = 1; i < array.Length; i++)
{
if (max < array[i])
{
max = array[i];
maxInd = i;
}
}
return maxInd;
}
If code-readability/maintainability is more important and you don't care of few milliseconds more or less, you could use LINQ (a version that enumerates only once):
int minIndexOfMaxVal = a.Select((num, index) => new {num, index})
.OrderByDescending(x => x.num)
.Select(x => x.index)
.DefaultIfEmpty(-1)
.First();
This works with every kind of sequence and types not only with arrays and doubles.
Try this simple line of code:
int[] numbers = { 1, 2, 3, 4, 5, 4, 3, 2, 1 };
var index = numbers.ToList().IndexOf(numbers.Max());
I think code is simple enough to be self-explanatory.
However, if you aim for performance, conversion to List could be omitted and you could wirte own code to find index of maximum number.
Or even simplier, proposed by #fubo:
Array.IndexOf(numbers, numbers.Max());
A lot of simplification is possible in this code:
int? maxVal = null; // null because of array of negative value;
int index = -1;
for (int i = 0; i < array.Length; i++)
{
int current = array[i];
if (!maxVal.HasValue || current > maxVal.Value)
{
maxVal = current ;
index = i;
}
}
Will get you the first index of the max value. If you just need a short code and Don't mind iterating twice a simple linq can do the trick
var index = array.ToList().IndexOf(array.Max());
It returns zero, because minIndex is indeed zero:
Change minIndex to maxIndex:
if (maxCount > 1) return maxIndex;
In order to compare doubles use the following code instead of ==:
if (Math.Abs(a-b)<double.Epsilon)
Your code in general is way too complicated with way too many variables for what it has to do.
You want the index of the first occurence of the highest value, so there isn't any real reason to store anything but a MaxValueIndex and a MaxValue.
All other variables should be local so garbage collection can dispose of them.
As for what is actually wrong with your code, I can't help out, since the variable names are confusing to me.
But here is some code that achieves the goal you want to achieve.
double[] a = { 1, 9, 9, 8, 9, 2, 2 };
var highestValueInArray = a.Max();
var arrayLength = a.Length;
for (int i = 0; i < arrayLength; i++)
{
if (a[i] == highestValueInArray)
{
Console.WriteLine(i);
break;
}
}
instead of manually calculating the max value, you can just use YourArray.Max() to get the highest value.
then just iterate through it like normal, but at the first occurence, you break; out of the loop and return the index it is at.
I'm pretty sure there's also a way to use FirstOrDefault in combination with IndexOf, but couldn't get that to work myself.

How to find minimum number of steps to sort an integer array

I have an integer array int[] number = { 3,4,2,5,1};
The minimum number of steps to sort it should be 2. But I am getting 4.
static void Main(string[] args)
{
int[] number = { 3,4,2,5,1};
int result = get_order(number);
Console.ReadKey();
}
public static int get_order(int[] input1)
{
input1 = input1.OrderByDescending(o => o).ToArray();
bool flag = true;
int temp;
int numLength = input1.Length;
int passes = 0;
for (int i = 1; (i <= (numLength - 1)) && flag; i++)
{
flag = false;
for (int j = 0; j < (numLength - 1); j++)
{
if (input1[j + 1] > input1[j])
{
temp = input1[j];
input1[j] = input1[j + 1];
input1[j + 1] = temp;
flag = true;
}
}
passes++;
}
return passes+1;
}
What is the problem and what changes i need to do in my code?
Edit
implement #Patashu, algorithm,
public static int get_order(int[] input1)
{
var sorterArray = input1.OrderByDescending(o => o).ToArray();
var unsortedArray = input1;
int temp1;
int swap = 0;
int arrayLength = sorterArray.Length;
for (int i = 0; i < arrayLength; i++)
{
if (sorterArray[i] != unsortedArray[i])
{
temp1 = unsortedArray[i];
unsortedArray[i] = sorterArray[i];
for (int j = i + 1; j < arrayLength; j++)
{
if (unsortedArray[j] == sorterArray[i])
{
unsortedArray[j] = temp1;
swap++;
break;
}
}
}
}
return swap;
}
The problem with your algorithm is that it only attempts swapping adjacent elements.
3,4,2,5,1 is best sorted by swapping 3 with 5, which is an unadjacent swap, and then 2 with 3.
So, I suggest that you will find a better algorithm by doing the following:
1) First, sort the array into descending order using the built in sorting function of C#.
2) Now, you can use this sorted array as a comparison - iterate through the array from left to right. Every time you see an element in the unsorted array that is != to the element in the same space in the sorted array, look deeper into the unsorted array for the value the sorted array has there, and do one swap.
e.g.
3,4,2,5,1
Sort using Sort -> 5,4,3,2,1 is our sorted array
3 is != 5 - look in unsorted array for 5 - found it, swap them.
Unsorted is now 5,4,2,3,1
4 == 4
2 is != 3 - look in unsorted array for 3 - found it, swap them.
Unsorted is now 5,4,3,2,1
2 == 2
1 == 1
We're at the end of the unsorted array and we did two swaps.
EDIT: In your algorithm implementation, it looks almost right except
instead of
unsortedArray[j] = sorterArray[i];
unsortedArray[i] = temp1;
you had it backwards, you want
unsortedArray[j] = temp1;
unsortedArray[i] = sorterArray[i];
Since you're asking why you're getting 4 steps, and not how to calculate the passes, the correct way to do this is to simply step through your code. In your case the code is simple enough to step through on a piece of paper, in the debugger, or with added debug statements.
Original: 3, 4, 2, 5, 1
Pass: 1: 4, 3, 5, 2, 1
Pass: 2: 4, 5, 3, 2, 1
Pass: 3: 5, 4, 3, 2, 1
Pass: 4: 5, 4, 3, 2, 1
Basically what you see is that each iteration you sort one number into the correct position. At the end of pass one 2 is in the correct position. Then 3, 4, 5.
Ah! But this is only 3 passes you say. But you're actually incrementing passes regardless of flag, which shows you that you actually did one extra step where the array is sorted (in reverse order) but you didn't know this so you had to go through and double check (this was pass 4).
To improve performance, you do not need to start checking the array from the beginning.
Better than the last equal element.
static int MinimumSwaps(int[] arr)
{
int result = 0;
int temp;
int counter = 0;
for (int i = 0; i < arr.Length; ++i)
{
if (arr[i] - 1 == i)
{
//once all sorted then
if(counter==arr.Length)break;
counter++;
continue;
}
temp = arr[arr[i]-1];
arr[arr[i] - 1] = arr[i];
arr[i] = temp;
result++;//swapped
i = counter ;//needs to start from the last equal element
}
return result;
}
At the start:
{ 3,4,2,5,1}; // passes = 0
Round 1 reuslt:
{ 4,3,2,5,1};
{ 4,3,5,2,1}; // passes = 1
Round 2 reuslt:
{ 4,5,3,2,1}; // passes = 2
Round 3 reuslt:
{ 5,4,3,2,1}; // passes = 3 and flag is set to true
Round 4 reuslt:
{ 5,4,3,2,1}; // same result and passes is incremented to be 4
You fail to mention that the array is supposed to be sorted in descending order, which is usually not the default expected behavior (at least in "C" / C++). To turn:
3, 4, 2, 5, 1
into:
1, 2, 3, 4, 5
one indeed needs 4 (non-adjacent) swaps. However, to turn it into:
5, 4, 3, 2, 1
only two swaps suffice. The following algorithm finds the number of swaps in O(m) of swap operations where m is number of swaps, which is always strictly less than the number of items in the array, n (alternately the complexity is O(m + n) of loop iterations):
int n = 5;
size_t P[] = {3, 4, 2, 5, 1};
for(int i = 0; i < n; ++ i)
-- P[i];
// need zero-based indices (yours are 1-based)
for(int i = 0; i < n; ++ i)
P[i] = 4 - P[i];
// reverse order?
size_t count = 0;
for(int i = 0; i < n; ++ i) {
for(; P[i] != i; ++ count) // could be permuted multiple times
std::swap(P[P[i]], P[i]); // look where the number at hand should be
}
// count number of permutations
This indeed finds two swaps. Note that the permutation is destroyed in the process.
The test case for this algorithm can be found here (tested with Visual Studio 2008).
Here is the solution for your question :)
static int MinimumSwaps(int[] arr)
{
int result = 0;
int temp;
int counter = 0;
for (int i = 0; i < arr.Length; ++i)
{
if (arr[i] - 1 == i)
{
//once all sorted then
if(counter==arr.Length)break;
counter++;
continue;
}
temp = arr[arr[i]-1];
arr[arr[i] - 1] = arr[i];
arr[i] = temp;
result++;//swapped
i = 0;//needs to start from the beginning after every swap
counter = 0;//clearing the sorted array counter
}
return result;
}

C# find highest array value and index

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);

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

How to get the second highest number in an array in Visual C#?

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);

Categories

Resources