Related
Given an array of n integers and a number, d, perform left rotations on the array. Then print the updated array as a single line of space-separated integers.
Sample Input:
5 4
1 2 3 4 5
The first line contains two space-separated integers denoting the respective values of n (the number of integers) and d (the number of left rotations you must perform).
The second line contains n space-separated integers describing the respective elements of the array's initial state.
Sample Output:
5 1 2 3 4
static void Main(String[] args)
{
string[] arr_temp = Console.ReadLine().Split(' ');
int n = Int32.Parse(arr_temp[0]);
int d = Int32.Parse(arr_temp[1]);
string[] arr = Console.ReadLine().Split(' ');
string[] ans = new string[n];
for (int i = 0; i < n; ++i)
{
ans[(i + n - d) % n] = arr[i];
}
for (int j = 0; j < n; ++j)
{
Console.Write(ans[j] + " ");
}
}
How to use less memory to solve this problem?
This will use less memory in most cases as the second array is only as big as the shift.
public static void Main(string[] args)
{
int[] n = { 1, 2, 3, 4, 5 };
LeftShiftArray(n, 4);
Console.WriteLine(String.Join(",", n));
}
public static void LeftShiftArray<T>(T[] arr, int shift)
{
shift = shift % arr.Length;
T[] buffer = new T[shift];
Array.Copy(arr, buffer, shift);
Array.Copy(arr, shift, arr, 0, arr.Length - shift);
Array.Copy(buffer, 0, arr, arr.Length - shift, shift);
}
This problem can get a bit tricky but also has a simple solution if one is familiar with Queues and Stacks.
All I have to do is define a Queue (which will contain the given array) and a Stack.
Next, I just have to Push the Dequeued index to the stack and Enqueue the Popped index in the Queue and finally return the Queue.
Sounds confusing? Check the code below:
static int[] rotLeft(int[] a, int d) {
Queue<int> queue = new Queue<int>(a);
Stack<int> stack = new Stack<int>();
while(d > 0)
{
stack.Push(queue.Dequeue());
queue.Enqueue(stack.Pop());
d--;
}
return queue.ToArray();
}
Do you really need to physically move anything? If not, you could just shift the index instead.
Actually you asked 2 questions:
How to efficiently rotate an array?
and
How to use less memory to solve this problem?
Usually efficiency and low memory usage are mutually exclusive. So I'm going to answer your second question, still providing the most efficient implementation under that memory constraint.
The following method can be used for both left (passing negative count) or right (passing positive count) rotation. It uses O(1) space (single element) and O(n * min(d, n - d)) array element copy operations (O(min(d, n - d)) array block copy operations). In the worst case scenario it performs O(n / 2) block copy operations.
The algorithm is utilizing the fact that
rotate_left(n, d) == rotate_right(n, n - d)
Here it is:
public static class Algorithms
{
public static void Rotate<T>(this T[] array, int count)
{
if (array == null || array.Length < 2) return;
count %= array.Length;
if (count == 0) return;
int left = count < 0 ? -count : array.Length + count;
int right = count > 0 ? count : array.Length - count;
if (left <= right)
{
for (int i = 0; i < left; i++)
{
var temp = array[0];
Array.Copy(array, 1, array, 0, array.Length - 1);
array[array.Length - 1] = temp;
}
}
else
{
for (int i = 0; i < right; i++)
{
var temp = array[array.Length - 1];
Array.Copy(array, 0, array, 1, array.Length - 1);
array[0] = temp;
}
}
}
}
Sample usage like in your example:
var array = Enumerable.Range(1, 5).ToArray(); // { 1, 2, 3, 4, 5 }
array.Rotate(-4); // { 5, 1, 2, 3, 4 }
Isn't using IEnumerables better? Since It won't perform all of those maths, won't allocate that many arrays, etc
public static int[] Rotate(int[] elements, int numberOfRotations)
{
IEnumerable<int> newEnd = elements.Take(numberOfRotations);
IEnumerable<int> newBegin = elements.Skip(numberOfRotations);
return newBegin.Union(newEnd).ToArray();
}
IF you don't actually need to return an array, you can even remove the .ToArray() and return an IEnumerable
Usage:
void Main()
{
int[] n = { 1, 2, 3, 4, 5 };
int d = 4;
int[] rotated = Rotate(n,d);
Console.WriteLine(String.Join(" ", rotated));
}
I have also tried this and below is my approach...
Thank you
public static int[] RotationOfArray(int[] A, int k)
{
if (A == null || A.Length==0)
return null;
int[] result =new int[A.Length];
int arrayLength=A.Length;
int moveBy = k % arrayLength;
for (int i = 0; i < arrayLength; i++)
{
int tmp = i + moveBy;
if (tmp > arrayLength-1)
{
tmp = + (tmp - arrayLength);
}
result[tmp] = A[i];
}
return result;
}
I have tried to used stack and queue in C# to achieve the output as follows:
public int[] rotateArray(int[] A, int rotate)
{
Queue<int> q = new Queue<int>(A);
Stack<int> s;
while (rotate > 0)
{
s = new Stack<int>(q);
int x = s.Pop();
s = new Stack<int>(s);
s.Push(x);
q = new Queue<int>(s);
rotate--;
}
return q.ToArray();
}
I've solve the challange from Hackerrank by following code. Hope it helps.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace ConsoleApp1
{
class ArrayLeftRotationSolver
{
TextWriter mTextWriter;
public ArrayLeftRotationSolver()
{
mTextWriter = new StreamWriter(#System.Environment.GetEnvironmentVariable("OUTPUT_PATH"), true);
}
public void Solve()
{
string[] nd = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(nd[0]);
int d = Convert.ToInt32(nd[1]);
int[] a = Array.ConvertAll(Console.ReadLine().Split(' '), aTemp => Convert.ToInt32(aTemp))
;
int[] result = rotLeft(a, d);
mTextWriter.WriteLine(string.Join(" ", result));
mTextWriter.Flush();
mTextWriter.Close();
}
private int[] rotLeft(int[] arr, int shift)
{
int n = arr.Length;
shift %= n;
int[] vec = new int[n];
for (int i = 0; i < n; i++)
{
vec[(n + i - shift) % n] = arr[i];
}
return vec;
}
static void Main(string[] args)
{
ArrayLeftRotationSolver solver = new ArrayLeftRotationSolver();
solver.Solve();
}
}
}
Hope this helps.
public static int[] leftrotation(int[] arr, int d)
{
int[] newarr = new int[arr.Length];
var n = arr.Length;
bool isswapped = false;
for (int i = 0; i < n; i++)
{
int index = Math.Abs((i) -d);
if(index == 0)
{
isswapped = true;
}
if (!isswapped)
{
int finalindex = (n) - index;
newarr[finalindex] = arr[i];
}
else
{
newarr[index] = arr[i];
}
}
return newarr;
}
Take the Item at position 0 and add it at the end. remove the item at position 0. repeat n times.
List<int> iList = new List<int>();
private void shift(int n)
{
for (int i = 0; i < n; i++)
{
iList.Add(iList[0]);
iList.RemoveAt(0);
}
}
An old question, but I thought I'd add another possible solution using just one intermediate array (really, 2 if you include the LINQ Take expression). This code rotates to right rather than left, but may be useful nonetheless.
public static Int32[] ArrayRightRotation(Int32[] A, Int32 k)
{
if (A == null)
{
return A;
}
if (!A.Any())
{
return A;
}
if (k % A.Length == 0)
{
return A;
}
if (A.Length == 1)
{
return A;
}
if (A.Distinct().Count() == 1)
{
return A;
}
for (var i = 0; i < k; i++)
{
var intermediateArray = new List<Int32> {A.Last()};
intermediateArray.AddRange(A.Take(A.Length - 1).ToList());
A = intermediateArray.ToArray();
}
return A;
}
O(1) space, O(n) time solution
I think in theory this is as optimal as it gets, since it makes a.Length in-place swaps and 1 temp variable swap per inner loop.
However I suspect O(d) space solutions would be faster in real life due to less code branching (fewer CPU command pipeline resets) and cache locality (mostly sequential access vs in d element steps).
static int[] RotateInplaceLeft(int[] a, int d)
{
var swapCount = 0;
//get canonical/actual d
d = d % a.Length;
if(d < 0) d += a.Length;
if(d == 0) return a;
for (var i = 0; swapCount < a.Length; i++) //we're done after a.Length swaps
{
var dstIdx = i; //we need this becasue of ~this: https://youtu.be/lJ3CD9M3nEQ?t=251
var first = a[i]; //save first element in this group
for (var j = 0; j < a.Length; j++)
{
var srcIdx = (dstIdx + d) % a.Length;
if(srcIdx == i)// circled around
{
a[dstIdx] = first;
swapCount++;
break; //hence we're done with this group
}
a[dstIdx] = a[srcIdx];
dstIdx = srcIdx;
swapCount++;
}
}
return a;
}
If you take a look at constrains you will see that d <= n (number of rotations <= number of elements in array). Because of that this can be solved in 1 line.
static int[] rotLeft(int[] a, int d)
{
return a.Skip(d).Concat(a.Take(d)).ToArray();
}
// using the same same array, and only one temp variable
// shifting everything several times by one
// works, simple, but slow
public static int[] ArrayRotateLeftCyclical(int[] a, int shift)
{
var length = a.Length;
for (int j = 0; j < shift; j++)
{
int t = a[0];
for (int i = 0; i < length; i++)
{
if (i == length - 1)
a[i] = t;
else
a[i] = a[i + 1];
}
}
return a;
}
Let's say if I have a array of integer 'Arr'. To rotate the array 'n' you can do as follows:
static int[] leftRotation(int[] Arr, int n)
{
int tempVariable = 0;
Queue<int> TempQueue = new Queue<int>(a);
for(int i=1;i<=d;i++)
{
tempVariable = TempQueue.Dequeue();
TempQueue.Enqueue(t);
}
return TempQueue.ToArray();`
}
Let me know if any comments. Thanks!
This is my attempt. It is easy, but for some reason it timed out on big chunks of data:
int arrayLength = arr.Length;
int tmpCell = 0;
for (int rotation = 1; rotation <= d; rotation++)
{
for (int i = 0; i < arrayLength; i++)
{
if (arr[i] < arrayElementMinValue || arr[i] > arrayElementMaxValue)
{
throw new ArgumentException($"Array element needs to be between {arrayElementMinValue} and {arrayElementMaxValue}");
}
if (i == 0)
{
tmpCell = arr[0];
arr[0] = arr[1];
}
else if (i == arrayLength - 1)
{
arr[arrayLength - 1] = tmpCell;
}
else
{
arr[i] = arr[i + 1];
}
}
}
what about this?
public static void RotateArrayAndPrint(int[] n, int rotate)
{
for (int i = 1; i <= n.Length; i++)
{
var arrIndex = (i + rotate) > n.Length ? n.Length - (i + rotate) : (i + rotate);
arrIndex = arrIndex < 0 ? arrIndex * -1 : arrIndex;
var output = n[arrIndex-1];
Console.Write(output + " ");
}
}
It's very straight forward answer.
Main thing is how you choose the start index.
public static List<int> rotateLeft(int d, List<int> arr) {
int n = arr.Count;
List<int> t = new List<int>();
int h = d;
for (int j = 0; j < n; j++)
{
if ((j + d) % n == 0)
{
h = 0;
}
t.Add(arr[h]);
h++;
}
return t;
}
using this code, I have successfully submitted to hacker rank problem,
// fast and beautiful method
// reusing the same array
// using small temp array to store replaced values when unavoidable
// a - array, s - shift
public static int[] ArrayRotateLeftWithSmallTempArray(int[] a, int s)
{
var l = a.Length;
var t = new int[s]; // temp array with size s = shift
for (int i = 0; i < l; i++)
{
// save cells which will be replaced by shift
if (i < s)
t[i] = a[i];
if (i + s < l)
a[i] = a[i + s];
else
a[i] = t[i + s - l];
}
return a;
}
https://github.com/sam-klok/ArraysRotation
public static void Rotate(int[] arr, int steps)
{
for (int i = 0; i < steps; i++)
{
int previousValue = arr[arr.Length - 1];
for (int j = 0; j < arr.Length; j++)
{
int currentValue = arr[j];
arr[j] = previousValue;
previousValue = currentValue;
}
}
}
Here is an in-place Rotate implementation of a trick posted by גלעד ברקן in another question. The trick is:
Example, k = 3:
1234567
First reverse in place each of the two sections delineated by n-k:
4321 765
Now reverse the whole array:
5671234
My implementation, based on the Array.Reverse method:
/// <summary>
/// Rotate left for negative k. Rotate right for positive k.
/// </summary>
public static void Rotate<T>(T[] array, int k)
{
ArgumentNullException.ThrowIfNull(array);
k = k % array.Length;
if (k < 0) k += array.Length;
if (k == 0) return;
Debug.Assert(k > 0);
Debug.Assert(k < array.Length);
Array.Reverse(array, 0, array.Length - k);
Array.Reverse(array, array.Length - k, k);
Array.Reverse(array);
}
Live demo.
Output:
Array: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
Rotate(5)
Array: 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7
Rotate(-2)
Array: 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9
I am trying to implement the top-down Merge Sort algorithm in C# as described on Wikipedia. The following implementation is what I have come up with, however, it doesn't seem to sort the array correctly. I have gone through the debugger a few times but cannot figure out where the code goes wrong. Any help would be appreciated.
using System;
class MergeSort
{
static void Main()
{
int[] A = { 4, 3, 2, 1 };
int lastIndex = A.Length - 1;
int[] B = new int[A.Length];
Array.Copy(A, B, A.Length);
MergeSortNumbers(B, 0, lastIndex, A);
foreach (var item in A)
{
Console.WriteLine("{0} ", item);
}
}
private static void MergeSortNumbers(int[] B, int iStart, int iEnd, int[] A)
{
int iMiddle = (iStart + iEnd) / 2;
if ((iEnd - iStart) < 2)
{
// Merge(B, iStart, iMiddle, iEnd, A);
return;
}
MergeSortNumbers(A, iStart, iMiddle - 1, B);
MergeSortNumbers(A, iMiddle, iEnd, B);
Merge(B, iStart, iMiddle, iEnd, A);
}
private static void Merge(int[] A, int iStart, int iMiddle, int iEnd, int[] B)
{
int i = iStart;
int j = iMiddle;
for (int k = iStart; k < iEnd; k++)
{
if (i < iMiddle && (j >= iEnd || A[i] <= A[j]))
{
B[k] = A[i];
i = i + 1;
}
else
{
B[k] = A[j];
j = j + 1;
}
}
}
}
There are two problems. you should know that iEnd is exclusive. that means iEnd it self does not take account in indexing. that's because of j >= iEnd condition in Merge method and (iEnd - iStart) < 2 in MergeSortNumbers method.
iMiddle is also exclusive for left side. because of i < iMiddle condition in Merge method.
so basically don't decrement ends by 1. (you only decrement by one if ends were inclusive)
static void Main()
{
int[] A = { 4, 3, 2, 1 };
int[] B = new int[A.Length];
Array.Copy(A, B, A.Length);
MergeSortNumbers(B, 0, A.Length, A); // Do not decrement A.Length
foreach (var item in A)
{
Console.WriteLine("{0} ", item);
}
}
private static void MergeSortNumbers(int[] B, int iStart, int iEnd, int[] A)
{
if ((iEnd - iStart) < 2) return;
int iMiddle = (iStart + iEnd) / 2;
MergeSortNumbers(A, iStart, iMiddle, B); // Do Not decrement iMiddle
MergeSortNumbers(A, iMiddle, iEnd, B);
Merge(B, iStart, iMiddle, iEnd, A);
}
private static void Merge(int[] A, int iStart, int iMiddle, int iEnd, int[] B)
{
int i = iStart;
int j = iMiddle;
for (int k = iStart; k < iEnd; k++)
{
if (i < iMiddle && (j >= iEnd || A[i] <= A[j]))
{
B[k] = A[i++];
}
else
{
B[k] = A[j++];
}
}
}
I've written the following code in C# for obtaining the length of longest common subsequence of two texts given by use, but it doesn't work with large strings. Could you please help me. I'm really confused.
public Form1()
{
InitializeComponent();
}
public int lcs(char[] s1, char[] s2, int s1size, int s2size)
{
if (s1size == 0 || s2size == 0)
{
return 0;
}
else
{
if (s1[s1size - 1] == s2[s2size - 1])
{
return (lcs(s1, s2, s1size - 1, s2size - 1) + 1);
}
else
{
int x = lcs(s1, s2, s1size, s2size - 1);
int y = lcs(s1, s2, s1size - 1, s2size);
if (x > y)
{
return x;
}
else
return y;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
string st1 = textBox2.Text.Trim(' ');
string st2 = textBox3.Text.Trim(' ');
char[] a = st1.ToCharArray();
char[] b = st2.ToCharArray();
int s1 = a.Length;
int s2 = b.Length;
textBox1.Text = lcs(a, b, s1, s2).ToString();
}
Here you are using the Recursion method. So it leads the program to occur performance problems as you mentioned.
Instead of recursion, use the dynamic programming approach.
Here is the C# Code.
public static void LCS(char[] str1, char[] str2)
{
int[,] l = new int[str1.Length, str2.Length];
int lcs = -1;
string substr = string.Empty;
int end = -1;
for (int i = 0; i < str1.Length; i++)
{
for (int j = 0; j < str2.Length; j++)
{
if (str1[i] == str2[j])
{
if (i == 0 || j == 0)
{
l[i, j] = 1;
}
else
l[i, j] = l[i - 1, j - 1] + 1;
if (l[i, j] > lcs)
{
lcs = l[i, j];
end = i;
}
}
else
l[i, j] = 0;
}
}
for (int i = end - lcs + 1; i <= end; i++)
{
substr += str1[i];
}
Console.WriteLine("Longest Common SubString Length = {0}, Longest Common Substring = {1}", lcs, substr);
}
Here is a solution how to find the longest common substring in C#:
public static string GetLongestCommonSubstring(params string[] strings)
{
var commonSubstrings = new HashSet<string>(strings[0].GetSubstrings());
foreach (string str in strings.Skip(1))
{
commonSubstrings.IntersectWith(str.GetSubstrings());
if (commonSubstrings.Count == 0)
return string.Empty;
}
return commonSubstrings.OrderByDescending(s => s.Length).DefaultIfEmpty(string.Empty).First();
}
private static IEnumerable<string> GetSubstrings(this string str)
{
for (int c = 0; c < str.Length - 1; c++)
{
for (int cc = 1; c + cc <= str.Length; cc++)
{
yield return str.Substring(c, cc);
}
}
}
I found it here: http://www.snippetsource.net/Snippet/75/longest-common-substring
Just for fun, here is one example using Queue<T>:
string LongestCommonSubstring(params string[] strings)
{
return LongestCommonSubstring(strings[0], new Queue<string>(strings.Skip(1)));
}
string LongestCommonSubstring(string x, Queue<string> strings)
{
if (!strings.TryDequeue(out var y))
{
return x;
}
var output = string.Empty;
for (int i = 0; i < x.Length; i++)
{
for (int j = x.Length - i; j > -1; j--)
{
string common = x.Substring(i, j);
if (y.IndexOf(common) > -1 && common.Length > output.Length) output = common;
}
}
return LongestCommonSubstring(output, strings);
}
It's still using recursion though, but it's a nice example of Queue<T>.
I refactored the C++ code from Ashutosh Singh at https://iq.opengenus.org/longest-common-substring-using-rolling-hash/ to create a rolling hash approach in C# - this will find the substring in O(N * log(N)^2) time and O(N) space
using System;
using System.Collections.Generic;
public class RollingHash
{
private class RollingHashPowers
{
// _mod = prime modulus of polynomial hashing
// any prime number over a billion should suffice
internal const int _mod = (int)1e9 + 123;
// _hashBase = base (point of hashing)
// this should be a prime number larger than the number of characters used
// in my use case I am only interested in ASCII (256) characters
// for strings in languages using non-latin characters, this should be much larger
internal const long _hashBase = 257;
// _pow1 = powers of base modulo mod
internal readonly List<int> _pow1 = new List<int> { 1 };
// _pow2 = powers of base modulo 2^64
internal readonly List<long> _pow2 = new List<long> { 1L };
internal void EnsureLength(int length)
{
if (_pow1.Capacity < length)
{
_pow1.Capacity = _pow2.Capacity = length;
}
for (int currentIndx = _pow1.Count - 1; currentIndx < length; ++currentIndx)
{
_pow1.Add((int)(_pow1[currentIndx] * _hashBase % _mod));
_pow2.Add(_pow2[currentIndx] * _hashBase);
}
}
}
private class RollingHashedString
{
readonly RollingHashPowers _pows;
readonly int[] _pref1; // Hash on prefix modulo mod
readonly long[] _pref2; // Hash on prefix modulo 2^64
// Constructor from string:
internal RollingHashedString(RollingHashPowers pows, string s, bool caseInsensitive = false)
{
_pows = pows;
_pref1 = new int[s.Length + 1];
_pref2 = new long[s.Length + 1];
const long capAVal = 'A';
const long capZVal = 'Z';
const long aADif = 'a' - 'A';
unsafe
{
fixed (char* c = s)
{
// Fill arrays with polynomial hashes on prefix
for (int i = 0; i < s.Length; ++i)
{
long v = c[i];
if (caseInsensitive && capAVal <= v && v <= capZVal)
{
v += aADif;
}
_pref1[i + 1] = (int)((_pref1[i] + v * _pows._pow1[i]) % RollingHashPowers._mod);
_pref2[i + 1] = _pref2[i] + v * _pows._pow2[i];
}
}
}
}
// Rollingnomial hash of subsequence [pos, pos+len)
// If mxPow != 0, value automatically multiply on base in needed power.
// Finally base ^ mxPow
internal Tuple<int, long> Apply(int pos, int len, int mxPow = 0)
{
int hash1 = _pref1[pos + len] - _pref1[pos];
long hash2 = _pref2[pos + len] - _pref2[pos];
if (hash1 < 0)
{
hash1 += RollingHashPowers._mod;
}
if (mxPow != 0)
{
hash1 = (int)((long)hash1 * _pows._pow1[mxPow - (pos + len - 1)] % RollingHashPowers._mod);
hash2 *= _pows._pow2[mxPow - (pos + len - 1)];
}
return Tuple.Create(hash1, hash2);
}
}
private readonly RollingHashPowers _rhp;
public RollingHash(int longestLength = 0)
{
_rhp = new RollingHashPowers();
if (longestLength > 0)
{
_rhp.EnsureLength(longestLength);
}
}
public string FindCommonSubstring(string a, string b, bool caseInsensitive = false)
{
// Calculate max neede power of base:
int mxPow = Math.Max(a.Length, b.Length);
_rhp.EnsureLength(mxPow);
// Create hashing objects from strings:
RollingHashedString hash_a = new RollingHashedString(_rhp, a, caseInsensitive);
RollingHashedString hash_b = new RollingHashedString(_rhp, b, caseInsensitive);
// Binary search by length of same subsequence:
int pos = -1;
int low = 0;
int minLen = Math.Min(a.Length, b.Length);
int high = minLen + 1;
var tupleCompare = Comparer<Tuple<int, long>>.Default;
while (high - low > 1)
{
int mid = (low + high) / 2;
List<Tuple<int, long>> hashes = new List<Tuple<int, long>>(a.Length - mid + 1);
for (int i = 0; i + mid <= a.Length; ++i)
{
hashes.Add(hash_a.Apply(i, mid, mxPow));
}
hashes.Sort(tupleCompare);
int p = -1;
for (int i = 0; i + mid <= b.Length; ++i)
{
if (hashes.BinarySearch(hash_b.Apply(i, mid, mxPow), tupleCompare) >= 0)
{
p = i;
break;
}
}
if (p >= 0)
{
low = mid;
pos = p;
}
else
{
high = mid;
}
}
// Output answer:
return pos >= 0
? b.Substring(pos, low)
: string.Empty;
}
}
Currently studying algorithm analysis, and instead of blindly running off of pseudo-code from my textbook, I'm implementing each algorithm in C#. This is the psuedo-code:
MERGE-SORT(A,p,r)
1 if p < r
2 q = (p+r)/2
3 MERGE-SORT(A,p,q)
4 MERGE-SORT(A,q+1,r)
5 MERGE(A,p,q,r)
MERGE(A,p,q,r)
1 n1 = q - p + 1
2 n2 = r - q
3 let L[1..n1+1] and R[1..n2+1] be new arrays
4 for i = 1 to n1
5 L[i] = A[p+i-1]
6 for j = 1 to n2
7 R[j] = A[q+j]
8 L[n1+1] = INF
9 R[n1+1] = INF
10 i = 1
11 j = 1
12 for k = p to r
13 if L[i] <= R[j]
14 A[k] = L[i]
15 i = i + 1
16 else
17 A[k] = R[j]
18 j = j + 1
This is my code:
static void Main(string[] args)
{
int[] unsortedArray = new int[] { 5, 2, 7, 4, 1, 6, 8, 3, 9, 10 };
MergeSort(ref unsortedArray, 1, unsortedArray.Length);
foreach (int element in unsortedArray)
{
Console.WriteLine(element);
}
Console.Read();
}
private static void MergeSort(ref int[] unsortedArray, int leftIndex, int rightIndex)
{
if (leftIndex < rightIndex)
{
int middleIndex = (leftIndex + rightIndex) / 2;
//Sort left (will call Merge to produce a fully sorted left array)
MergeSort(ref unsortedArray, leftIndex, middleIndex);
//Sort right (will call Merge to produce a fully sorted right array)
MergeSort(ref unsortedArray, middleIndex + 1, rightIndex);
//Merge the sorted left & right to finish off.
Merge(ref unsortedArray, leftIndex, middleIndex, rightIndex);
}
}
private static void Merge(ref int[] unsortedArray, int leftIndex, int middleIndex, int rightIndex)
{
int lengthLeft = middleIndex - leftIndex + 1;
int lengthRight = rightIndex - middleIndex;
int[] leftArray = new int[lengthLeft + 1];
int[] rightArray = new int[lengthRight + 1];
for (int i = 0; i < lengthLeft; i++)
{
leftArray[i] = unsortedArray[leftIndex + i - 1];
}
for (int j = 0; j < lengthRight; j++)
{
rightArray[j] = unsortedArray[middleIndex + j];
}
leftArray[lengthLeft] = Int32.MaxValue;
rightArray[lengthRight] = Int32.MaxValue;
int iIndex = 0;
int jIndex = 0;
for (int k = leftIndex; k < rightIndex; k++)
{
if (leftArray[iIndex] <= rightArray[jIndex])
{
unsortedArray[k] = leftArray[iIndex];
iIndex++;
}
else
{
unsortedArray[k] = rightArray[jIndex];
jIndex++;
}
}
}
I'm not sure where I'm messing things up -- I tried to follow the pseudo-code as well as I could, but my output is funky (i.e. repeated values and not properly sorted).
Debugging this didn't help me figure out the problem either (recursive solutions get too messy).
Where am I going wrong, and how do I fix it?
As correctly pointed out in the comments, C# array indexing is zero-based, while your pseudo code is one-based.
That being said, here's the errors:
1) Main method
MergeSort(ref unsortedArray, 1, unsortedArray.Length);
has to be changed to:
MergeSort(ref unsortedArray, 0, unsortedArray.Length - 1);
2) Merge method
leftArray[i] = unsortedArray[leftIndex + i - 1];
has to be change to:
leftArray[i] = unsortedArray[leftIndex + i];
3) Merge method
rightArray[j] = unsortedArray[middleIndex + j];
has to be change to:
rightArray[j] = unsortedArray[middleIndex + j + 1];
4) Merge method
for (int k = leftIndex; k < rightIndex; k++)
has to be change to:
for (int k = leftIndex; k <= rightIndex; k++)
BTW, the ref keyword in your code is not really necessay, since you're just modifying the values inside the array and not creating a new instance of it .
private static void Merge(int[]A, int[]aux, int lo, int mid, int hi)
{
for (int k = lo; k <= hi; k++)
aux[k] = A[k];
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
{
if (i > mid) A[k] = aux[j++];
else if (j > hi) A[k] = aux[i++];
else if (aux[j] < aux[i]) A[k] = aux[j++];
else A[k] = aux[i++];
}
}
private static void Sort(int[] A, int[] aux, int lo, int hi)
{
if (hi <= lo) return;
int mid = lo + (hi - lo) / 2;
Sort(A, aux, lo, mid);
Sort(A, aux, mid + 1, hi);
if (A[mid + 1] > A[mid]) return;
Merge(A, aux, lo, mid, hi);
}
public static void Sort(int[] A)
{
int[] aux = new int[A.Length];
Sort(A, aux, 0, A.Length - 1);
}
A Simple Merge Sort Implementation.
https://github.com/bharathkumarms/AlgorithmsMadeEasy/blob/master/AlgorithmsMadeEasy/MergeSort.cs
using System;
using System.Collections.Generic;
using System.Linq;
namespace AlgorithmsMadeEasy
{
class MergeSort
{
public void MergeSortMethod()
{
var input = System.Console.ReadLine();
string[] sInput = input.Split(' ');
int[] numbers = Array.ConvertAll(sInput, int.Parse);
int len = numbers.Length;
MergeSort_Recursive(numbers, 0, len - 1);
for (int i = 0; i < len; i++)
{
Console.Write(numbers[i] + " ");
}
Console.ReadLine();
}
static public void MergeSort_Recursive(int[] numbers, int left, int right)
{
int mid;
if (right > left)
{
mid = (right + left) / 2;
MergeSort_Recursive(numbers, left, mid);
MergeSort_Recursive(numbers, (mid + 1), right);
DoMerge(numbers, left, (mid + 1), right);
}
}
static public void DoMerge(int[] numbers, int left, int mid, int right)
{
int[] temp = new int[numbers.Length];
int i, left_end, num_elements, tmp_pos;
left_end = (mid - 1);
tmp_pos = left;
num_elements = (right - left + 1);
while ((left <= left_end) && (mid <= right))
{
if (numbers[left] <= numbers[mid])
temp[tmp_pos++] = numbers[left++];
else
temp[tmp_pos++] = numbers[mid++];
}
while (left <= left_end)
temp[tmp_pos++] = numbers[left++];
while (mid <= right)
temp[tmp_pos++] = numbers[mid++];
for (i = 0; i < num_elements; i++)
{
numbers[right] = temp[right];
right--;
}
}
}
}
/*
Sample Input:
6 5 3 2 8
Calling Code:
MergeSort ms = new MergeSort();
ms.MergeSortMethod();
*/
What is the best way to compare two strings to see how similar they are?
Examples:
My String
My String With Extra Words
Or
My String
My Slightly Different String
What I am looking for is to determine how similar the first and second string in each pair is. I would like to score the comparison and if the strings are similar enough, I would consider them a matching pair.
Is there a good way to do this in C#?
static class LevenshteinDistance
{
public static int Compute(string s, string t)
{
if (string.IsNullOrEmpty(s))
{
if (string.IsNullOrEmpty(t))
return 0;
return t.Length;
}
if (string.IsNullOrEmpty(t))
{
return s.Length;
}
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
// initialize the top and right of the table to 0, 1, 2, ...
for (int i = 0; i <= n; d[i, 0] = i++);
for (int j = 1; j <= m; d[0, j] = j++);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
int min1 = d[i - 1, j] + 1;
int min2 = d[i, j - 1] + 1;
int min3 = d[i - 1, j - 1] + cost;
d[i, j] = Math.Min(Math.Min(min1, min2), min3);
}
}
return d[n, m];
}
}
If anyone was wondering what the C# equivalent of what #FrankSchwieterman posted is:
public static int GetDamerauLevenshteinDistance(string s, string t)
{
if (string.IsNullOrEmpty(s))
{
throw new ArgumentNullException(s, "String Cannot Be Null Or Empty");
}
if (string.IsNullOrEmpty(t))
{
throw new ArgumentNullException(t, "String Cannot Be Null Or Empty");
}
int n = s.Length; // length of s
int m = t.Length; // length of t
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
int[] p = new int[n + 1]; //'previous' cost array, horizontally
int[] d = new int[n + 1]; // cost array, horizontally
// indexes into strings s and t
int i; // iterates through s
int j; // iterates through t
for (i = 0; i <= n; i++)
{
p[i] = i;
}
for (j = 1; j <= m; j++)
{
char tJ = t[j - 1]; // jth character of t
d[0] = j;
for (i = 1; i <= n; i++)
{
int cost = s[i - 1] == tJ ? 0 : 1; // cost
// minimum of cell to the left+1, to the top+1, diagonally left and up +cost
d[i] = Math.Min(Math.Min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
}
// copy current distance counts to 'previous row' distance counts
int[] dPlaceholder = p; //placeholder to assist in swapping p and d
p = d;
d = dPlaceholder;
}
// our last action in the above loop was to switch d and p, so p now
// actually has the most recent cost counts
return p[n];
}
I am comparing two sentences like this
string[] vs = string1.Split(new char[] { ' ', '-', '/', '(', ')' },StringSplitOptions.RemoveEmptyEntries);
string[] vs1 = string2.Split(new char[] { ' ', '-', '/', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
vs.Intersect(vs1, StringComparer.OrdinalIgnoreCase).Count();
Intersect gives you a set of identical word lists , I continue by looking at the count and saying if it is more than 1, these two sentences contain similar words.