Related
I have the following question:-
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [−1, −3], the function should return 1.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [−1,000,000..1,000,000].
now i tried this code:-
using System;
// you can also use other imports, for example:
// using System.Collections.Generic;
// you can write to stdout for debugging purposes, e.g.
// Console.WriteLine("this is a debug message");
class Solution
{
public int solution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
int n = 1;
Array.Sort(A);
for (int i = 1; i <= 100000; i++)
{
for (int i2 = 0; i2 <= A.Length - 1; i2++)
{
if (A[i2] == i)
{
n = A[i2] + 1;
break;
}
}
}
return n;
}
}
where my code worked well for these test data:-
A = [1, 2, 3]
A = [−1, −3]
while failed for this one:-
A = [1, 3, 6, 4, 1, 2] where it return 7 instead of 5.
any advice why my code failed on the 3rd test?
Thanks
using System.Linq;
int smallestNumber = Enumerable.Range(1, 100000).Except(A).Min();
I would use following approach that uses a HashSet<int> to check if a given integer is missing:
public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
HashSet<int> hs = new HashSet<int>(A);
for (int i = rangeStart; i <= rangeEnd; i++)
if(!hs.Contains(i)) return i;
return null;
}
A HashSet is a collection if unique values and it's very efficient in lookup items(complexity is O(1)). So you get a very readable and efficient algorithm at the cost of some memory.
Maybe you could optimize it by providing another algorithm in case the array is very large, you don't want to risk an OutOfMemoryException:
public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
if(A.Length > 1_000_000)
{
Array.Sort(A);
for (int i = rangeStart; i <= rangeEnd; i++)
{
int index = Array.BinarySearch(A, i);
if(index < 0) return i;
}
return null;
}
HashSet<int> hs = new HashSet<int>(A);
for (int i = rangeStart; i <= rangeEnd; i++)
if(!hs.Contains(i)) return i;
return null;
}
If you're allowed to sort the array in-place, which means modifying the input parameter value, here's a simple linear probe for the missing value (on top of the sort of course).
Here's the pseudo-code:
Sort the array
Skip all negatives and 0's at the start
Loopify the following:
Expect 1, if not found at current location return 1
Skip all 1's
Expect 2, if not found at current location return 2
Skip all 2's
Expect 3, if not found at current location return 3
Skip all 3's
... and so on for 4, 5, 6, etc. until end of array
If we get here, return currently expected value which should've been at the end
Here's the code:
public static int FirstMissingValue(int[] input)
{
Array.Sort(input);
int index = 0;
// Skip negatives
while (index < input.Length && input[index] < 1)
index++;
int expected = 1;
while (index < input.Length)
{
if (input[index] > expected)
return expected;
// Skip number and all duplicates
while (index < input.Length && input[index] == expected)
index++;
expected++;
}
return expected;
}
Test-cases:
Console.WriteLine(FirstMissingValue(new[] { 1, 3, 6, 4, 1, 2 }));
Console.WriteLine(FirstMissingValue(new[] { 1, 2, 3 }));
Console.WriteLine(FirstMissingValue(new[] { -1, -3 }));
output:
5
4
1
Your alg won't work in case input array becomes like this: [1,2-1,1,3,5]. I did this based on your alg. Give it a try:
int[] a = new int[] { -1, -2};
IEnumerable<int> uniqueItems = a.Distinct<int>().Where(x => x > 0);
if (uniqueItems.Count() == 0)
{
Console.WriteLine("result: 1");
}
else
{
Array asList = uniqueItems.ToArray();
Array.Sort(asList);
for (int i = 1; i <= 100000; i++)
{
if ((int)asList.GetValue(i - 1) != i)
{
Console.WriteLine("result: " + i);
break;
}
}
}
you can try like this.
public static int solution(int[] A)
{
int smallest = -1;
Array.Sort(A);
if(A[0] > 1)
return 1;
for(int i = 0; i < A.Length; i++)
{
if(A.Length != i+1 && A[i] + 1 != A[i + 1] && A[i+1] > 0)
{
smallest = A[i]+1;
break;
}
else if(A[i] > 0 && A.Length == i+1)
{
smallest = A[i] + 1;
}
}
return smallest > 0 ? smallest:1;
}
Here's the approach that uses O(N) partitioning followed by an O(N) search. This approach does not use any additional storage, but it DOES change the contents of the array.
This code was converted from here. Also see this article.
I've added comments to try to explain how the second stage findSmallestMissing() works. I've not commented the partitioning method, since that's just a variant of a standard partition as might be used in a QuickSort algorithm.
static class Program
{
public static void Main()
{
Console.WriteLine(FindSmallestMissing(1, 3, 6, 4, 1, 2));
Console.WriteLine(FindSmallestMissing(1, 2, 3));
Console.WriteLine(FindSmallestMissing(-1, -3));
}
public static int FindSmallestMissing(params int[] array)
{
return findSmallestMissing(array, partition(array));
}
// Places all the values > 0 before any values <= 0,
// and returns the index of the first value <= 0.
// The values are unordered.
static int partition(int[] arr)
{
void swap(int x, int y)
{
var temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
int pIndex = 0; // Index of pivot.
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > 0) // pivot is 0, hence "> 0"
swap(i, pIndex++);
}
return pIndex;
}
// This is the clever bit.
// We will use the +ve values in the array as flags to indicate that the number equal to that index is
// present in the array, by making the value negative if it is found in the array.
// This way we can store both the original number AND whether or not the number equal to that index is present
// in a single value.
//
// Given n numbers that are all > 0, find the smallest missing number as follows:
//
// For each array index i in (0..n):
// val = |arr[i]| - 1; // Subtract 1 so val will be between 0 and max +ve value in original array.
// if (val is in range) // If val beyond the end of the array we can ignore it
// and arr[val] is non-negative // If already negative, no need to make it negative.
// make arr[val] negative
//
// After that stage, we just need to find the first positive number in the array, which indicates that
// the number equal to that index + 1 is missing.
// n = number of values at the start of the array that are > 0
static int findSmallestMissing(int[] arr, int n)
{
for (int i = 0; i < n; i++)
{
int val = Math.Abs(arr[i]) - 1;
if (val < n && arr[val] >= 0)
arr[val] = -arr[val];
}
for (int i = 0; i < n; i++)
{
if (arr[i] > 0) // Missing number found.
return i + 1;
}
return n + 1; // No missing number found.
}
}
class Program
{
static void Main(string[] args)
{
int [] A = new int[] {1, 2, 3};
int n = 0;
bool found = false;
Array.Sort(A);
for (int i = 1; i <= 100000; i++) {
for (int x = 0; x <= A.Length - 1; x++) {
int next = (x + 1) < A.Length ? (x + 1): x;
if (A[x] > 0 && (A[next] - A[x]) > 0) {
n = A[x] + 1;
found = true;
break;
}
}
if(found) {
break;
}
}
Console.WriteLine("Smallest number: " + n);
}
}
int smallestNumber=Enumerable.Range(1,(int.Parse(A.Length.ToString())+1)).Except(A).Min();
Array.Sort(A);
for (int number = 1; number <= 100000; number++)
{
for (int num = number; i2 <= A.Length - 1; num++)
{
if (A[num] == number)
{
smallestNumber = A[num] + 1;
break;
}
}
}
return smallestNumber;
}
The easiest one :)
class Solution
{
public int solution(int[] array)
{
int[] onlyPositiveArray = array.Where(a => a > 0).OrderBy(a => a).Distinct().ToArray();
int smallestNumber = 1;
foreach (var number in onlyPositiveArray)
{
if (smallestNumber != number)
{
break;
}
smallestNumber ++;
}
if (!onlyPositiveArray.Contains(smallestNumber ))
{
return smallestNumber;
}
else
{
return smallestNumber + 1;
}
}
}
PHP Solution:
function solution($A) {
// write your code in PHP7.0
// sort array
sort($A);
// get the first
$smallest = $A[0];
// write while
while( in_array(($smallest),$A) || (($smallest) < 1 ) )
{
$smallest++;
}
return $smallest;
}
My solution, also if someone could test how performant it is?
public int solution(int[] N) {
if (N.Length == 0)
return 1;
else if (N.Length == 1)
return N[0] >= 0 ? N[0] + 1 : 1;
Array.Sort(N);
int min = Array.Find(N, IsUnderZero);
if (min ==
default)
return 1;
HashSet < int > hashSet = new HashSet < int > (N);
int max = N[N.Length - 1];
for (int i = min + 1; i <= max + 1; i++) {
if (!hashSet.Contains(i) && i > 0)
return i;
}
return max + 1;
bool IsUnderZero(int i) => i <= 0;
}
Try the below:
public static int MinIntegerGreaterThanZeroInArray(int[] A)
{
int minInt;
if (A.Length > 0)
{
Array.Sort(A);
for (minInt = 1; minInt <= A.Length; minInt++)
{
int index = Array.BinarySearch(A, minInt);
if (index < 0) return minInt;
}
return minInt;
}
//Array is empty.
throw new InvalidOperationException();
}
public static int Smallest(int[] A)
{
int maxPositiveInt = 1;
HashSet<int> NumDic = new HashSet<int>();
for (int i = 0; i < A.Length; i++)
{
if (A[i] <= 0)
{
continue;
}
if (!NumDic.Contains(A[i]))
{
NumDic.Add(A[i]);
}
maxPositiveInt = Math.Max(A[i], maxPositiveInt);
}
//All numbers are negative
if (NumDic.Count == 0)
{
return 1;
}
int smallestinteger = 1;
for (int i = 0; i < A.Length; i++)
{
if (A[i] <= 0)
{
continue;
}
if (!NumDic.Contains(smallestinteger))
{
return smallestinteger;
}
else
{
smallestinteger++;
}
}
return maxPositiveInt + 1;
}
static void Main(string[] args)
{
Console.WriteLine(solution(new int[]{1, 3, 6, 4, 1, 2}));
}
public static int solution(int[] A)
{
Array.Sort(A);
int smallest = A[0];
while (A.Contains(smallest+1)|| (smallest+1)<1)
{
smallest++;
}
return smallest +1;
}
I'm looking for a backtrack algorithm in C# that will search the correct numbers from a List<int> where the sum of these numbers is closest to X.
e.g: list={5,1,3,5}, X = 10 the output should be (5,5) (5+5 is the closest to 10)
it cant be (3,3,3,1) because I can't use a number more than once from the List. (if we have two piece from number 3 than we can use two times)
e.g.2: list={4,1,3,4}, X=10 the output should be {4,1,3} and {1,3,4}.
I got this kind of code to start, but i cant do it;
(I know there are wikipedia about backtracking, and knapsack, but it doesn't help me)
static void BackTrack(int lvl, bool Van, int[] E)
{
int i = -1;
do
{
i++;
if (ft(lvl, i))
{
int k = 0;
while (k < szint && fk(E[i], E[k]))
{
k++;
}
if (k == szint)
{
E[k] = R[lvl,i];
if (lvl == E.Length - 1)
{
}
else
{
BackTrack(lvl + 1, Van, E);
}
}
}
}
while (i < E.Length - 1);
}
static bool fk(int nr, int nr2)
{
return (nr + nr2 <= 10);
}
static bool ft(int lvl, int nr)
{
return true;
}
From what i am reading, this example:
e.g.2: list={4,1,3,4}, X=10 the output should be {4,1,3} and {1,3,4}.
output should be {4,1,4} 9 is closer then 8.
Here is what i did. it works with the two examples you gave.
public List<int> highest(List<int> list, int number)
{
//probably a better way to do this
IEnumerable<int> orderedList = list.OrderByDescending(item => item);
var currentNumber = 0;
List<int> combinationResult = new List<int>();
foreach (var item in orderedList)
{
var temp = currentNumber + item;
if (temp <= number)
{
combinationResult.Add(item);
currentNumber = temp;
}
}
return combinationResult;
}
I would like to know how I can count the number of the comparisons made by the HeapSort I got on rosettacode? I tried to count it by adding a variable and each time the comparison method gets called this variable gets incremented. But somehow I dont get the right results. I think I have to override the comparison method somehow and use a getter and setter to increment a count variable. A hint will be highly appreciated...
using System;
using System.Collections.Generic;
using System.Text;
public class Program
{
public static void HeapSort<T>(T[] array)
{
HeapSort<T>(array, 0, array.Length, Comparer<T>.Default);
}
public static void HeapSort<T>(T[] array, int offset, int length, IComparer<T> comparer)
{
HeapSort<T>(array, offset, length, comparer.Compare);
}
public static void HeapSort<T>(T[] array, int offset, int length, Comparison<T> comparison)
{
int count = 0;
// build binary heap from all items
for (int i = 0; i < length; i++)
{
int index = i;
T item = array[offset + i]; // use next item
// and move it on top, if greater than parent
while (index > 0 &&
comparison(array[offset + (index - 1) / 2], item) < 0)
{
int top = (index - 1) / 2;
array[offset + index] = array[offset + top];
index = top;
}
count++;
array[offset + index] = item;
//Console.WriteLine(item);
}
for (int i = length - 1; i > 0; i--)
{
// delete max and place it as last
T last = array[offset + i];
array[offset + i] = array[offset];
int index = 0;
// the last one positioned in the heap
while (index * 2 + 1 < i)
{
int left = index * 2 + 1, right = left + 1;
if (right < i && comparison(array[offset + left], array[offset + right]) < 0)
{
if (comparison(last, array[offset + right]) > 0)
{
break;
}
array[offset + index] = array[offset + right];
index = right;
//Console.WriteLine("1st if ");
}
else
{
if (comparison(last, array[offset + left]) > 0)
{
break;
}
count++;
array[offset + index] = array[offset + left];
index = left;
//Console.WriteLine("2nd if ");
}
}
array[offset + index] = last;
//Console.WriteLine("\nRun");
//for (int j = 0; j <= 3; j++)
// Console.WriteLine(array[j]);
}
Console.WriteLine("\nThe case needed " + count + " comparisons!");
}
static void Main()
{
// hardcoded arrays according to the assignment
int[] arrOne = { 503, 087, 512, 061, 908, 170, 897, 275, 653, 426, 154, 509, 612, 677, 765, 703 };
int[] arrTwo = { 908, 897, 765, 703, 677, 653, 612, 512, 509, 503, 426, 275, 170, 154, 087, 061 };
int[] arrThree = { 4, 7, 2, 3 };
int[] arrFour = { 0, 1, 0, 0, 1, 1, 1, 0, 1, 0 };
int n = 0;
string c = String.Empty;
// the application runs until the user agrees to quit at the end of a sorting run
do
{
// displays the 4 arrrays
Console.WriteLine("Assignment: Given are 4 different arrays; You have the choice which one you want to sort.");
Console.WriteLine("\n1. Knuths entry sequence:\n 503,087,512,061,908,170,897,275,653,426,154,509,612,677,765,703");
Console.WriteLine("\n2. Knuths entry sequence descended:\n 908,897,765,703,677,653,612,512,509,503,426,275,170,154,087,061");
Console.WriteLine("\n3. Just one number:\n 300");
Console.WriteLine("\n4. A set of 0 and 1:\n 0,1,0,0,1,1,1,0,1,0");
Console.WriteLine("\n Which array do you want to sort?");
n = Convert.ToInt32(Console.ReadLine());
// creating an comparer instance
//var comp = new CountingComparer<int>();
Console.Clear();
switch (n)
{
case 1:
HeapSort(arrOne);
DisplayArray(arrOne);
break;
case 2:
HeapSort(arrTwo);
DisplayArray(arrTwo);
break;
case 3:
HeapSort(arrThree);
DisplayArray(arrThree);
break;
case 4:
HeapSort(arrFour);
DisplayArray(arrFour);
break;
default:
Console.WriteLine("\nArray does not exist!");
break;
}
//Console.WriteLine("\nThe case needed " + comp.Count + " comparisons!");
Console.WriteLine("\nDo you want to quit the application? (y/n) ");
c = Console.ReadLine();
Console.Clear();
}
while (c != "y");
}
public static void DisplayArray(int[] arr)
{
Console.WriteLine("\nSorted Array!\n");
for (int i = 0; i < arr.Length; i++)
Console.WriteLine(" " + arr[i]);
}
}
I think doing the count in the compare method is a good idea. Here's a quick and dirty way:
public class Program
{
public static int Count = 0;
public static int MyCompare<T>(T first, second)
{
Count++;
return Comparer<T>.Default.Compare(first, second);
}
// Update your first sort to use the new compare.
public static void HeapSort<T>(T[] array)
{
HeapSort<T>(array, 0, array.Length, MyCompare);
}
// Now all of the rest of your original code inside of Program.
}
Set Count to 0 before calling the sorts, then read count after the sorting is done. I confirmed that on the first sort, it does get set to 85, like you expect.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I am trying to develop Max Sub Array Problem in C#
And my code is
try
{
int[] Values = { 9, 1, 4, 15, -5, -41, -8, 78, 145, 14 };//Will be executed once '1'
int StartIndex = 0;//Will be executed once '1'
double Sum = 0;//Will be executed once '1'
double Temp = 0;//Will be executed once '1'
double Max = 0;//Will be executed once '1'
do
{
for (int i = 0; i < Values.Length; i++)//1+(N+1)+N
{
Sum = Values[StartIndex];
if (StartIndex < i)
{
for (int j = StartIndex+1; j <= i; j++)
{
Sum += Values[j];
}
if (Sum > Temp)
{
Max = Sum;
Temp = Sum;
}
}
}
StartIndex++;
} while (StartIndex<Values.Length);
MessageBox.Show("The Max Value is " + Max);
}
catch { }
I would like to know if this is the best approach to solve this algorithm as I am trying to minimize the time complexity
Thank you all for your time
There's an O(N) algorithm presented here: http://en.wikipedia.org/wiki/Maximum_subarray_problem
It doesn't actually give you the subarray, just the maximal value of the subarray.
Note the important restriction that the input array must contain at least one positive (nonzero) number.
I have modified it to return the range as well as the maximal value:
using System;
namespace Demo
{
public static class Program
{
public static void Main(string[] args)
{
//int[] numbers = new[] { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
//int[] numbers = new[] { 1, 1, 1, 1, 1, 1, 1, 1 };
int[] numbers = new[] {9, 1, 4, 15, -5, -41, -8, 78, 145, 14};
var result = FindMaximumSubarray(numbers);
Console.WriteLine("Range = {0}..{1}, Value = {2}", result.StartIndex, result.EndIndex, result.Value);
}
public static MaximumSubarray FindMaximumSubarray(int[] numbers)
{
int maxSoFar = numbers[0];
int maxEndingHere = numbers[0];
int begin = 0;
int startIndex = 0;
int endIndex = 0;
for (int i = 1; i < numbers.Length; ++i)
{
if (maxEndingHere < 0)
{
maxEndingHere = numbers[i];
begin = i;
}
else
{
maxEndingHere += numbers[i];
}
if (maxEndingHere > maxSoFar)
{
startIndex = begin;
endIndex = i;
maxSoFar = maxEndingHere;
}
}
return new MaximumSubarray
{
StartIndex = startIndex,
EndIndex = endIndex,
Value = maxSoFar
};
}
public struct MaximumSubarray
{
public int StartIndex;
public int EndIndex;
public int Value;
}
}
}
time complexity of your code is O(n^3), but you can improve it with two renovations and change it to O(N^2). but there is a better algorithm or this that designed by the dynamic programming.
this solution solve it in matrix array.
Note: maximum default value should be set to the infinite negative.
This is a code from the wiki:
A variation of the problem that does not allow zero-length subarrays to be returned in the case that the entire array consists of negative numbers can be solved with the following code, expressed here in C++ Programming Language.
int sequence(std::vector<int>& numbers)
{
// Initialize variables here
int max_so_far = numbers[0], max_ending_here = numbers[0];
size_t begin = 0;
size_t begin_temp = 0;
size_t end = 0;
// Find sequence by looping through
for(size_t i = 1; i < numbers.size(); i++)
{
// calculate max_ending_here
if(max_ending_here < 0)
{
max_ending_here = numbers[i];
begin_temp = i;
}
else
{
max_ending_here += numbers[i];
}
// calculate max_so_far
if(max_ending_here > max_so_far )
{
max_so_far = max_ending_here;
begin = begin_temp;
end = i;
}
}
return max_so_far ;
}
Divide-and-Conquer realization with O(N*logN) complexity was described in Inroduction to Algorithms: CLRS, Chapter 4 Divide-and-Conquer 4.1 The maximum-subarray problem. C# port from.
class Program {
static void Main(string[] args) {
int[] values = { 9, 1, 4, 15, -5, -41, -8, 78, 145, 14 };
Console.WriteLine(FindMaxSubarray(values, 0, values.Length - 1));
}
public struct MaxSubArray {
public int Low;
public int High;
public int Sum;
public override string ToString() {
return String.Format("From: {0} To: {1} Sum: {2}", Low, High, Sum);
}
}
private static MaxSubArray FindMaxSubarray(int[] a, int low, int high) {
var res = new MaxSubArray {
Low = low,
High = high,
Sum = a[low]
};
if (low == high) return res;
var mid = (low + high) / 2;
var leftSubarray = FindMaxSubarray(a, low, mid);
var rightSubarray = FindMaxSubarray(a, mid + 1, high);
var crossingSubarray = FindMaxCrossingSubarray(a, low, mid, high);
if (leftSubarray.Sum >= rightSubarray.Sum &&
leftSubarray.Sum >= crossingSubarray.Sum)
return leftSubarray;
if (rightSubarray.Sum >= leftSubarray.Sum &&
rightSubarray.Sum >= crossingSubarray.Sum)
return rightSubarray;
return crossingSubarray;
}
private static MaxSubArray FindMaxCrossingSubarray(int[] a, int low, int mid, int high) {
var maxLeft = 0;
var maxRight = 0;
var leftSubarraySum = Int32.MinValue;
var rightSubarraySum = Int32.MinValue;
var sum = 0;
for (var i = mid; i >= low; i--) {
sum += a[i];
if (sum <= leftSubarraySum) continue;
leftSubarraySum = sum;
maxLeft = i;
}
sum = 0;
for (var j = mid + 1; j <= high; j++) {
sum += a[j];
if (sum <= rightSubarraySum) continue;
rightSubarraySum = sum;
maxRight = j;
}
return new MaxSubArray {
Low = maxLeft,
High = maxRight,
Sum = leftSubarraySum + rightSubarraySum
};
}
}
Try this
static void Main()
{
try
{
int[] Values = { 9, 1, 4, 15, -5, -41, -8, 78, 145, 14 };//Will be executed once '1'
int max_ending_here = 0;
int max_so_far = 0;
foreach(int x in Values)
{
max_ending_here = Math.Max(0, max_ending_here + x);
max_so_far = Math.Max(max_so_far, max_ending_here);
}
Console.WriteLine("The Max Value is " + max_so_far);
Console.ReadKey();
}
catch { }
}
Reference Source
I found quicksort algorithm from this book
This is the algorithm
QUICKSORT (A, p, r)
if p < r
q = PARTITION(A, p, r)
QUICKSORT(A, p, q-1)
QUICKSORT(A, q+1, r)
PARTITION(A, p, r)
x=A[r]
i=p-1
for j = p to r - 1
if A <= x
i = i + 1
exchange A[i] with A[j]
exchange A[i+1] with A[r]
return i + 1
And I made this c# code:
private void quicksort(int[] input, int low, int high)
{
int pivot_loc = 0;
if (low < high)
pivot_loc = partition(input, low, high);
quicksort(input, low, pivot_loc - 1);
quicksort(input, pivot_loc + 1, high);
}
private int partition(int[] input, int low, int high)
{
int pivot = input[high];
int i = low - 1;
for (int j = low; j < high-1; j++)
{
if (input[j] <= pivot)
{
i++;
swap(input, i, j);
}
}
swap(input, i + 1, high);
return i + 1;
}
private void swap(int[] ar, int a, int b)
{
temp = ar[a];
ar[a] = ar[b];
ar[b] = temp;
}
private void print(int[] output, TextBox tbOutput)
{
tbOutput.Clear();
for (int a = 0; a < output.Length; a++)
{
tbOutput.Text += output[a] + " ";
}
}
When I call function like this quicksort(arr,0,arr.Length-1); I get this error An unhandled exception of type 'System.StackOverflowException' occurred it pass empty array... when call function like this quicksort(arr,0,arr.Length); I get error Index was outside the bounds of the array. on this line int pivot = input[high]; but array passed successfully.
I also want to print it like this print(input,tbQuick); but where to place it so it would print when quicksort finished?
You did not properly implement the base case termination, which causes quicksort to never stop recursing into itself with sublists of length 0.
Change this:
if (low < high)
pivot_loc = partition(input, low, high);
quicksort(input, low, pivot_loc - 1);
quicksort(input, pivot_loc + 1, high);
to this:
if (low < high) {
pivot_loc = partition(input, low, high);
quicksort(input, low, pivot_loc - 1);
quicksort(input, pivot_loc + 1, high);
}
In addition to Deestan's answer, you also have this wrong:
for (int j = low; j < high-1; j++)
It should be:
for (int j = low; j < high; j++)
Just in case you want some shorter code for Quicksort:
IEnumerable<int> QuickSort(IEnumerable<int> i)
{
if (!i.Any())
return i;
var p = (i.First() + i.Last) / 2 //whichever pivot method you choose
return QuickSort(i.Where(x => x < p)).Concat(i.Where(x => x == p).Concat(QuickSort(i.Where(x => x > p))));
}
Get p (pivot) with whatever method is suitable of course.
This is the shortest implementation of Quick Sort algorithm (Without StackOverflowException)
IEnumerable<T> QuickSort<T>(IEnumerable<T> i) where T :IComparable
{
if (!i.Any()) return i;
var p = i.ElementAt(new Random().Next(0, i.Count() - 1));
return QuickSort(i.Where(x => x.CompareTo(p) < 0)).Concat(i.Where(x => x.CompareTo(p) == 0)).Concat(QuickSort(i.Where(x => x.CompareTo(p) > 0)));
}
A Simple Quick Sort Implementation.
https://github.com/bharathkumarms/AlgorithmsMadeEasy/blob/master/AlgorithmsMadeEasy/QuickSort.cs
using System;
using System.Collections.Generic;
using System.Linq;
namespace AlgorithmsMadeEasy
{
class QuickSort
{
public void QuickSortMethod()
{
var input = System.Console.ReadLine();
string[] sInput = input.Split(' ');
int[] iInput = Array.ConvertAll(sInput, int.Parse);
QuickSortNow(iInput, 0, iInput.Length - 1);
for (int i = 0; i < iInput.Length; i++)
{
Console.Write(iInput[i] + " ");
}
Console.ReadLine();
}
public static void QuickSortNow(int[] iInput, int start, int end)
{
if (start < end)
{
int pivot = Partition(iInput, start, end);
QuickSortNow(iInput, start, pivot - 1);
QuickSortNow(iInput, pivot + 1, end);
}
}
public static int Partition(int[] iInput, int start, int end)
{
int pivot = iInput[end];
int pIndex = start;
for (int i = start; i < end; i++)
{
if (iInput[i] <= pivot)
{
int temp = iInput[i];
iInput[i] = iInput[pIndex];
iInput[pIndex] = temp;
pIndex++;
}
}
int anotherTemp = iInput[pIndex];
iInput[pIndex] = iInput[end];
iInput[end] = anotherTemp;
return pIndex;
}
}
}
/*
Sample Input:
6 5 3 2 8
Calling Code:
QuickSort qs = new QuickSort();
qs.QuickSortMethod();
*/
Code Implemented with Iteration With last element as Pivot
<code>https://jsfiddle.net/zishanshaikh/5zxvwoq0/3/ </code>
function quickSort(arr,l,u) {
if(l>=u)
{
return;
}
var pivot=arr[u];
var pivotCounter=l;
for(let i=l;i<u;i++)
{
if(arr[i] <pivot )
{
var temp= arr[pivotCounter];
arr[pivotCounter]=arr[i] ;
arr[i]=temp;
pivotCounter++;
}
}
var temp2= arr[pivotCounter];
arr[pivotCounter]=arr[u] ;
arr[u]=temp2;
quickSort(arr,pivotCounter+1,u);
quickSort(arr,0,pivotCounter-1);
}
<code>https://jsfiddle.net/zishanshaikh/exL9cdoe/1/</code>
Code With first element as Pivot
//Logic For Quick Sort
function quickSort(arr,l,u) {
if(l>=u)
{
return;
}
var pivot=arr[l];
var pivotCounter=l+1;
for(let i=l+1;i<u;i++)
{
if(arr[i] <pivot )
{
var temp= arr[pivotCounter];
arr[pivotCounter]=arr[i] ;
arr[i]=temp;
pivotCounter++;
}
}
var j=pivotCounter-1;
var k=l+1;
while(k<=j)
{
var temp2= arr[k-1];
arr[k-1]=arr[k] ;
arr[k]=temp2;
k++;
}
arr[pivotCounter-1]=pivot;
quickSort(arr,pivotCounter,u);
quickSort(arr,0,pivotCounter-2);
}
A simple generic C# implementation of QuickSort, can use first or last value or any other intermediate value for pivot
using System;
namespace QuickSort
{
class Program
{
static void Main(string[] args)
{
int[] arInt = { 6, 4, 2, 8, 4, 5, 4, 5, 4, 5, 4, 8, 11, 1, 7, 4, 13, 5, 45, -1, 0, -7, 56, 10, 57, 56, 57, 56 };
GenericQuickSort<int>.QuickSort(arInt, 0, arInt.Length - 1);
string[] arStr = { "Here", "Is", "A", "Cat", "Really", "Fast", "And", "Clever" };
GenericQuickSort<string>.QuickSort(arStr, 0, arStr.Length - 1); ;
Console.WriteLine(String.Join(',', arInt));
Console.WriteLine(String.Join(',', arStr));
Console.ReadLine();
}
}
class GenericQuickSort<T> where T : IComparable
{
public static void QuickSort(T[] ar, int lBound, int uBound)
{
if (lBound < uBound)
{
var loc = Partition(ar, lBound, uBound);
QuickSort(ar, lBound, loc - 1);
QuickSort(ar, loc + 1, uBound);
}
}
private static int Partition(T[] ar, int lBound, int uBound)
{
var start = lBound;
var end = uBound;
var pivot = ar[uBound];
// switch to first value as pivot
// var pivot = ar[lBound];
while (start < end)
{
while (ar[start].CompareTo(pivot) < 0)
{
start++;
}
while (ar[end].CompareTo(pivot) > 0)
{
end--;
}
if (start < end)
{
if (ar[start].CompareTo(ar[end]) == 0)
{
start++;
}
else
{
swap(ar, start, end);
}
}
}
return end;
}
private static void swap(T[] ar, int i, int j)
{
var temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
}
}
}
Output:
-7,-1,0,1,2,4,4,4,4,4,4,5,5,5,5,6,7,8,8,10,11,13,45,56,56,56,57,57
A,And,Cat,Clever,Fast,Here,Is,Really
One important thing to notice here is that this optimized and simple code properly handles duplicates. I tried several posted quick sort code. Those do not give correct result for this (integer array) input or just hangs, such as https://www.w3resource.com/csharp-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-9.php and http://www.softwareandfinance.com/CSharp/QuickSort_Iterative.html. Therefore, if author also wants to use the code which handles duplicates this would be a good reference.