How to sort ascending only odd numbers in array? - c#

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.

Related

Getting a two dimensional array of all possible unique combination of numbers lower than a mixmum for each cell starting from 1

Hello and thanks for your attention.
(my mathematical vocabulary for English language is rather limited, if you can think of a better title for this question please feel free to edit and thanks for help.)
I am trying to write a function that takes a One-dimensional array of numbers as an input and then returns a two dimensional array that contains all the potential combination of the all numbers lower or equal than their equivalent in input array starting from 1.
let me try to explain this better in two examples:
example one:
Input: [2,3]
Output:
[1,1]
[1,2]
[1,3]
[2,1]
[2,2]
[2,3]
example two:
Input: [2,3,2]
Output:
[1,1,1]
[1,1,2]
[1,2,1]
[1,2,2]
[1,3,1]
[1,3,2]
[2,1,1]
[2,1,2]
[2,2,1]
[2,2,2]
[2,3,1]
[2,3,2]
Also it would be great that you code returns order of arrays in the output in similar order of arrays in outputs in examples but that's not necessary.(the order of numbers inside arrays that are in the output is of course important!)
Note: the length of input array is unspecified and can contain any number of numbers.
Note: there is no need for output to be in array form and can be in form of common .NET collection like List<double[]> or List<List<double>> same goes for input.
If i can clarify the question better please tell in comment.
The following code is our attempt at solving this but it does not return all combinations and contain repetitions of arrays:
public class ArrayGenerator
{
private int mainCounter;
int count = 1;
int counter = 0;
private int movingCounter;
public Dictionary<int, List<int>> series = new Dictionary<int, List<int>>();
public ArrayGenerator(params int[] args)
{
ConcurrentDictionary<int, int> listsCounter = new ConcurrentDictionary<int, int>();
for (int i = 0; i < args.Length; i++)
{
listsCounter.TryAdd(i, 0);
count *= args[i];
var l = new List<int>();
for (int j = 1; j <= args[i]; j++)
{
l.Add(j);
}
series.Add(i, l);
}
List<string> strs = new List<string>();
while (mainCounter<count)
{
string str = "";
counter = 0;
while (counter < args.Length)
{
if (listsCounter[counter] < series[counter].Count)
{
str += series[counter][listsCounter[counter]];
int c, d;
c = listsCounter[counter];
d = c + 1;
listsCounter.TryUpdate(counter, d, c);
}
else
{
int c = listsCounter[counter];
listsCounter.TryUpdate(counter, 0,c);
str += series[counter][listsCounter[counter]];
}
counter++;
}
strs.Add(str);
mainCounter++;
}
}
}
It's much easier to create jagged array (i.e. array of array), int[][] then 2D one int[,]:
using System.Linq;
...
private static IEnumerable<int[]> Solution(int[] maxes) {
if (null == maxes || maxes.Length <= 0 || maxes.Any(item => item < 1))
yield break; // Or throw exception(s)
int[] current = Enumerable
.Repeat(1, maxes.Length)
.ToArray();
do {
yield return current.ToArray(); // copy of current
for (int i = current.Length - 1; i >= 0; --i)
if (current[i] < maxes[i]) {
current[i] += 1;
break;
}
else
current[i] = 1;
}
while (!current.All(item => item == 1));
}
...
// Having an enumeration, we materialize it as an array, i.e. array of array
int[][] demo = Solution(new int[] { 2, 3, 2})
.ToArray();
// Let's have a look at the results
Console.Write(string.Join(Environment.NewLine,
demo.Select(line => string.Join(", ", line))));
Outcome:
1, 1, 1
1, 1, 2
1, 2, 1
1, 2, 2
1, 3, 1
1, 3, 2
2, 1, 1
2, 1, 2
2, 2, 1
2, 2, 2
2, 3, 1
2, 3, 2
If you insist on 2D array, you can convert:
int[,] data2D = new int[demo.Length, demo.Length > 0 ? demo[0].Length : 0];
for (int y = 0; y < demo.Length; ++y)
for (int x = 0; x < demo[0].Length; ++x)
data2D[y, x] = demo[y][x];

Index of multiple max values in array

I have an array of for example
int[] array = new int[] {1, 3, 2, 3};
and problem is with getting index of multiple max values from an array.
First get the max:
int max = array.Max();
Now get the indices of the elements that have that value:
var indices = array.Select((x, i) => new { Index = i, Value = x })
.Where(x => x.Value == max)
.Select(x => x.Index);
Here's how you can do that in one loop.
var indices = new List<int>();
int max = int.MinValue;
for(int i = 0; i < array.Length; i++)
{
if(array[i] > max)
{
max = array[i];
indices.Clear();
}
if(array[i] == max)
{
indices.Add(i);
}
}
Basically you keep track of the max and a list of indices. When you see a value greater than the max you set it to max and clear the list since any indices in there are no longer pointing at the max. Then just check if the value equals the max and add the index to the list if it does.
Linq approach
int[] array = new int[] { 1, 3, 2, 3 };
int[] result = array.Select((x, i) => new { index = i, value = x })
.GroupBy(x => x.value)
.OrderByDescending(x => x.Key)
.First()
.Select(x => x.index)
.ToArray();
With an extention method given that you already have the maxValue you are looking for:
public static IEnumerable<int> AllIndexesOf(this List<T> list, T searchValue)
{
int minIndex = list.IndexOf(searchValue);
while (minIndex != -1)
{
yield return minIndex;
minIndex = list.IndexOf(searchValue, minIndex + 1);
}
}
You can have :
int[] array = new int[] {1, 3, 2, 3};
int maxValue = array.Max();
int[] indexesOfMax = array.AllIndexesOf(maxValue).ToArray();
As a counter to #HimBromBeere's answer
We can use a dictionary for every unique number and then a list of integers for every index it showed up.
var intArray = new int[5];
var dictionary = new Dictionary<int, List<int>>();
for (int i = 0; i < intArray.Length; i++)
{
var num = intArray[i];
if (!dictionary.ContainsKey(num))
{
dictionary.Add(num, new List<int>());
}
dictionary[num].Add(i);
}
var max = dictionary.Keys.Max();
return dictionary[max];
This has less overall operations but is a bit more terse.
Using yield return and looping through the array you can do this:
using Linq;
using System.Collections.Generic;
public static class IEnumerableExtensions
{
// Extension method for IEnumerable
public static IEnumerable<int> AllIndexesOf<T>(this IEnumerable<T> list, T searchValue)
{
for (int i = 0; i < list.Count(); i++)
{
if (list.ElementAt(i) == searchValue)
{
yield return i;
}
}
}
}
Then find the max value in the array using LINQ and call the method:
using Linq; // include this at the top of your file, if not already present.
// ...
int[] array = new int[] {1, 3, 2, 3};
IEnumerable<int> matchingIndexes = array.AllIndexesOf(array.Max());
// Convert to array if you need one
int[] matchingIndexesArr = matchingIndexes.ToArray();
You can find more information about extension methods in the docs.

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

Move duplicate numbers at end in integer array

I want to move all duplicate numbers at the end of array like this.
{4,1,5,4,3,1,6,5}
{4,1,5,3,6,4,1,5}
also i want to know number of dups. that i will use to resize array.
here is the code i tried but this code is not compatible when i insert more than 2 dups at starting.
static void RemoveRepeated(ref int[] array)
{
int count = 0; bool flag;
for (int i = 0; i < array.Length; i++)
{
flag = true;
for (int j = i+1; j < array.Length-1; j++)
{
if (array[i] == array[j] )
{
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
if (flag)
{
count++;
flag = false;
}
}
}
}
Array.Resize(ref array,array.Length-count);
}
Thanks in advance :)
A good solution will be to use a fitting data-structure. It will not fix your algorithm but replace it. Here a HashSet<T> is perfect. A HashSet<T> remove itself all duplicate. Check the msdn for more informations.
Demo on .NETFiddle
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var array = new int[]{ 4,1,5,4,3,1,6,5 };
RemoveRepeated(ref array);
foreach (var item in array)
Console.WriteLine(item);
}
static void RemoveRepeated(ref int[] array)
{
array = new HashSet<int>(array).ToArray();
}
}
By the way you don't really need ref here. I would remove it and change void RemoveRepeated(ref int[] array) to int[] RemoveRepeated(int[] array). See ref parameter or return value?
What you are doing is equivalent to leaving only the unique elements in their original order. Here is simpler way to do this:
static void RemoveRepeated(ref int[] array)
{
HashSet<int> seen = new HashSet<int>();
List<int> newArray = new List<int>(array.Length);
foreach(int x in array)
{
if(!seen.Contains(x))
{
seen.Add(x);
newArray.Add(x);
}
}
array = newArray.ToArray();
}
Don't use an array here. You can try to (just one example) group a List<int> and Count() all groups that have more than one element. When you have the count, you can use Distinct() to get only the distinct elements.
In my opinion, resizing an array like this is always a very bad idea.
Edit:
Well, like the other answers already stated, a HashSet is a even better way of doing it.
class Program
{
static void Main(string[] args)
{
int[] arr = new int[] { 4, 1, 5, 4, 3, 1, 6, 5 };
RemoveRepeated(ref arr);
foreach (int i in arr)
{
Console.WriteLine(i);
}
Console.ReadKey();
}
private static void RemoveRepeated(ref int[] array)
{
int count =0;
for (int i = 0; i < array.Length; i++)
{
for (int j = i + 1; j < array.Length; j++)
{
if (array[i] == array[j])
{
int temp = array[j];
count++;
for (int k = j; k < array.Length-1; k++)
{
array[k] = array[k + 1];
}
array[array.Length - 1] = temp;
j = array.Length;
}
}
}
Array.Resize(ref array, array.Length - count);
}
}
Try this:
class Program
{
static void Main(string[] args)
{
int[] ints = {4,1,5,4,3,1,6,5};
var query = ints.GroupBy(x => x).OrderBy(x => x.Count()).Select(x => x);
// print ordered array showing dupes are last
query.ToList().ForEach(x => Console.WriteLine(x.Key.ToString()));
// Get number of dupes
int dupeCount = query.Where(x => x.Count() > 1).Count();
// put unique items into a new array
var newArray = query.Where(x => x.Count() == 1).Select(x => x.Key).ToArray();
// put distinct items into an array
var distinctArray = ints.Distinct().ToArray();
Console.ReadKey();
}
}
Edit: Added distinct elements
If you want to move the duplicates to the end of array (but preserve order) you can do this:
static void RemoveRepeated(ref int[] array)
{
var lookup = array.ToLookup(x => x);
var maxdupes = lookup.Select(x => x.Count()).Max();
var reordered =
Enumerable
.Range(0, maxdupes)
.SelectMany(x => lookup.SelectMany(y => y.Skip(x).Take(1)))
.ToArray();
Array.Copy(reordered, array, reordered.Length);
}
This would turn { 4, 1, 5, 4, 3, 1, 6, 5 } into { 4, 1, 5, 3, 6, 4, 1, 5 }
You can easily get the number of duplicates by doing this:
lookup
.Select(x => new
{
Value = x.Key,
Count = x.Count(),
});
This returns:
4 2
1 2
5 2
3 1
6 1

Check for missing number in sequence

I have an List<int> which contains 1,2,4,7,9 for example.
I have a range from 0 to 10.
Is there a way to determine what numbers are missing in that sequence?
I thought LINQ might provide an option but I can't see one
In the real world my List could contain 100,000 items so performance is key
var list = new List<int>(new[] { 1, 2, 4, 7, 9 });
var result = Enumerable.Range(0, 10).Except(list);
Turn the range you want to check into a HashSet:
public IEnumerable<int> FindMissing(IEnumerable<int> values)
{
HashSet<int> myRange = new HashSet<int>(Enumerable.Range(0,10));
myRange.ExceptWith(values);
return myRange;
}
Will return the values that aren't in values.
Using Unity i have tested two solutions on set of million integers. Looks like using Dictionary and two "for" loops gives better result than Enumerable.Except
FindMissing1 Total time: 0.1420 (Enumerable.Except)
FindMissing2 Total time: 0.0621 (Dictionary and two for loops)
public static class ArrayExtension
{
public static T[] FindMissing1<T>(T[] range, T[] values)
{
List<T> result = Enumerable.Except<T>(range, values).ToList<T>();
return result.ToArray<T>();
}
public static T[] FindMissing2<T>(T[] range, T[] values)
{
List<T> result = new List<T>();
Dictionary<T, T> hash = new Dictionary<T, T>(values.Length);
for (int i = 0; i < values.Length; i++)
hash.Add(values[i], values[i]);
for (int i = 0; i < range.Length; i++)
{
if (!hash.ContainsKey(range[i]))
result.Add(range[i]);
}
return result.ToArray<T>();
}
}
public class ArrayManipulationTest : MonoBehaviour
{
void Start()
{
int rangeLength = 1000000;
int[] range = Enumerable.Range(0, rangeLength).ToArray();
int[] values = new int[rangeLength / 5];
int[] missing;
float start;
float duration;
for (int i = 0; i < rangeLength / 5; i ++)
values[i] = i * 5;
start = Time.realtimeSinceStartup;
missing = ArrayExtension.FindMissing1<int>(range, values);
duration = Time.realtimeSinceStartup - start;
Debug.Log($"FindMissing1 Total time: {duration:0.0000}");
start = Time.realtimeSinceStartup;
missing = ArrayExtension.FindMissing2<int>(range, values);
duration = Time.realtimeSinceStartup - start;
Debug.Log($"FindMissing2 Total time: {duration:0.0000}");
}
}
List<int> selectedNumbers = new List<int>(){8, 5, 3, 12, 2};
int firstNumber = selectedNumbers.OrderBy(i => i).First();
int lastNumber = selectedNumbers.OrderBy(i => i).Last();
List<int> allNumbers = Enumerable.Range(firstNumber, lastNumber - firstNumber + 1).ToList();
List<int> missingNumbers = allNumbers.Except(selectedNumbers).ToList();
foreach (int i in missingNumbers)
{
Response.Write(i);
}
LINQ's Except method would be the most readable. Whether it performs adequately for you or not would be a matter for testing.
E.g.
range.Except(listOfValues);
Edit
Here's the program I used for my mini-benchmark, for others to plug away with:
static void Main()
{
var a = Enumerable.Range(0, 1000000);
var b = new List<int>();
for (int i = 0; i < 1000000; i += 10)
{
b.Add(i);
}
Stopwatch sw = new Stopwatch();
sw.Start();
var c = a.Except(b).ToList();
sw.Stop();
Console.WriteLine("Milliseconds {0}", sw.ElapsedMilliseconds );
sw.Reset();
Console.ReadLine();
}
An alternative method which works in general for any two IEnunumerable<T> where T :IComparable. If the IEnumerables are both sorted, this works in O(1) memory (i.e. there is no creating another ICollection and subtracting, etc.) and in O(n) time.
The use of IEnumerable<IComparable> and GetEnumerator makes this a little less readable, but far more general.
Implementation
/// <summary>
/// <para>For two sorted IEnumerable<T> (superset and subset),</para>
/// <para>returns the values in superset which are not in subset.</para>
/// </summary>
public static IEnumerable<T> CompareSortedEnumerables<T>(IEnumerable<T> superset, IEnumerable<T> subset)
where T : IComparable
{
IEnumerator<T> supersetEnumerator = superset.GetEnumerator();
IEnumerator<T> subsetEnumerator = subset.GetEnumerator();
bool itemsRemainingInSubset = subsetEnumerator.MoveNext();
// handle the case when the first item in subset is less than the first item in superset
T firstInSuperset = superset.First();
while ( itemsRemainingInSubset && supersetEnumerator.Current.CompareTo(subsetEnumerator.Current) >= 0 )
itemsRemainingInSubset = subsetEnumerator.MoveNext();
while ( supersetEnumerator.MoveNext() )
{
int comparison = supersetEnumerator.Current.CompareTo(subsetEnumerator.Current);
if ( !itemsRemainingInSubset || comparison < 0 )
{
yield return supersetEnumerator.Current;
}
else if ( comparison >= 0 )
{
while ( itemsRemainingInSubset && supersetEnumerator.Current.CompareTo(subsetEnumerator.Current) >= 0 )
itemsRemainingInSubset = subsetEnumerator.MoveNext();
}
}
}
Usage
var values = Enumerable.Range(0, 11);
var list = new List<int> { 1, 2, 4, 7, 9 };
var notIncluded = CompareSortedEnumerables(values, list);
If the range is predictable I suggest the following solution:
public static void Main()
{
//set up the expected range
var expectedRange = Enumerable.Range(0, 10);
//set up the current list
var currentList = new List<int> {1, 2, 4, 7, 9};
//get the missing items
var missingItems = expectedRange.Except(currentList);
//print the missing items
foreach (int missingItem in missingItems)
{
Console.WriteLine(missingItem);
}
Console.ReadLine();
}
Regards,
y00daa
This does not use LINQ but it works in linear time.
I assume that input list is sorted.
This takes O(list.Count).
private static IEnumerable<int> get_miss(List<int> list,int length)
{
var miss = new List<int>();
int i =0;
for ( i = 0; i < list.Count - 1; i++)
{
foreach (var item in
Enumerable.Range(list[i] + 1, list[i + 1] - list[i] - 1))
{
yield return item;
}
}
foreach (var item in Enumerable.Range(list[i]+1,length-list[i]))
{
yield return item;
}
}
This should take O(n) where n is length of full range.
static void Main()
{
List<int> identifiers = new List<int>() { 1, 2, 4, 7, 9 };
Stopwatch sw = new Stopwatch();
sw.Start();
List<int> miss = GetMiss(identifiers,150000);
sw.Stop();
Console.WriteLine("{0}",sw.ElapsedMilliseconds);
}
private static List<int> GetMiss(List<int> identifiers,int length)
{
List<int> miss = new List<int>();
int j = 0;
for (int i = 0; i < length; i++)
{
if (i < identifiers[j])
miss.Add(i);
else if (i == identifiers[j])
j++;
if (j == identifiers.Count)
{
miss.AddRange(Enumerable.Range(i + 1, length - i));
break;
}
}
return miss;
}
Ok, really, create a new list which parallels the initial list and run the method Except over it...
I have created a fully linq answer using the Aggregate method instead to find the missings:
var list = new List<int>(new[] { 1, 2, 4, 7, 9 }); // Assumes list is ordered at this point
list.Insert(0, 0); // No error checking, just put in the lowest and highest possibles.
list.Add(10); // For real world processing, put in check and if not represented then add it/them.
var missing = new List<int>(); // Hold any missing values found.
list.Aggregate ((seed, aggr) => // Seed is the previous #, aggr is the current number.
{
var diff = (aggr - seed) -1; // A difference between them indicates missing.
if (diff > 0) // Missing found...put in the missing range.
missing.AddRange(Enumerable.Range((aggr - diff), diff));
return aggr;
});
The missing list has this after the above code has been executed:
3, 5, 6, 8
for a List L a general solution (works in all programming languages) would be simply
L.Count()*(L.Count()+1)/2 - L.Sum();
which returns the expected sum of series minus the actual series.
for a List of size n the missing number is:
n(n+1)/2 - (sum of list numbers)
this method here returns the number of missing elements ,sort the set , add all elements from range 0 to range max , then remove the original elements , then you will have the missing set
int makeArrayConsecutive(int[] statues)
{
Array.Sort(statues);
HashSet<int> set = new HashSet<int>();
for(int i = statues[0]; i< statues[statues.Length -1]; i++)
{
set.Add(i);
}
for (int i = 0; i < statues.Length; i++)
{
set.Remove(statues[i]);
}
var x = set.Count;
return x;
// return set ; // use this if you need the actual elements + change the method return type
}
Create an array of num items
const int numItems = 1000;
bool found[numItems] = new bool[numItems];
List<int> list;
PopulateList(list);
list.ForEach( i => found[i] = true );
// now iterate found for the numbers found
for(int count = 0; i < numItems; ++numItems){
Console.WriteList("Item {0} is {1}", count, found[count] ? "there" : "not there");
}
This method does not use LINQ and works in general for any two IEnunumerable<T> where T :IComparable
public static IEnumerable<T> FindMissing<T>(IEnumerable<T> superset, IEnumerable<T> subset) where T : IComparable
{
bool include = true;
foreach (var i in superset)
{
foreach (var j in subset)
{
include = i.CompareTo(j) == 0;
if (include)
break;
}
if (!include)
yield return i;
}
}
int sum = 0,missingNumber;
int[] arr = { 1,2,3,4,5,6,7,8,9};
for (int i = 0; i < arr.Length; i++)
{
sum += arr[i];
}
Console.WriteLine("The sum from 1 to 10 is 55");
Console.WriteLine("Sum is :" +sum);
missingNumber = 55 - sum;
Console.WriteLine("Missing Number is :-"+missingNumber);
Console.ReadLine();

Categories