Given an unsorted array find the max and min values. I'm trying to do this in a recursive, divide and conquer way but I keep getting a stack overflow error. I debugged and i keep getting the error in my recursive calls but do not know what is wrong or how to fix it.
I do have static min and max variables.
Thanks for the information and help!
static void findMaxMin(int[] array, int start, int end)
{
if (end == 2)
{
setMaxMin(array);
}
else
{
int mid = ((end) / 2);
findMaxMin(array, start, mid);
findMaxMin(array, mid + 1, end);
}
}
private static void setMaxMin(int[] array)
{
if (array[0] > array[1])
{
max = array[0];
min = array[1];
}
else
{
min = array[0];
max = array[1];
}
}
Here is one simple way to do it (without recursion):
void FindMinAndMaxValues(int[] array out int min, out int max)
{
min = int.MaxValue,
max = int.MinValue;
foreach(var val in array)
{
max = (val > max) ? val : max;
min = (val < min) ? val : min;
}
}
Please note that I'm using out parameters here. This is done for simplicity of the code. Usually, I would prefer to either return a designated class or a tuple.
Also, LINQ has min and max extension methods that you can use - so the entire thing turns to something like this:
var max = array.Max();
var min = array.Min();
Related
I learnt about quick sort and how it can be implemented in both Recursive and Iterative method.
In Iterative method:
Push the range (0...n) into the stack
Partition the given array with a pivot
Pop the top element.
Push the partitions (index range) onto a stack if the range has more than one element
Do the above 3 steps, till the stack is empty
And the recursive version is the normal one defined in wiki.
I learnt that recursive algorithms are always slower than their iterative counterpart.
So, Which method is preferred in terms of time complexity (memory is not a concern)?
Which one is fast enough to use in Programming contest?
Is c++ STL sort() using a recursive approach?
In terms of (asymptotic) time complexity - they are both the same.
"Recursive is slower then iterative" - the rational behind this statement is because of the overhead of the recursive stack (saving and restoring the environment between calls).
However -these are constant number of ops, while not changing the number of "iterations".
Both recursive and iterative quicksort are O(nlogn) average case and O(n^2) worst case.
EDIT:
just for the fun of it I ran a benchmark with the (java) code attached to the post , and then I ran wilcoxon statistic test, to check what is the probability that the running times are indeed distinct
The results may be conclusive (P_VALUE=2.6e-34, https://en.wikipedia.org/wiki/P-value. Remember that the P_VALUE is P(T >= t | H) where T is the test statistic and H is the null hypothesis). But the answer is not what you expected.
The average of the iterative solution was 408.86 ms while of recursive was 236.81 ms
(Note - I used Integer and not int as argument to recursiveQsort() - otherwise the recursive would have achieved much better, because it doesn't have to box a lot of integers, which is also time consuming - I did it because the iterative solution has no choice but doing so.
Thus - your assumption is not true, the recursive solution is faster (for my machine and java for the very least) than the iterative one with P_VALUE=2.6e-34.
public static void recursiveQsort(int[] arr,Integer start, Integer end) {
if (end - start < 2) return; //stop clause
int p = start + ((end-start)/2);
p = partition(arr,p,start,end);
recursiveQsort(arr, start, p);
recursiveQsort(arr, p+1, end);
}
public static void iterativeQsort(int[] arr) {
Stack<Integer> stack = new Stack<Integer>();
stack.push(0);
stack.push(arr.length);
while (!stack.isEmpty()) {
int end = stack.pop();
int start = stack.pop();
if (end - start < 2) continue;
int p = start + ((end-start)/2);
p = partition(arr,p,start,end);
stack.push(p+1);
stack.push(end);
stack.push(start);
stack.push(p);
}
}
private static int partition(int[] arr, int p, int start, int end) {
int l = start;
int h = end - 2;
int piv = arr[p];
swap(arr,p,end-1);
while (l < h) {
if (arr[l] < piv) {
l++;
} else if (arr[h] >= piv) {
h--;
} else {
swap(arr,l,h);
}
}
int idx = h;
if (arr[h] < piv) idx++;
swap(arr,end-1,idx);
return idx;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String... args) throws Exception {
Random r = new Random(1);
int SIZE = 1000000;
int N = 100;
int[] arr = new int[SIZE];
int[] millisRecursive = new int[N];
int[] millisIterative = new int[N];
for (int t = 0; t < N; t++) {
for (int i = 0; i < SIZE; i++) {
arr[i] = r.nextInt(SIZE);
}
int[] tempArr = Arrays.copyOf(arr, arr.length);
long start = System.currentTimeMillis();
iterativeQsort(tempArr);
millisIterative[t] = (int)(System.currentTimeMillis()-start);
tempArr = Arrays.copyOf(arr, arr.length);
start = System.currentTimeMillis();
recursvieQsort(tempArr,0,arr.length);
millisRecursive[t] = (int)(System.currentTimeMillis()-start);
}
int sum = 0;
for (int x : millisRecursive) {
System.out.println(x);
sum += x;
}
System.out.println("end of recursive. AVG = " + ((double)sum)/millisRecursive.length);
sum = 0;
for (int x : millisIterative) {
System.out.println(x);
sum += x;
}
System.out.println("end of iterative. AVG = " + ((double)sum)/millisIterative.length);
}
Recursion is NOT always slower than iteration. Quicksort is perfect example of it. The only way to do this in iterate way is create stack structure. So in other way do the same that the compiler do if we use recursion, and propably you will do this worse than compiler. Also there will be more jumps if you don't use recursion (to pop and push values to stack).
That's the solution i came up with in Javascript. I think it works.
const myArr = [33, 103, 3, 726, 200, 984, 198, 764, 9]
document.write('initial order :', JSON.stringify(myArr), '<br><br>')
qs_iter(myArr)
document.write('_Final order :', JSON.stringify(myArr))
function qs_iter(items) {
if (!items || items.length <= 1) {
return items
}
var stack = []
var low = 0
var high = items.length - 1
stack.push([low, high])
while (stack.length) {
var range = stack.pop()
low = range[0]
high = range[1]
if (low < high) {
var pivot = Math.floor((low + high) / 2)
stack.push([low, pivot])
stack.push([pivot + 1, high])
while (low < high) {
while (low < pivot && items[low] <= items[pivot]) low++
while (high > pivot && items[high] > items[pivot]) high--
if (low < high) {
var tmp = items[low]
items[low] = items[high]
items[high] = tmp
}
}
}
}
return items
}
Let me know if you found a mistake :)
Mister Jojo UPDATE :
this code just mixes values that can in rare cases lead to a sort, in other words never.
For those who have a doubt, I put it in snippet.
I've got a two dimensional integer array that represents a map I'm using to track locations of objects in a game. It gets modified by a procedural system that will change the numbers in there to place different objects. I'll set the value of each Int as a 0,1 or 2. Looks like this:
00010
00100
02120
21200
12000
Since the procedural step relies heavily on randomization, I want to put several checks in place that if the array location I'm trying to write is outside the bounds of the array, it'll fall back to the edge of the map instead of causing a fault. e.g. I try to put an entry in [0,10] it'll default to [0,4].
Yes, I know that I should just be careful to make sure I never attempt to write outside the bounds of the array, but given other elements that won't happen every time. A sanity check seems prudent.
The solution I came up with works, but it seems overly fiddly and long. Is there a cleaner solution I'm unaware of?
Here's the code sample:
//Example of something randomly being written to the array
random r = new Random();
int xMax = field.GetLength(0);
field[mid(r.next(0,5), 0, xMax), 0] = 1;
//Method for sanity bounds.
private static int mid(int target, int min, int max)
{
//Target is the value we want
//Min is the smallest possible value
//Max is the largest possible value.
if (target == min)
{
return min;
}
if (target == max)
{
return max;
}
if (target < max && target > min)
{
return target;
}
else if (target > max && target > min)
{
return max;
}
else if (target < min && target < max)
{
return min;
}
return min; //This shouldn't ever get trigger. In here so compiler won't complain.
}
You can just do:
public int mid(int target, int min, int max)
{
return Math.max(min, Math.min(max, target));
}
This function returns the maximum of the smaller value of the intended value and the maximum bound, ensuring that a valid value will be returned.
You can also use % in your accesses if you are using a rectangular 2-dimensional array:
array[index1 % array.length][index2 % array[0].length] = /* somevar */;
If you want the index to 'wrap' around the array as you described, this should work:
public void GetValidIndexForArrayFromRandomIndex(int index, string[] myArray)
{
var upperBound = myArray.GetUpperBound(0);
var lowerBound = myArray.GetLowerBound(0);
while (index > upperBound)
{
index -= upperBound + 1;
}
while (index < lowerBound)
{
index += upperBound;
}
return index;
}
Or this should do what your code above does:
// We really only need to test the upper and lower bounds.
// If target is greater than max or less than min, then return the bound that it crossed
if (target > max) return max;
if (target < min) return min;
// Otherwise, it's within the bounds, so just return target.
return target;
Or you could do it in one line:
return (target > max) ? max : (target < min) ? min : target;
I need ideas for a simple, lightweight way to get the max and min values of an array of doubles. The trick is I only need the max and min between two indexes in the array.
The built-in arrayOfDoubles.Max() and arrayOfDoubles.Min() will not work, because they check the entire array.
This code will be running constantly and needs to be somewhat efficient. That said, simplicity and readability are more important than speed alone.
Here's one way to get the max and min between two indexes:
double[] array = new double[8] { 3, 1, 15, 5, 11, 9, 13, 7 };
int startIndex = 3;
int endIndex = 6;
// Get max and min between these two indexes in the array
double max = GetMax(array, startIndex, endIndex);
double min = GetMin(array, startIndex, endIndex);
Console.WriteLine("Max = " + max + ", Min = " + min);
Here is the code for GetMax, and GetMin would be very similar:
private static double GetMax(double[] array, int startIndex, int endIndex)
{
double max = double.MinValue;
for (int i = startIndex; i <= endIndex; i++)
{
// Increase max with each bigger value
max = Math.Max(max, array[i]);
}
return max;
}
And the output: Max = 13, Min = 5
The Question: What other ways could I get the same result that might be simpler and wouldn't require too much overhead?
var list = array.Skip(startIndex).Take(endIndex - startIndex + 1).ToList();
var min = list.Min();
var max = list.Max();
You can also do:
var segment = new ArraySegment<double>(array, startIndex, endIndex - startIndex + 1);
var min = segment.Min();
var max = segment.Max();
It should be obvious that finding the minimum and maximum elements in an unsorted array requires an O(n) algorithm because no matter how you do it you do have to examine each element, at least once. So the only optimizations you can hope for are implementation specific and can only bring you gains in terms of the constants.
There is however a clever trick you can employ for finding both minimum and maximum in the array using only 3*[n/2] comparisons. While this is not an asymptotic improvement, it is an improvement of n/2 compared to the typical 2*n comparison that are needed in the straight forward algorithm. So, if you expect to be performing lots of the min/max computations then it may be worth considering it as an option.
The way you do it is like this:
maintain both minimum and maximum elements so far in two variables
at each iteration:
compare the next two elements between each other to determine which one is larger
compare the larger element with the maximum (and swap if necessary)
compare the smaller element with the minimum (and swap if necessary)
You will be executing n/2 iterations of that loop, and 3 comparisons for each iteration for a total of 3*[n/2] operations.
Here's an implementation:
void GetMinMax(double[] array, int start, int end, out double min, out double max)
{
min = array[start];
max = array[start];
if((end - start) % 2 == 0) // if there's an odd number of elements
start = start + 1; // skip the first one
for (int i = start + 1; i <= end; i += 2)
{
if(array[i] > array[i-1])
{
if(array[i] > max) max = array[i];
if(array[i - 1] < min) min = array[i - 1];
} else {
if(array[i - 1] > max) max = array[i - 1];
if(array[i] < min) min = array[i];
}
}
}
You can do this by scanning the array once. This is the standard min/max tracking algorithm that is asked in a bazillion interview questions, so readability shouldn't be an issue.
void GetMinMax(double[] array, int start, int end, out double min, out double max)
{
min = Double.MaxValue;
max = Double.MinValue;
// TODO: error checks for out-of-bounds, null, etc...
for (int i = start; i <= end; ++i)
{
if (array[i] > max) max = array[i];
if (array[i] < min) min = array[i];
}
}
Edit:
Using Usman Zafar's answer to simplify and remove the need for several error checks:
void GetMinMax(IList<double> list, out double min, out double max)
{
// TODO: null/empty check for list.
min = Double.MaxValue;
max = Double.MinValue;
for (int i = 0; i < list.Count; ++i)
{
if (list[i] > max) max = list[i];
if (list[i] < min) min = list[i];
}
}
Now call with any IList<double>, or in your case: new ArraySegment<double>(array, 3, 4).
using the sweet drug that is LINQ:
var res = array.Skip(startIndex).Take(1 + endIndex - startIndex );
var min = res.Min();
var max = res.Max();
I am trying to return maximum element from array using recursion
here is my code
static void Main(string[] args)
{
int[] Array=new int[]{10,233,34};
int _MaxVal = CalculateMax(Array, 0, 0);
Console.WriteLine(_MaxVal);
Console.ReadKey();
}
private static int CalculateMax(int[] Array, int Startpos, int maxval)
{
if (Startpos != Array.Length)
{
if (Array[Startpos] > maxval)
{
maxval = Array[Startpos];
}
CalculateMax(Array, ++Startpos, maxval);
}
return maxval;
}
I am getting MaxVal as 10 .
What is wrong with it ??
Thanks all
You're losing the value of maxval.
Try this:
maxval = CalculateMax(Array, ++Startpos, maxval);
Unless you're doing this as a personal exercise or for an assignment, you could handle this way more gracefully with LINQ:
var maxValue = Array.Max();
To use recursion you should have a stop test and be sure to always launch the next step on a smaller problem.
Try this : (Not sure if Array.SubArray(int) is a real function but that is the idea.
static void Main(string[] args)
{
int[] Array=new int[]{10,233,34};
int _MaxVal = CalculateMax(Array);
Console.WriteLine(_MaxVal);
Console.ReadKey();
}
private static int CalculateMax(int[] Array)
{
if (Array.Length > 0)
{
int maxSubArray = CalculateMax(Array.SubArray(1)); // Use recursive function on the SubArray starting at index 1 (that the smaller problem)
if (maxSubArray > Array[0])
{
return maxSubArray;
} else {
return Array[0];
}
} else {
return 0; // Stop test
}
}
Note : it will not work with negative value.
static void Main(string[] args)
{
int[] Array = new int[] { 10, 233, 34 };
int _MaxVal = CalculateMax(Array);
Console.WriteLine(_MaxVal);
Console.ReadKey();
}
private static int CalculateMax(int[] Array)
{
int max = 0;
for (int i = 0; i < Array.Length; i++)
if (Array[i] > max)
max = Array[i];
return max;
}
OR
var max1 = Array.Max();
var max2 = Array.Concat(new[] { 0 }).Max();
var max3 = Array.OrderByDescending(p => p).FirstOrDefault();
You don't use return value from deeper calls of CalculateMax
Change
CalculateMax(Array, ++Startpos, maxval);
to
maxval = CalculateMax(Array, ++Startpos, maxval);
This way you pass maxval not only forward, but also backwards to main().
As (probably) said before, recursion is not best way to do it, because stack overflow may happen.
You are not using the return value from the recursive call. This:
CalculateMax(Array, ++Startpos, maxval);
should be:
maxval = CalculateMax(Array, ++Startpos, maxval);
Anyway, you are using recursion instead of a loop, which is a very bad way to use recursion. You will be doing recursion as deep as there are items in the array, which means that you have a very slow loop, and you will get a stack overflow if the array is too large.
To use recursion correctly you should divide the work into smaller parts, and use recursion to handle those smaller parts, until the parts are so small that they are trivial.
For example, split the array in half for each level:
int[] Array = new int[]{ 10, 233, 34 };
int _MaxVal = CalculateMax(Array, 0, Array.Length);
Console.WriteLine(_MaxVal);
private static int CalculateMax(int[] array, int start, int length) {
if (length == 1) {
return array[start];
} else {
int half = length / 2;
int first = CalculateMax(array, start, half);
int second = CalculateMax(array, start + half, length - half);
return first > second ? first : second;
}
}
I need to generate bins for the purposes of calculating a histogram. Language is C#. Basically I need to take in an array of decimal numbers and generate a histogram plot out of those.
Haven't been able to find a decent library to do this outright so now I'm just looking for either a library or an algorithm to help me do the binning of the data.
So...
Are there any C# libraries out there that will take in an array of decimal data and output a binned histogram?
Is there generic algorithm for building the bins to be used in generated a histogram?
Here is a simple bucket function I use. Sadly, .NET generics doesn't support a numerical type contraint so you will have to implement a different version of the following function for decimal, int, double, etc.
public static List<int> Bucketize(this IEnumerable<decimal> source, int totalBuckets)
{
var min = source.Min();
var max = source.Max();
var buckets = new List<int>();
var bucketSize = (max - min) / totalBuckets;
foreach (var value in source)
{
int bucketIndex = 0;
if (bucketSize > 0.0)
{
bucketIndex = (int)((value - min) / bucketSize);
if (bucketIndex == totalBuckets)
{
bucketIndex--;
}
}
buckets[bucketIndex]++;
}
return buckets;
}
I got odd results using #JakePearson accepted answer. It has to do with an edge case.
Here is the code I used to test his method. I changed the extension method ever so slightly, returning an int[] and accepting double instead of decimal.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Random rand = new Random(1325165);
int maxValue = 100;
int numberOfBuckets = 100;
List<double> values = new List<double>();
for (int i = 0; i < 10000000; i++)
{
double value = rand.NextDouble() * (maxValue+1);
values.Add(value);
}
int[] bins = values.Bucketize(numberOfBuckets);
PointPairList points = new PointPairList();
for (int i = 0; i < numberOfBuckets; i++)
{
points.Add(i, bins[i]);
}
zedGraphControl1.GraphPane.AddBar("Random Points", points,Color.Black);
zedGraphControl1.GraphPane.YAxis.Title.Text = "Count";
zedGraphControl1.GraphPane.XAxis.Title.Text = "Value";
zedGraphControl1.AxisChange();
zedGraphControl1.Refresh();
}
}
public static class Extension
{
public static int[] Bucketize(this IEnumerable<double> source, int totalBuckets)
{
var min = source.Min();
var max = source.Max();
var buckets = new int[totalBuckets];
var bucketSize = (max - min) / totalBuckets;
foreach (var value in source)
{
int bucketIndex = 0;
if (bucketSize > 0.0)
{
bucketIndex = (int)((value - min) / bucketSize);
if (bucketIndex == totalBuckets)
{
bucketIndex--;
}
}
buckets[bucketIndex]++;
}
return buckets;
}
}
Everything works well when using 10,000,000 random double values between 0 and 100 (exclusive). Each bucket has roughly the same number of values, which makes sense given that Random returns a normal distribution.
But when I changed the value generation line from
double value = rand.NextDouble() * (maxValue+1);
to
double value = rand.Next(0, maxValue + 1);
and you get the following result, which double counts the last bucket.
It appears that when a value is same as one of the boundaries of a bucket, the code as it is written puts the value in the incorrect bucket. This artifact doesn't appear to happen with random double values as the chance of a random number being equal to a boundary of a bucket is rare and wouldn't be obvious.
The way I corrected this is to define what side of the bucket boundary is inclusive vs. exclusive.
Think of
0< x <=1 1< x <=2 ... 99< x <=100
vs.
0<= x <1 1<= x <2 ... 99<= x <100
You cannot have both boundaries inclusive, as the method wouldn't know which bucket to put it in if you have a value that is exactly equal to a boundary.
public enum BucketizeDirectionEnum
{
LowerBoundInclusive,
UpperBoundInclusive
}
public static int[] Bucketize(this IList<double> source, int totalBuckets, BucketizeDirectionEnum inclusivity = BucketizeDirectionEnum.UpperBoundInclusive)
{
var min = source.Min();
var max = source.Max();
var buckets = new int[totalBuckets];
var bucketSize = (max - min) / totalBuckets;
if (inclusivity == BucketizeDirectionEnum.LowerBoundInclusive)
{
foreach (var value in source)
{
int bucketIndex = (int)((value - min) / bucketSize);
if (bucketIndex == totalBuckets)
continue;
buckets[bucketIndex]++;
}
}
else
{
foreach (var value in source)
{
int bucketIndex = (int)Math.Ceiling((value - min) / bucketSize) - 1;
if (bucketIndex < 0)
continue;
buckets[bucketIndex]++;
}
}
return buckets;
}
The only issue now is if the input dataset has a lot of min and max values, the binning method will exclude many of those values and the resulting graph will misrepresent the dataset.