Apply indexing in binary search for string - c#

I'm getting the error of not being able to apply indexing, but I'm not sure how establish a 'bounds'(algebraically) for the BinarySearch to find a string. It's apparent that
if (item > N[mid])
can't function because item is a string. How do I find item in this?:
public static int BinarySearch(string[] name, string item)
{
int min = 0;
int N = name.Length;
int max = N - 1;
do
{
int mid = (min + max) / 2;
if (item > N[mid])
min = mid + 1;
else
max = mid - 1;
if (name[mid] == item)
return mid;
//if (min > max)
// break;
} while (min <= max);
return -1;
}
and trying to appease it with something like this
public static int BinarySearch(string[] name, string searchKeyword)
{
int min = 0; //=0
int N = name.Length; //.Length
int max = N - 1;
int S = searchKeyword.Length;
do
{
int mid = (min + max) / 2;
if (S > N[mid])
min = mid + 1;
else
max = mid - 1;
if (name[mid] == S)
return mid;
//if (min > max)
// break;
} while (min <= max);
return -1;
}

You cannot use the > operator in a string because C# does not know what do you mean when saying that a string is bigger than another. Do you compare by length, alphabetical order...?.
If you want to sort them alphabetically, use the String.Compare method instead:
public static int BinarySearch(string[] name, string item)
{
int min = 0;
int N = name.Length;
int max = N - 1;
do
{
int mid = (min + max) / 2;
if (String.Compare(item, name[mid]) > 0)
min = mid + 1;
else
max = mid - 1;
if (String.Compare(item, name[mid]) == 0)
return mid; //if (min > max)
// break;
} while (min <= max);
return -1;
}

Related

Appending '0' using concat does not seem to work

I have a program that compares two integer value's length with this extension method
public static int NumDigits(this int n)
{
if (n < 0)
{
n = (n == int.MinValue) ? int.MaxValue : -n;
}
if (n < 10) return 1;
if (n < 100) return 2;
if (n < 1000) return 3;
if (n < 10000) return 4;
if (n < 100000) return 5;
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
return n < 1000000000 ? 9 : 10;
}
And it works perfectly. When I print the value of num1.numDigits(), the value returns 4 (it is worth '1111'. And my other integer: num2.numDigits() returns 2 (it is 11). This is great but when I actually compare them:
int[] rawNum2 = Arrays.DigitArr(num2);
if (num1.NumDigits() > num2.NumDigits())
{
int diff = num1.NumDigits() - num2.NumDigits();
for (int i = 1; i < diff; i++)
{
rawNum2.Append(0);
}
reversedNum2 = rawNum2.Reverse();
}
reversedNum2 is still '11' when it should be '0011'.
This is the class I compiled and used.
public static int[] Append(this int[] source, int value)
{
int[] newValue = source;
newValue = newValue.Concat(new[] { value }).ToArray();
return newValue;
}
public static int[] Reverse(this int[] array)
{
int[] arr = array;
for (int i = 0; i < arr.Length / 2; i++)
{
int tmp = arr[i];
arr[i] = arr[arr.Length - i - 1];
arr[arr.Length - i - 1] = tmp;
}
return arr;
}
public static int[] DigitArr(int n)
{
if (n == 0) return new int[1] { 0 };
var digits = new List<int>();
for (; n != 0; n /= 10)
digits.Add(n % 10);
var arr = digits.ToArray();
Array.Reverse(arr);
return arr;
}
Why is this happening?
You are discarding the return value of the Append method.
Change
rawNum2.Append(0);
to
rawNum2 = rawNum2.Append(0);
inside the for loop.
Your loop could be and should be simplified to:
rawNum2 = rawNum2.PadRight(num1.NumDigits(), '0')
To get the reversedNum2 as 0011 change your loop as below.
for (int i = 1; i <= diff; i++)
{
rawNum2=rawNum2.Append(0);
}
I made two changes changed the for loop to use i<=diff instead of i < diff
and assigning the return value from Append() method into the rawNum2.

Invalid expression term '&&' [duplicate]

This question already has an answer here:
Invalid expression term
(1 answer)
Closed 4 years ago.
I copy the code straight out of the text book and it doesn't work.
Here's the code:
public void BinarySearch(int[] numlist, int value)
{
int min = 0;
int max = numlist.Length - 1;
int index = -1;
while (min <= && index == -1)
{
int mid = (min + max) / 2;
if (value > numlist[mid])
{
min = mid + 1;
}
else if ( value< numlist[mid])
{
max = mid - 1;
}
else
{
index = mid;
}
}
return index;
}
The error I get is:
"Invalid expression term '&&'"
What have I done wrong? I have battled this before and not found an answer for it on StackOverflow.
You want to compare min with max not && and that condition have two part
then the code would be (from what I am seeing BainarySearch):
public void BinarySearch(int[] numlist, int value)
{
int min = 0;
int max = numlist.Length - 1;
int index = -1;
while (min <=max && index == -1)
{
int mid = (min + max) / 2;
if (value > numlist[mid])
{
min = mid + 1;
}
else if ( value< numlist[mid])
{
max = mid - 1;
}
else
{
index = mid;
}
}
return index;
}
You are missing a value in your while condition:
while (min <= [here goes your value] && index == -1)
problem is min <= ? what
while (min <= && index == -1)

Fastest StringBuilder Append of integer

Append integer to StringBuilder with minimum amount of allocations. Is there a faster way?
public static void AppendInvariant(this StringBuilder builder, int value)
{
// Deal with negative numbers
if (value < 0)
{
builder.Append('-');
uint uint_value = uint.MaxValue - ((uint)value) + 1; //< This is to deal with Int32.MinValue
AppendInvariant(builder, uint_value);
}
else
{
AppendInvariant(builder, (uint)value);
}
}
public static void AppendInvariant(this StringBuilder builder, uint value)
{
if (value == 0)
{
builder.Append('0');
return;
}
// Pad out space for writing.
int length = UintLength(value);
builder.Append('0', length);
length = builder.Length;
uint tmp_value;
do
{
tmp_value = value;
value /= 10;
builder[--length] = (char)('0' + (tmp_value - value * 10));
} while (value > 0);
}
private static int UintLength(uint i)
{
if (i < 100000)
{
if (i < 10) return 1;
if (i < 100) return 2;
if (i < 1000) return 3;
if (i < 10000) return 4;
return 5;
}
else
{
if (i < 1000000) return 6;
if (i < 10000000) return 7;
if (i < 100000000) return 8;
if (i < 1000000000) return 9;
return 10;
}
}
The following implementation is approximately 2 times faster.
It does that by minimizing the StringBuilder calls by using a small 100 element pre allocated string table
private static readonly string[] UIntPairStrings =
Enumerable.Range(0, 100).Select(n => n.ToString("00")).ToArray();
and also minimizes the number of divisions by processing the input value in 2 digit pairs from higher to lower (to compensate the lack of storage). This way the operation performs no more than 5 Append calls.
private static readonly uint[] UIntPairScales = { 100000000, 1000000, 10000, 100 };
public static void AppendInvariant(this StringBuilder builder, uint value)
{
bool next = false;
foreach (var scale in UIntPairScales)
{
if (value >= scale)
{
uint pair = value / scale;
if (!next && pair < 10)
builder.Append((char)('0' + pair));
else
builder.Append(UIntPairStrings[pair]);
value -= pair * scale;
next = true;
}
else if (next)
{
builder.Append("00");
}
}
if (!next && value < 10)
builder.Append((char)('0' + value));
else
builder.Append(UIntPairStrings[value]);
}

C# (find second largest number) How to split program in subprograms ?so I can reuse code later...?

I have this program that finds second largest number from users input, user needs to input atleast 2 numbers and maximum 10. I want to split program into subprograms(at least main and one function). And i cant get it to work :(
Org. code:
static void Main(string[] args)
{
int n = 1, max = 0, smax = 0, i = 0, ISsmaxrepeating = 0;
while (n != 0 && i < 10)
{
Console.WriteLine("Input number");
n = int.Parse(Console.ReadLine());
//I want this part to be in a function from here.
if (n > max)
{
smax = max;
max = n;
}
else if (n > smax)
{
smax = n;
}
//to here
if (n == smax)
{
ISsmaxrepeating = n; // checks if there are 2 numbers smax. Example: 2 1 1 it outputs error
}
i++;
}
if (smax != 0 && smax != ISsmaxrepeating)
{
Console.WriteLine("secondmax is {0}", smax);
}
else
{
Console.WriteLine("error");
}
Console.ReadLine();
So far I come up with this but it is not working :(
static int checking(int n, int max, int smax)
{
if (n > max)
{
smax = max;
max = n;
}
else if (n > smax)
{
smax = n;
}
return n;
}
static void Main(string[] args)
{
int n = 1, max = 0, smax = 0, i = 0, ISsmaxrepeating = 0, result = 0;
while (n != 0 && i < 10)
{
Console.WriteLine("Input number");
n = int.Parse(Console.ReadLine());
result = checking(n,max,smax);
if (n == smax)
{
ISsmaxrepeating = n; // checks if there are 2 numbers smax. Example: 2 1 1 it outputs error
}
i++;
}
if (smax != 0 && smax != ISsmaxrepeating)
{
Console.WriteLine("secondmax is {0}", smax);
}
else
{
Console.WriteLine("error");
}
Console.ReadLine();
}
You can output multiple variables from the function using ref keyword. However, it's better not to use a function for this kind of operation.
static void checking(int n, ref int max, ref int smax)
{
if (n > max)
{
smax = max;
max = n;
}
else if (n > smax)
{
smax = n;
}
}
Call the function inside Main
checking(n, ref max, ref smax);
Why dont.you use Math.max or Math.min? If.you want to find highest between 3 numbes, first do int halfmax=math.max(firstnum,secondnum)
then do int max = Math.max(halfmaz,thirdnum).

Largest substring composed of identical characters

I want to develop method that will return the length of largest substring composed of identical characters form string that is passed as argument, but without using any of .NET libraries.
For example if we pass aaacccccdefffgg as parameter the biggest substring is ccccc and method should return 5.
Here is my working solution :
public static int GetMaxSubstringLenght(char[] myArray)
{
int max = 0;
for (int i = 0; i < myArray.Length-1; i++)
{
if (myArray.Length == 0)
{
return 0;
}
else
{
int j = i + 1;
int currentMax = 1; // string has some value, so we start with 1
while (myArray[i] == myArray[j])
{
currentMax++;
if (max < currentMax)
{
max = currentMax;
}
j++;
}
}
}
return max;
}
The code above will return expected result, but there will be some unnecessary iteration in for loop that I want to avoid. In first iteration when i=0it will compare it until j=2 and then will get out of while loop and start second iteration in for loop comparing the one at [1] index with [2], which we already did in previous iteration.So basically, when first iteration is completed, next one should start from the last value of j. How can I achieve that ?
Thank You in advance.
Since you want "Largest substring..." let's take String as argument and return String
public static String GetMaxSubstring(String value) {
if (String.IsNullOrEmpty(value))
return "";
int bestCount = 0;
char bestChar = '\0';
int currentCount = 0;
char current = '\0';
for (int i = 0; i < value.Length; ++i) {
if ((i == 0) || (value[i] != current))
currentCount = 0;
currentCount += 1;
current = value[i];
if (currentCount > bestCount) {
bestCount = currentCount;
bestChar = current;
}
}
return new String(bestChar, bestCount);
}
....
// "ccccc"
String result = GetMaxSubstring("aaacccccdefffgg");
// 5
int length = result.Length;
Another approach:
public static int MaxSubstringLength(string s)
{
if (string.IsNullOrEmpty(s))
return 0;
int max = 0, cur = 1;
for (int i = 1; i < s.Length; ++i, ++cur)
{
if (s[i] != s[i-1])
{
max = cur > max ? cur : max;
cur = 0;
}
}
return cur > max ? cur : max;
}
[EDIT] Simplified the code.
[EDIT2] Simplified the code further.
you also can do it with one loop:
public static int GetMaxSubstringLenght(char[] myArray)
{
int max = 0;
char currentchar = myArray[0];
int count = 1;
for each(char c in myArray)
{
if(currentchar != c)
{
count = 1;
currentchar = c;
}
if(count > max)
{
max = count;
}
count++;
}
return max;
}
I changed the code... now this code does not use math.max and I think I eleminated the mistake... I've no IDE at the moment to test it
public static int GetMaxSubstringLenght(char[] myArray)
{
if (myArray.Length == 0)
return 0;
if (myArray.Length == 1)
return 1;
int max = 1;
int localMax = 1;
for (int i = 0; i < myArray.Length - max; i++ )
{
if (myArray[i] == myArray[i + 1])
{
localMax++;
}
else
{
max = Math.Max(max, localMax);
localMax = 1;
}
}
return Math.Max(max, localMax);
}
static int LongestCharSequence(string s)
{
if (string.IsNullOrEmpty(s)) return 0;
var prevChar = '\0';
int cmax = 0;
int max = 1;
foreach (char c in s)
{
if (c != prevChar)
{
cmax = 1;
prevChar = c;
}
else
{
if (++cmax > max) max = cmax;
}
}
return max;
}
recursion!
static int LongestCharSequence(string s)
{
int i = (s?.Length ?? 0) == 0 ? 0 : 1;
for (; i < s?.Length; i++)
if (s[i] != s[i - 1]) return Math.Max(i, LongestCharSequence(s.Substring(i)));
return i;
}
Another solution using my favorite nested loop technique:
public static int MaxSubstringLength(string s)
{
int maxLength = 0;
for (int length = s != null ? s.Length : 0, pos = 0; pos < length;)
{
int start = pos;
while (++pos < length && s[pos] == s[start]) { }
maxLength = Math.Max(maxLength, pos - start);
}
return maxLength;
}

Categories

Resources