I solved #9 with one integer finally and the time complexity is O(n).
It's really interesting so I want to record my thinking process.
Leetcode #9 Discussion // Rewrite in Markdown mode. 16/9/13
Initial Solution
- It’s easy to start this problem with this formula:
- Then you could get it:
- With this formula, you could easily solve this problem like what I did in my last article, at that time, I use 5 variables to solve it:
int i; //Loop variable for computing X's length and comparing digits
int j; //Record the length of X
int t; //Loop variable to compute 10^i
int l; //Record 10^i
int a; //Record X[i] when compare X[i] and X[j-i+1]
- 5 varaibles and O(n^2). More details in my last article.
Improvement. 3 variables to solve it
- Compute 10^i again and again makes this code O(n^2) and you have to record it by a variable. So try to improve it.
- Try to start the loop at the middle digit of the number.
- For odd number:
- For even number:
- Now, compute 10^(n/2) first, we don’t need to compute 10^i every time, you could also remove variable l and variable a, because you don’t need to record 10^i and Xi.
- So, 3 variables and O(n) to solve it, code below:
bool isPalindrome(int x)
{
if(x<0) return false;
int i,j,t;
i=x; j=0;
while (i) { j++; i/=10;}
if (j % 2==0)
{
t=1; j/=2;
for (i=1;i<=j;i++)t*=10;
i=10;
while (j)
{
if (j==1)
{
if (x%(t/i*10)/(t/i)!=x/(t/10*i)) return false;
} else
{
if (x%(t/i*10)/(t/i)!=x%(t*i)/(t*i/10)) return false;
}
j--; i*=10;
}
} else
{
t=1; j/=2;
for (i=1;i<=j;i++) t*=10;
i=10;
while (j)
{
if (j==1)
{
if (x%(t/i*10)/(t/i)!=x/(t*i)) return false;
} else
{
if (x%(t/i*10)/(t/i)!=x%(t*i*10)/(t*i)) return false;
}
j--; i*=10;
}
}
return true;
}
Final version. Make a new start
- In the method above, we use this formula to solve the problem:
- This formula is really complex because we keep X unchanged. In fact, these is no need to do like this. Can we simplify this formula by changing X?
- Look at the picture above. If we could remove the first digit and the last digit of X after each step, we could compare X0 and Xn by these formulas.
- It’s easy to work out, and I tried with 2 variables at first.
bool isPalindrome(int x)
{
if (x<0) return false;
int i=1,j=x;
while (x>=10) {x/=10; i*=10;}
x=j;
while (x>=10)
{
if (x % 10 != x / i) return false;
else
{
x/=10; i/=10;
x%=i; i/=10;
}
}
return true;
}
- However, it can’t pass.
- ‘X>=10’ was used to end the loop, but if you try a number like X=200012, the answer will be TRUE.
- ‘200012’, after you delete the first digit and last digit of this number, it changes to ‘1’. Then ‘X>=10’ is not satisfied so the loop goes to end.
- So the point is you need to control the length of number. The program need to know ‘1’ is ‘0001’ in fact.
- While this information is actually hidden in the code.’int i’ in the code is equal to ‘10^n’ at first. After each step, you deleted the first and the last digit, and n(the length of number) minus 2, so i is divided by 100. Wait, it means that ‘int i’ knows the length of X exactly.
- Up to this point, the algorithm is good enough.2 variables, O(n), short codes.
bool isPalindrome(int x)
{
if (x<0) return false;
int i=1,j=x;
while (x>=10) {x/=10; i*=10;}
x=j;
while (i>1)
{
if (x % 10 != x / i) return false;
else
{
x/=10; i/=10;
x%=i; i/=10;
}
}
return true;
}
- However, it could be better. For initializing i, we need j to record x and do division again and again. Think another way, we multiply i rather than divide j, then we can keep x unchanged and j could be removed.
- Then you get the final version, one integer, O(n), really short codes to solve it.
bool isPalindrome(int x)
{
if(x<0) return false;
int j=1;
while (x/j>=10) j*=10;
while (j>1)
{
if (x/j != x % 10) return false;
x%=j; x/=10; j/=100;
}
return true;
}
FAST!