Reputation: 977
Problem statement: For a given positive number, I have to find out the immediately next palindrome. Eg:
For 808, output:818
2133, output:2222
I want to know if my code is efficient at all, and how efficient is it? Is this a good way to solve the problem?
Logic explanation: I've set i
to the leftmost position of the number, j
to the rightmost position an I'm basically comparing the 2 numbers. I assign num[j]=num[i]
always, and keep track if the number becomes greater than the original value, or lesser, or equal. In the end,that is: j-i==1 or j==i
, depending on number of digits of the number being even or odd, I see if the number became greater or not, taking a decision accordingly.
EDIT: The number can be upto 100,000 digits long!..That was part of the problem statement,so I'm trying to avoid brute force methods.
int LeftNineIndex = 0, RightNineIndex = 0;
bool NumberLesser = false, NumberGreater = false;
string number = Console.ReadLine();
char[] num = number.ToCharArray();
int i, j, x, y;
for (i = 0, j = num.Length - 1; i <= j; i++, j--)
{
char m;
Int32.TryParse(num[i].ToString(),out x);
Int32.TryParse(num[j].ToString(), out y);
if (x > y)
{
NumberGreater = true;
NumberLesser = false;
}
else if (x < y)
{
if (j - i == 1)
{
NumberGreater = true;
NumberLesser = false;
x = x + 1;
Char.TryParse(x.ToString(), out m);
num[i] = m;
}
else
{
NumberGreater = false;
NumberLesser = true;
}
}
if ((j == i && NumberGreater == false) || (j - i == 1 && x == y && NumberGreater == false))
{
if (x != 9) // if the number is 9, then i can't add 1 to it
{
x = x + 1;
Char.TryParse(x.ToString(), out m);
num[i] = m;
}
else
{
if (num.Length != 1)
{
Int32.TryParse(num[LeftNineIndex].ToString(), out x);
Int32.TryParse(num[RightNineIndex].ToString(), out y);
x = x + 1;
Char.TryParse(x.ToString(), out m);
num[LeftNineIndex] = m;
num[RightNineIndex] = m;
}
else
{
// user has entered just '9', in which case I've hard-coded
Console.WriteLine("11");
}
}
}
num[j] = num[i];
if (x != 9) //gives us the index of the number closest to the middle, which is not 9
{
LeftNineIndex = i;
RightNineIndex = j;
}
}
Console.WriteLine(num);
Upvotes: 5
Views: 1461
Reputation: 108830
It's relatively simple to find the next palindrome in constant time:
The BigInteger
type is useful for implementing this:
This approach has a cost linear in the length of the input, i.e. it's logarithmic in the size of the number.
public static BigInteger NextPalindrome(BigInteger input)
{
string firstHalf=input.ToString().Substring(0,(input.ToString().Length+1)/2);
string incrementedFirstHalf=(BigInteger.Parse(firstHalf)+1).ToString();
var candidates=new List<string>();
candidates.Add(firstHalf+new String(firstHalf.Reverse().ToArray()));
candidates.Add(firstHalf+new String(firstHalf.Reverse().Skip(1).ToArray()));
candidates.Add(incrementedFirstHalf+new String(incrementedFirstHalf.Reverse().ToArray()));
candidates.Add(incrementedFirstHalf+new String(incrementedFirstHalf.Reverse().Skip(1).ToArray()));
candidates.Add("1"+new String('0',input.ToString().Length-1)+"1");
return candidates.Select(s=>BigInteger.Parse(s))
.Where(i=>i>input)
.OrderBy(i=>i)
.First();
}
Tested to work with all positive integers below 100000 by comparing with the native implementation.
The fifth case is easy to miss. If the number consists of all 9
s, incrementing the first half changes the length, and requires extra handling if the current length is odd (9
, 999
,...).
Upvotes: 6
Reputation: 4563
This is how I did it. Seems to work.
private int FindNextPaladindrone(int value)
{
int result = 0;
bool found = false;
while (!found)
{
value++;
found = IsPalindrone(value);
if (found)
result = value;
}
return result;
}
private bool IsPalindrone(int number)
{
string numberString = number.ToString();
int backIndex;
bool same = true;
for (int i = 0; i < numberString.Length; i++)
{
backIndex = numberString.Length - (i + 1);
if (i == backIndex || backIndex < i)
break;
else
{
if (numberString[i] != numberString[backIndex])
{
same = false;
break;
}
}
}
return same;
}
Upvotes: 0