Duplicate values in an int array (best performance) - c#

I have an array of numbers that have some duplicate values.
I want to find the first two duplicate numbers.
The real problem is it must be in best performance and I cant use LINQ it must be in classic codes.
The real question is about best performance so it means best answer is the fastest language and fastest algorithm.
I tried it in C#:
int[] numbers = {5, 2, 10, 18, 55, 100, 10, 50, 23, 6, 14, 25, 12};
int result1 = -1;
int result2 = -1;
for (int i = 0; i < numbers.Length; i++)
{
for (int j = 0; j < numbers.Length; j++)
{
if (numbers[j] == numbers[i] & i != j)
{
result2 = j;
result1 = i;
J = numbers.Length; //this will cause loop exit.
i = numbers.Length; //this will cause first loop to exit.
}
}
}
Console.Write("The result of search is {0} and {1}", result1, result2);
Console.ReadLine();
I will appreciate any answers ;)

Use a dictionary to store the numbers and where you found them, and when you find one that exists in the dictionary, you have your duplicate and its position. Adding and locating items in a dictionary are O(1) operations, so the algorighm is an O(n) operation:
int[] numbers = { 5, 2, 10, 18, 55, 100, 10, 50, 23, 6, 14, 25, 12 };
Dictionary<int, int> found = new Dictionary<int,int>();
int result1 = -1, result2 = -1;
for (int i = 0; i < numbers.Length; i++) {
int number = numbers[i];
int pos;
if (found.TryGetValue(number, out pos)) {
result1 = pos;
result2 = i;
break;
}
found.Add(number, i);
}
Console.Write("The result of search is {0} and {1}", result1, result2);
Console.ReadLine();
For some additional performance you can preallocate space for all the items in the dictionary that it might need. This uses more memory in the average case, but keeps the dictionary from repeatedly allocating more space when it grows:
Dictionary<int, int> found = new Dictionary<int,int>(numbers.Length);

Related

C# how to count how many numbers in an array that are not within a specifc number

the input is like this
100 5
0 10
0 5
75 95
12 17
13 14
and the output is 65
so i want the program to count which numbers from 0-100 are not in the array.
this is how i started
static void Main(string[] args)
{
string input1 = Console.ReadLine();
int roadlength = Convert.ToInt32(input1.Split(" ")[0]);
int stagecnt = Convert.ToInt32(input1.Split(" ")[1]);
int[] startpoint = new int[stagecnt];
int[] endpoint = new int[stagecnt];
int km = 0;
for (int i = 0; i < stagecnt; i++)
{
string input2 = Console.ReadLine();
startpoint[i] = Convert.ToInt32(input2.Split(' ')[0]);
endpoint[i] = Convert.ToInt32(input2.Split(' ')[1]);
}
for (int i = 0; i < stagecnt; i++)
{
Let's count distinct numbers that are in 0..100 range and then subtract from total number in 0..100 range:
using System.Linq;
...
int[] data = new int[] {
100, 5, 0, 10, 0, 5, 75, 95, 12, 17, 13, 14,
};
...
int min = 0;
int max = 100;
int result = max - min + 1 - data
.Where(item => item >= min && item <= max)
.Distinct()
.Count();
you are complicating the problem, it's very simple.
Initialize an array/list with the given range.
and check all your input items one by one whether they are present in the first carry. and if not present then just increment the count.
though complexity is high but its simplest solution.
int[] items = ;
int start = 1;
int end = 100;
int[] arr = Enumerable.Range(start, end - start).ToArray();
int count = 0;
for(int i = 0; i < arr.Length; i++)
{
if (!items.Contains(arr[i]))
{
count++;
}
}
If you want to count missing integers in your array, compared to all between 1 and 100:
int[] array = {1,2,3,4,5};
HashSet<int> allBetween1And100 = Enumerable.Range(1, 100).ToHashSet();
allBetween1And100.ExceptWith(array); // removes all from the set which are not in array
int countMissing = allBetween1And100.Count; // 95
The advantage of this approach is that you even have a collection with the missing. Of course this needs some memory, so if you don't need them, prefer a simple loop.

Bubblesort Issue C# [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I have a small issue to get my bubble sort algorithm to run correctly in C# but I can't figure out my mistake.
For ex. Random Input:
23,20, 17, 11, 17, 18, 4, 1, 16, 11
Output
20, 17, 11, 17, 18, 4, 1, 16, 11, 23
public class BubbleSort
{
public static void Start()
{
Console.WriteLine("This is a BubbleSort Program!");
Console.WriteLine("Pease enter the amount of Numbers to sort:");
int userNumber = int.Parse(Console.ReadLine());
int[] randomNumbers = new int[userNumber]; //Create an array of a random lengh (user decides)
Random r = new Random();
for (int i = 0; i < userNumber; i++)
{
randomNumbers[i] = r.Next(1, 25); //fill array with random numbers between 1 and 25
}
for (int i = 0; i < userNumber; i++)
{
Console.Write(" " + randomNumbers[i]); //write down the Array numbers unsorted
}
Console.ReadKey();
Console.WriteLine("");
bool getSwapper = true;
while (getSwapper) //Runs as long as there are numbers to sort
{
for (int i = 1; i < randomNumbers.Length; i++)
{
int tempNumber = 0;
if (randomNumbers[i - 1] > randomNumbers[i])
{
tempNumber = randomNumbers[i - 1]; //safe the bigger number in a temp var
randomNumbers[i - 1] = randomNumbers[i]; //overwrites the bigger number with the smaller one
randomNumbers[i] = tempNumber; //overwrites the smaller with the bigger one
getSwapper = true; //sets swapper to true
}
}
for (int i = 0; i < randomNumbers.Length; i++)
{
Console.Write(" " + randomNumbers[i]); //lists the sorted numbers of the array
}
Console.ReadKey();
}
}
}
}
You have two issues:
You should reset getSwapper to false.
You print the randomNumbers too early when they are not sorted yet.
Code:
bool getSwapper = true;
while (getSwapper) //Runs as long as there are numbers to sort
{
getSwapper = false; // <- reset getSwagger or we'll have an infinite loop;
for (int i = 1; i < randomNumbers.Length; i++)
{
int tempNumber = 0;
if (randomNumbers[i - 1] > randomNumbers[i])
{
tempNumber = randomNumbers[i - 1]; //safe the bigger number in a temp var
randomNumbers[i - 1] = randomNumbers[i]; //overwrites the bigger number with the smaller one
randomNumbers[i] = tempNumber; //overwrites the smaller with the bigger one
getSwapper = true; //sets swapper to true
}
}
} // <- You should end while here
// <- It's the right time now (when getSwapper is false) to print the results
for (int i = 0; i < randomNumbers.Length; i++)
{
Console.Write(" " + randomNumbers[i]); //lists the sorted numbers of the array
}
Console.ReadKey();
#Dmitry Bychenko already gave the correct answer that contains what you were missing.
I want to share a simple bubble sort algorithm with you that I just did, fewer lines of code, less complex. It may help you to master this algorithm.
Code:
var arrayValues = new[] { 99, 12, 11, 300, 400, 10, 9, 3, 6, 5, 7, 8};
for (var mainLoop = 0; mainLoop < arrayValues.Length; mainLoop++)
{
for (var innerLoop = mainLoop + 1; innerLoop < arrayValues.Length; innerLoop++)
{
if (arrayValues[mainLoop] <= arrayValues[innerLoop])
{
continue;
}
var temp = arrayValues[mainLoop];
arrayValues[mainLoop] = arrayValues[innerLoop];
arrayValues[innerLoop] = temp;
}
}

Last number in an array becomes first

I know that's easy, but I don't understand how I should do it.
1 23 29 18 43 20 5
to
5 1 23 29 18 43 20
I think we should use for-loop:
for (int i = 0; i < numbers.Count - 1; i++)
{
}
but I don't know what to do in it. Something like numbers[i] = numbers[i - 1] but it isn't working. I think there are some if checks which I miss.
The most straightforward way that comes to mind is a reverse loop.
int[] numbers = { 1, 23, 29, 18, 43, 20, 5};
int lastVal = numbers[numbers.Length - 1];
for (int i = numbers.Length -1; i > 0; i--)
numbers[i] = numbers[i-1];
numbers[0] = lastVal;
Just looping from the end (after saving the last value) and moving "up" the values, finally replacing the first value with the last
Here's a oneliner:
var numbers = new[] {1, 23, 29, 18, 43, 20, 5};
numbers = new[] {numbers.Last()}.Concat(numbers.Take(numbers.Length - 1)).ToArray();
This creates a new array containing the last element, then concatenates it with the original array excluding the last element.
What you want to do is make another array of the same size as the original one, then assign the last element and loop through the array up to the previous to last element.
Something like this:
int[] original = {1, 23, 29, 18, 43, 20, 5};
int[] altered = new int[original.length];
altered[0] = original[original.length - 1];
for (int i = 1; i < original.length - 1; i++)
{
altered[i] = original[i - 1];
}
You can perform a left rotation to the table by six positions on your case and create the requested new table
int[] myArray = new int[] { 1, 23, 29, 18, 43, 20, 5 };
var newArray = LeftRotationByD(myArray, 6);
and your function for the rotation would be:
private static int[] LeftRotationByD(int[] a, int k)
{
int[] b = new int[a.Length];
int index;
int length = a.Length;
int place;
for (int i = 0; i < length; i++)
{
index = i - k;
place = length + index;
if (index >= 0) b[index] = a[i];
else b[place] = a[i];
}
return b;
}
You can use this method to shift right:
void ShiftRight(int[] array, int count)
{
var clone = (int[])array.Clone();
for (var i = 0; i < array.Length; i++)
array[(i + count) % array.Length] = clone[i];
}
And use it this way:
var a = new int[] { 1, 2, 3, 4 };
ShiftRight(a, 1);

How to find the longest sequence of equal elements in an array of integers?

I want to write a program that finds the longest sequence of equal elements in an array of integers. If several longest sequences exist, we should print the leftmost one. e.g. Input: 0 1 1 5 2 2 6 3 3
Output: 1 1
I know that my code doesn't work correctly, but I don't know how to fix it. I should solve the problem using only arrays because I don't know how to use lists.
int[] numbers = Console.ReadLine().Split().Select(int.Parse).ToArray();
for (int i = 0; i < numbers.Length; i++)
{
int[] currentSequenceOfEqualElements = new int[numbers.Length];
for (int j = i + 1; j < numbers.Length; j++)
{
if (numbers[i] == numbers[j])
{
if (currentSequenceOfEqualElements[0] == 0)
{
currentSequenceOfEqualElements[0] = numbers[i];
currentSequenceOfEqualElements[1] = numbers[i];
}
else
{
currentSequenceOfEqualElements[i + 2] = numbers[i];
}
}
else
{
break;
}
}
Console.WriteLine(string.Join(' ', currentSequenceOfEqualElements));
}
I will be very grateful if you can explain to me how to do it.
Here is the solution using the MoreLinq library (https://morelinq.github.io/) that mjwills suggested.
Once you get used to linq and morelinq methods the code is easier to understand than custom algo with nested loops and if.
var numbers = new int[]{ 0, 1, 1, 5, 2, 2, 6, 3, 3};
var result = numbers.GroupAdjacent(x => x)
.MaxBy(x => x.Count())
.FirstOrDefault();
foreach (var i in result)
{
Console.Write($"{i} ");
}
Here's a simple solution, using only loops and no linq. It should be nice and easy to understand.
int[] numbers = new[] { 0, 1, 1, 5, 2, 2, 6, 3, 3 };
// Some variables to keep track of the sequence we're currently looking
// at, and the longest sequence we've found so far. We're going to start
// the loop at the 2nd number, so we'll initialize these as if we've
// already processed the first number (which is 0, so we've seen the
// first number of a sequence of 0's).
// Number of numbers in the current sequence
int count = 1;
// Number which is part of the longest sequence so faar
int longestNum = numbers[0];
// Number of numbers in the longest sequence we've seen so far
int longestCount = 1;
for (int i = 1; i < numbers.Length; i++)
{
// We're starting a new sequence
if (numbers[i] != numbers[i-1])
{
count = 0;
}
count++;
// Have we just found a new longest sequence?
if (count > longestCount)
{
longestCount = count;
longestNum = numbers[i];
}
}
// longestNum = 1 and longestCount = 2 (because the longest sequence
// had 2 1's in it). Turn this into the string "1 1".
Console.WriteLine(
string.Join(" ", Enumerable.Repeat(longestNum, longestCount)));
// If you wanted to end up with an array containing [1, 1], then:
int[] result = new int[longestCount];
Array.Fill(result, longestNum);
I will illustrate a recursive answer for your question, below is the code, I kept some if-else statements that there is no need to have them, but at least the code shows the idea.
The code has a basic method that should be exposed as public and a private recursive method that does the heavy lifting. The longest sequence is the empty array(list)
var longSequenceEqualElem = new List<int>();
Later on the recursion, you pass all the elems of the array through all the recursion calls to keep querying the positions, the pos parameter indicates the position level of the recursion.
if (pos < elems.Length) //stop the recursion here, the position will fall out of the indexes of the array, just return what you have in sequence that should be the longest.
The following statement if (sequence.Contains(elems[pos])) means that you found the same number you were carrying on the sequence in the position pos, so you can add it to the sequence and call the recursion with the adjacent position(pos + 1)
If the element in position pos is not part of the sequence you had, then you need to call the recursion with a new sequence containing elems[pos] and later compare the result of that recursion call with the sequence you had to see which of them is the longest one.
Hope this helps
class Program
{
static void Main(string[] args)
{
var elemts = new int[] { 0, 1, 1, 5, 2, 2, 6, 3, 3 };
var result = LongestSequence(elemts);
foreach (var i in result)
{
Console.Write(i + "\t");
}
Console.ReadLine();
}
public static int[] LongestSequence(int[] elems)
{
var longSequenceEqualElem = new List<int>();
return LongestSequenceRec(elems, longSequenceEqualElem, 0);
}
private static int[] LongestSequenceRec(int[] elems, List<int> sequence, int pos)
{
if (pos < elems.Length)
{
if (sequence.Contains(elems[pos]))
{
sequence.Add(elems[pos]);
return LongestSequenceRec(elems, sequence, pos + 1);
}
else
{
var newSeq = LongestSequenceRec(elems, new List<int> { elems[pos] }, pos + 1);
return (newSeq.Length > sequence.Count) ? newSeq.ToArray() : sequence.ToArray();
}
}
return sequence.ToArray();
}
}
static void Main()
{
int[] array1 = new int[9] {0, 1, 1, 5, 2, 2, 6, 3, 3};
int[] array2 = new int[9] {0, 0, 0, 0, 0, 0, 0, 0, 0};
int max_count = 1;
int tempCount = 1;
int num = 0;
for (int i = 0; i < array1.Length - 1; i++)
{
if (array1[i] == array1[i + 1]) tempCount++;
else tempCount = 1;
if (tempCount > max_count)
{
max_count = tempCount;
num = array1[i];
}
}
for (int i = 0; i < max_count; i++) array2[i] = num;
for (int i = 0; i < max_count; i++) Console.Write(array2[i] + " ");
Console.ReadKey();
}

How to sort ascending only odd numbers in array?

I want to sort only odd numbers without moving even numbers. For example, if my input is:
[5, 3, 2, 8, 1, 4]
The expected result is:
[1, 3, 2, 8, 5, 4]
I am new to C# and I came across a challenge on the Internet that has me perplexed. I have tried for hours and I would like to learn this concept in
The challenge states:
You have an array of numbers. Your task is to sort ascending odd numbers but even numbers must be on their places. Zero isn't an odd number and you don't need to move it. If you have an empty array, you need to return it.
Here is my code so far, please take it easy on me I am in the beginning stages of programming.
public static int[] SortArray(int[] array)
{
var dict = new Dictionary<int, int>();
var dict2 = new Dictionary<int, int>();
for (int i = 0; i < array.Length; i++)
{
int j =0;
if (array[i] % 2 != 0)
{
dict.Add(array[i], i+1);
}
else
{
dict2.Add(array[i], i+1);
}
}
var result = dict.OrderBy(x => x.Key);
Dictionary<int, int> resultDic = result.Union(dict2)
.GroupBy(x => x.Key).ToDictionary(o => o.Key, o => o.Key);
}
public static void Main()
{
SortArray(new int[] { 5, 3, 2, 8, 1, 4});
}
Check this code. Explanations added as comments
public static int[] SortArray(int[] array)
{
//temp variable for holding larger value for switching
int temp = 0;
for (int i = 0; i < array.Length; i++)
{
//If the value is 'even' continue with outer loop
if(array[i] % 2 == 0)
continue;
//Inner loop to compare array values
for(int j = (i + 1); j < array.Length; j++)
{
//If this value is not even do comparison
if(array[j] % 2 != 0)
{
//If the left value is greater than the right value
//swap them
if(array[i] > array[j])
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}
return array;
}
public static void Main()
{
SortArray(new int[] { 5, 3, 2, 8, 1, 4});
}
You can do this with linq by indexing the numbers before you start:
var nums = new[] { 5, 3, 2, 8, 1, 4 };
var indexedNums = nums.Select((num, idx) => new { num, idx }).ToList();
Then sorting these indexed numbers into evens and odds:
var evens = indexedNums.Where(x => x.num % 2 == 0);
var odds = indexedNums.Where(x => x.num % 2 == 1);
Sorting the odd (indexed) numbers by their value:
var sortedOdds = odds.OrderBy(x => x.num); //sort the odd numbers by their value
Zipping this sequence with the odds sequence (which is sorted by index), taking the number from sortedOdds and the index from odds
var reindexedOdds = sortedOdds.Zip(odds, (o1, o2) => new { o1.num, o2.idx });
...and throwing these reindexedOdds into a sequence with the indexed evens from above, sorting by index and then selecting out the number.
var endSequence = evens.Concat(reindexedOdds).OrderBy(x => x.idx).Select(x => x.num);
While the other solutions are formally correct, most of them are not efficient, being with O(n^2) time complexity.
Another (and more time efficient) approach should imply the use of two lists: the first will contain the indexes of odd numbers, and the second will store the sorted odd numbers.
public static int[] SortArray(int[] array)
{
var sortedOdds = new List<int>(array.Length);
var oddsIndexes = new List<int>(array.Length);
var newArray = new int[array.Length];
for(var i = 0; i < array.Length; i++) // O(n)
{
var value = array[i];
if(value % 2 == 1)
{
sortedOdds.Add(value);
oddsIndexes.Add(i);
} else
{
newArray[i] = value;
}
}
sortedOdds.Sort(); // average complexity O(n log n)
for(var j = 0; j < sortedOdds.Count; j++) // O(n)
{
var value = sortedOdds[j];
var index = oddsIndexes[j];
newArray[index] = value;
}
return newArray;
}
This will reduce the complexity to an average of O(n log n) time.

Categories