I'm trying to move negative numbers to the left.
using System;
class Class1
{
static void rearrange(int[] arr, int n)
{
int j = 0, temp;
for (int i = 0; i < n; i++)
{
if (arr[i] < 0)
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
j++;
}
}
}
static void printArray(int[] arr, int n)
{
for (int i = 0; i < n; i++)
Console.Write(arr[i] + ",");
}
//Call the Method
public static void Main()
{
int[] arr = { 1, -4, -7, 4, -2, 6, -9 };
int n = arr.Length;
rearrange(arr, n);
printArray(arr, n);
}
}
The question expects the output { -4, -7, -2, -9, 1, 4, 6 }
But my output is { -4, -7, -2, -9, 1, 6, 4 }, because the code is to switch -9 with 4.
How to adjust the code?
Wouldn't it be simpler to use LINQ?
Here is the code which does what you need using LINQ:
var list = new[]{ 1, -4, -7, 4, -2, 6, -9 };
var newList = list.Where(x => x < 0).Union(list.Where(x => x >= 0)).ToList();
Console.WriteLine(string.Join(", ", newList));
Output:
-4, -7, -2, -9, 1, 4, 6
It looks like the problem is that the code is always swapping a negative number with the number that's in the position where the negative number should go. This becomes a problem when there are a few positive numbers in a row, because the order is disturbed when a positive number in a low index is swapped with a negative number in a high index. This happens when i is 4 and -2 is swapped with 1 (so at that moment the array looks like { -4, -7, -2, 4, 1, 6, -9 }); and again when i is 6 and -9 gets swapped with 4, which leaves you with the result that prompted your question.
To resolve this, you have to swap the negative number with the number before it in an inner loop, until the number before it is also negative, so that the numbers retain their relative positioning:
static void Rearrange(int[] arr)
{
// Start at index 1 since the first item can't move left
for (int i = 1; i < arr.Length; i++)
{
if (arr[i] < 0)
{
// Walk backwards from the current index, swapping items as we
// go, until the item in the previous index is also negative
for (int j = i; j > 0; j--)
{
// If previous item is negative, we can stop
if (arr[j - 1] < 0) break;
// Otherwise, swap this item with the previous item
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
}
}
Before the last iteration, the array is in this state:
{ -4, -7, -2, 4, 1, 6, -9}
You algorithm then swaps -9 and 4:
{ -4, -7, -2, -9, 1, 6, 4}
Why would you expect 6 to be the last number in the array?
If you want numbers to be ordered, C# provides an .OrderBy extension method, but that would also change the order of the negative numbers.
Related
I know there are lot of resources on QuickSort but I need a fresh pair of eyes to catch a bug. I have written the QuickSort Algorithm, but it works for small array, but with large array it throws invalid result (last 3-4 elements didn't sort at all).
Test Case 1:
Input: { 5, 7, 2, 8, 10, 15, 14, 16, 16, 19, 20, 19, 3, 1, 5 }
OutPut: 1,2,3,5,10,14,15,16,16,19,20,19,7,5,8 (WRONG)
Test Case 2:
Input: { 5,1,15,2,8}
Output: 1,2,5,8,15
[TestMethod]
public void QuickSort_test()
{
//input
int[] input = InputArray();
//Algo
int n = input.Length-1;
QuickSort(0,n,input);
//matching result
bool isSorted = IsSorted(input);
Assert.AreEqual(true, isSorted);
}
private void QuickSort(int low, int high, int[] arr)
{
if(low< high)
{
//finding pivot correct index
int idxPivot = Partition(low, high, arr);
//Recursive QuickSort, on elements left on pivot and elements right on pivot
int h = high - idxPivot;
QuickSort(low, idxPivot - 1, arr); //left of pivot
QuickSort(idxPivot + 1, h, arr); //right of pivot
}
}
private int Partition(int low, int high, int[] arr)
{
int pivot = arr[high];
int idxp = low - 1; //smaller than pivot
for (int i = low; i < high; i++) //since element at high is already pivot, no need to run loop till that
{
if(arr[i]< pivot) //current ele < pivot . increment pivotsmallerIndex and swap current element with pivot smaller index
// hence making current element as the smaller element from pivot
{
idxp++;
//swapping
int temp = arr[idxp];
arr[idxp] = arr[i];
arr[i] = temp;
}
}
//idxp contains the last smallest element from the pivot
//so swapping pivot with the next element of idxp
int temp1 = arr[idxp + 1];
arr[idxp+1] = pivot;
arr[high] = temp1;
//return index of pivot, since it is added at idxp+1 now
return idxp + 1;
}
public int[] InputArray()
{
return new int[] { 5, 7, 2, 8, 10, 15, 14, 16, 16, 19, 20, 19, 3, 1, 5 };
//return new int[] { 5,1,15,2,8};
}
My task is to find a element in the array that is the same as given value, and then take it to right while maintaining the order of other elements. An example (Test Case):
{1, 2, 0, 1, 0, 1, 0, 3, 0, 1} for value = 0 => {1, 2, 1, 1, 3, 1, 0, 0, 0, 0}
While my code could do that above example, what it could not do is a very specific case: if the element in array equals value and the next element also equals value it will not shift the element. Again a example:
{ 1, int.MinValue, int.MinValue, int.MaxValue, int.MinValue, -1, -3, -9, 1 }, value = int.MinValue
Expected result: { 1, int.MaxValue, -1, -3, -9, 1, int.MinValue, int.MinValue, int.MinValue }
Result with my code: { 1, int.MinValue ,int.MaxValue, -1, -3, -9, 1, int.MinValue, int.MinValue }
I thought shifting is the one solution, is it? I am having a lot of problems with it, I also tried Array.Copy but there were problems the result was always out of range.
How can I make it so that it will shifts/rotates correctly in all cases?
Code:
static void Main(string[] args)
{
int[] source = new int[] { 1, int.MinValue, int.MinValue, int.MaxValue, int.MinValue, -1, -3, -9, 1 };
int value = int.MinValue;
for (int i = 0; i < source.Length; i++)
{
if (source[i] == value)
{
LeftShiftArray(source, i);
}
}
for (int i = 0; i < source.Length; i++)
{
Console.WriteLine(source[i]);
}
}
public static void LeftShiftArray(int[] source, int i)
{
var temp1 = source[i];
for (var j = i; j < source.Length - 1; j++)
{
source[j] = source[j + 1];
}
source[source.Length - 1] = temp1;
}
Now this
I have a simple approach to solve this problem. Run a loop, You keep on counting the numbers which are not equal to your number. And keep assigning to arr[count]. Then increment the count. And then finally you will be left to assign all the remaining numbers with the given number.
static void MoveToEnd(int []arr, int n)
{
int count = 0;
for (int i = 0; i < arr.Length; i++)
if (arr[i] != n)
arr[count++] = arr[i];
while (count < arr.Length)
arr[count++] = n;
}
Please note I have typed this answer from phone, so please avoid typing mistakes.
This is a classic off by one error. Think about it like this:
Let's say you are moving all 0s to the back (value = 0). When you find a zero at some position, let's say source[2], you turn your array from this:
1 1 0 0 1 1
source[2] ^
To this:
1 1 0 1 1 0
source[2] ^
Now that you've shifted the array, the next step in your code is to increase i by 1. That means the next comparison you make will be with source[3]. In the above array, that looks like this:
1 1 0 1 1 0
source[3] ^
Do you see the problem? Let me know if not and I can explain further.
PS. There are a couple of issues with the other code that was posted that will probably stop you from getting full points if you were to turn it in for an assignment :)
I'm having trouble with int[] arrays and adding them to a List<>. I'd like to add the values of my int[] array to something each loop but every time I do this my "something" gets the same value for every element I add. Very annoying. I understand arrays are always reference vars. However even the "new" key word doesn't seem to help. What needs to happen is to add result to some enumerated object like a List or Array or ArrayList.
Here's the codility question:
You are given N counters, initially set to 0, and you have two possible operations on them:
increase(X) − counter X is increased by 1,
max_counter − all counters are set to the maximum value of any counter.
A non-empty zero-indexed array A of M integers is given. This array represents consecutive operations:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max_counter.
For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the values of the counters after each consecutive operation will be:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
The goal is to calculate the value of every counter after all operations.
I copied some code from others and the variable "result" does indeed load the data correctly. I just wanted to copy it back to the main program so I could see it. The only method that works is += add it into a string. Thus losing any efficiency I might have gained.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testarray
{
class Program
{
static void Main(string[] args)
{
int[] A = new int[7];
A[0] = 3;
A[1] = 4;
A[2] = 4;
A[3] = 6;
A[4] = 1;
A[5] = 4;
A[6] = 4;
List<int[]> finish = solution(5, A);
}
public static List<int[]> solution(int N, int[] A)
{
int[] result = new int[N];
int maximum = 0;
int resetlimit = 0;
int iter = 0;
List<int[]> collected_result = new List<int[]>;
for (int K = 0; K < A.Length; K++)
{
if (A[K] < 1 || A[K] > N + 1)
{
throw new InvalidOperationException();
}
if (A[K] >= 1 && A[K] <= N)
{
if (result[A[K] - 1] < resetlimit)
{
result[A[K] - 1] = resetlimit + 1;
}
else
{
result[A[K] - 1]++;
}
if (result[A[K] - 1] > maximum)
{
maximum = result[A[K] - 1];
}
}
else
{
resetlimit = maximum;
result = Enumerable.Repeat(maximum, result.Length).ToArray<int>();
}
collected_result.Add(result);
}
// for (int i = 0; i < result.Length; i++)
//result[i] = Math.max(resetLimit, result[i]);
return collected_result;
}
}
}
This doesn't work, the collected_result ends up like:
(0,0,1,2,0)
(0,0,1,2,0)
(0,0,1,2,0)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
I know it's the line collected_result.Add(result); adding the reference each time to every instance of result in the List<>. Bother. I've tried adding "new" which is a compiler error. Finally in desperation I just added everything to a very long string. Can someone help me figure out how to properly load an object to pass back to main?
Easiest way to go:
Get a copy of your array before adding it to list:
collected_result.Add(result.ToArray());
Here is a Python solution:
def solution(A, N):
lenA = len(A)
k = 0
max_counter_value = 0
counters = [0 for x in range(0, N)]
for k in range(0, lenA):
if A[k] >= 1 and A[k] <= N:
counters[A[k] - 1] += 1
max_counter_value = max(counters)
if A[k] == N + 1:
counters = [max_counter_value for x in range(0, N)]
print counters
A = [3, 4, 4, 6, 1, 4, 4]
N = 5
solution(A, N)
My algorithm should find the greatest right number from the current number in an input array, for example, given the following int[] input:
5, 9, 6, 1, 3, 2
My algorithm will output:
9, 6, 3, 3, 2, 2
Here is my current code:
public static int[] FindGreatestRightNumber(int[] input)
{
var output = new int[input.Length];
for (var i = 0; i < input.Length; i++)
{
int maxRightNumber = (i == input.Length - 1 ? input[i] : 0);
for (var j = i+1; j < input.Length; j++)
{
var currentNumber = input[j];
if (maxRightNumber < currentNumber)
maxRightNumber = currentNumber;
}
output[i] = maxRightNumber;
}
return output;
}
I was told it could be much faster, how? any idea?
UPDATE: Please don't use LINQ in your answers, I would like to get familiar with faster ways to solve the problem using simple code, no LINQ, IEnumerable Extension Methods etc.
You can do this in a single pass from the right hand side. The trick is realizing maxRightVal(n) = max(maxRightVal(n+1), values(n+1)):
var output = new int[input.Length];
output[input.Length-1] = input[input.Length-1];
for(int i = input.Length - 2; i >= 0; i--)
output[i] = output[i+1] > input[i+1] ? output[i+1] : input[i+1];
Why not just using Enumerable.Max() method?
Returns the maximum value in a sequence of Int32 values.
int[] input = new int[] { 5, 9, 6, 1, 3, 2 };
int biggest = input.Max();
Console.WriteLine(biggest); // 9
Here is a DEMO.
Since, I see the question better now, VLad's answer looks the right one.
very simple if you want to skip some items and search the max
int[]arr = {5, 9, 6, 1, 3, 2};
int currentIndex = 2;
int currentValue = 6;
int max = arr.Skip(currentIndex).Where(f => f > currentValue).Max();
EDIT if you want to simply sort an array, then:
int[] sorted = arr.OrderByDescending();
Start from the (n-2)th elements, maintain a current max array which is initialised with nth element. Keep updating it if the current element is greater than the element in max array. Continue this until the first element is reached.
This takes the largest value to the right of each element;
int[] input = {5, 9, 6, 1, 3, 2};
int[] output = input
.Take(input.Length-1)
.Select( (x,i) => input.Skip(i+1).Max()).ToArray();
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);