I encountered the following in a leetcode article to determine whether an integer is a palindrome
Now let's think about how to revert the last half of the number. For number 1221, if we do 1221 % 10, we get the last digit 1, to get the second to the last digit, we need to remove the last digit from 1221, we could do so by dividing it by 10, 1221 / 10 = 122. Then we can get the last digit again by doing a modulus by 10, 122 % 10 = 2, and if we multiply the last digit by 10 and add the second last digit, 1 * 10 + 2 = 12, it gives us the reverted number we want. Continuing this process would give us the reverted number with more digits.
Now the question is, how do we know that we've reached the half of the number?
Since we divided the number by 10, and multiplied the reversed number by 10, when the original number is less than the reversed number, it means we've processed half of the number digits.
Can someone explain the last two sentences please?! Thank you!
Here is the enclosed C# code:
public class Solution {
public bool IsPalindrome(int x) {
// Special cases:
// As discussed above, when x < 0, x is not a palindrome.
// Also if the last digit of the number is 0, in order to be a palindrome,
// the first digit of the number also needs to be 0.
// Only 0 satisfy this property.
if(x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
int revertedNumber = 0;
while(x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
// When the length is an odd number, we can get rid of the middle digit by revertedNumber/10
// For example when the input is 12321, at the end of the while loop we get x = 12, revertedNumber = 123,
// since the middle digit doesn't matter in palidrome(it will always equal to itself), we can simply get rid of it.
return x == revertedNumber || x == revertedNumber/10;
}
}
The reason is due to the original given input, x will be decreasing by 1 digit while the reverted string increases by 1 digit at the same time. The process keeps on going until x is less than or equal to the reverted string. Hence due to the change length changes, when it terminates, we would approximately reach half of the string.
Let's visit a few examples with positive numbers to understand the process. I would write (x,y) as the (original number, reverted string). The third example is purposely designed to show that it need not be exactly half though but the code would still work.
The first example is 1221, where there are even number of digits. It will go from (1221, 0) to (122, 1) to (12, 12), at this stage, the two terms are equal and hence the process terminates and we can conclude that it is a palindrome.
The next example is 1223, where there are even number of digits. It will go from (1223, 0) to (122, 3) to (12, 32), at this stage, the termination condition holds and hence the process terminates and we can conclude that it is not a palindrome.
Now, the third example is 1211,then the sequence is (1211,0), (121, 1), (12,11), (1,112), after which we terminates from the string and it would conclude that it is not a palindrome
Now, let's make the number consists of odd number of digits:
For 12321. It will go from (12321, 0) to (1232, 1) to (123, 12) to (12, 123) and at this point, the condition breaks. We then divide the reverted string by 10 and we end up with (12,12) and we can conclude that it is a palindrome.
For 12323. It will go from (12323, 0) to (1232, 3) to (123, 32) to (12, 323) and at this point, the condition breaks. We then divide the reverted string by 10 and we end up with (12,32) and we can conclude that it is not a palindrome.
For 12311. It will go from (12311, 0) to (1231, 1) to (123, 11) to (12, 113) and at this point, the condition breaks. We then divide the reverted string by 10 and we end up with (12,11) and we can conclude that it is not a palindrome.
I hope these examples would help you to understand what the post mean.
Related
I was asked this question in a HackerEarth test and I couldn't wrap my head around even forming the algorithm.
The question is -
Count the number of substrings of a string, such that any of their permutations is a palindrome.
So, for aab, the answer is 5 - a, a, b, aa and aab (which can be permuted to form aba).
I feel this is dynamic programming, but I can't find what kind of relations the subproblems might have.
Edit:
So I think the recursive relation might be
dp[i] = dp[i-1] + 1 if str[i] has already appeared before and
substring ending at i-1 has at most 2 characters with odd frequency
else dp[i] = dp[i-1]
No idea if this is right.
I can think of O(n^2) - traverse substrings of length > 1, from indexes (0, 1) up to (0, n-1), then from (1, n-1) down to (1, 3), then from (2, 3) up to (2, n-2), then from (3, n-2) down to (3, 5)...etc.
While traversing, maintain a map of current frequency for each character, as well as totals of the number of characters with odd counts and the number of characters with even counts. Update those on each iteration and add to the total count of palindromic permuted substrings if we are on a substring with (1) odd length and only one character with odd frequency, or (2) even length and no character with odd frequency.
(Add the string length for the count of single character palindromes.)
If I did not misunderstand your question, I tend to believe this is a math problem. Say the length of a string is n, then the answer should be n * (n+1) / 2, the sum of an infinite series. See https://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF
For example, string abcde, we can get substrings
a, b, c, d, e,
ab, bc, cd, de,
abc, bcd, cde,
abcd, bcde,
abcde .
You may find the answer from the way I listed the substrings.
So here is my solution that may help you.
you can get a list of every possible substring of input by running a nested loop and for every substring you have to check if the substring can form a palindrome or not.
now how to check if a string/substring can form palindrome:
If a substring is having alphabet of odd number of occurance more than 1, them it can't form a palindrome.Here is the code:
bool stringCanbeFormAPalindrome(string s)
{
int oddValues, alphabet[26];
for(int i =0; i< s.length(); i++)
{
alphabet[s[i]-'a']++;
}
for(int i=0; i<26; i++)
{
if(alphabet[i]%2==1)
{
oddValues++;
if(oddValues>1) return FALSE;
}
}
return TRUE;
}
May that helps.
You can do it easily in O(N) time and O(N) space complexity
notice, the only thing that if the permutation of substring is palindrome or not is the parity of odd character in it so just create a mask of parity of every character, now for any valid substring there can be at most 1 bit different to our current mask, let's iterate on which bit is different, and adding the corresponding answer.
Here's a C++ code (assuming unordered_map is O(1) per query)
string s;
cin>>s;
int n=s.length();
int ans=0;
unordered_map<int,int>um;
um[0]=1;
int mask=0;
for(int i=0;i<n;++i){
mask^=1<<(s[i]-'a');
ans+=um[mask];
for(int j=27;j>=0;--j){
ans+=um[mask^(1<<j)];
}
um[mask]++;
}
cout<<ans;
take care of integer overflow.
Given that a number can contain only digits from 1 to 8 (with no repetition), and is of length 8, how can we hash such numbers without using a hashSet?
We can't just directly use the value of the number of the hashing value, as the stack size of the program is limited. (By this, I mean that we can't directly make the index of an array, represent our number).
Therefore, this 8 digit number needs to be mapped to, at maximum, a 5 digit number.
I saw this answer. The hash function returns a 8-digit number, for a input that is an 8-digit number.
So, what can I do here?
There's a few things you can do. You could subtract 1 from each digit and parse it as an octal number, which will map one-to-one every number from your domain to the range [0,16777216) with no gaps. The resulting number can be used as an index into a very large array. An example of this could work as below:
function hash(num) {
return parseInt(num
.toString()
.split('')
.map(x => x - 1), 8);
}
const set = new Array(8**8);
set[hash(12345678)] = true;
// 12345678 is in the set
Or if you wanna conserve some space and grow the data structure as you add elements. You can use a tree structure with 8 branches at every node and a maximum depth of 8. I'll leave that up to you to figure out if you think it's worth the trouble.
Edit:
After seeing the updated question, I began thinking about how you could probably map the number to its position in a lexicographically sorted list of the permutations of the digits 1-8. That would be optimal because it gives you the theoretical 5-digit hash you want (under 40320). I had some trouble formulating the algorithm to do this on my own, so I did some digging. I found this example implementation that does just what you're looking for. I've taken inspiration from this to implement the algorithm in JavaScript for you.
function hash(num) {
const digits = num
.toString()
.split('')
.map(x => x - 1);
const len = digits.length;
const seen = new Array(len);
let rank = 0;
for(let i = 0; i < len; i++) {
seen[digits[i]] = true;
rank += numsBelowUnseen(digits[i], seen) * fact(len - i - 1);
}
return rank;
}
// count unseen digits less than n
function numsBelowUnseen(n, seen) {
let count = 0;
for(let i = 0; i < n; i++) {
if(!seen[i]) count++;
}
return count;
}
// factorial fuction
function fact(x) {
return x <= 0 ? 1 : x * fact(x - 1);
}
kamoroso94 gave me the idea of representing the number in octal. The number remains unique if we remove the first digit from it. So, we can make an array of length 8^7=2097152, and thus use the 7-digit octal version as index.
If this array size is bigger than the stack, then we can use only 6 digits of the input, convert them to their octal values. So, 8^6=262144, that is pretty small. We can make a 2D array of length 8^6. So, total space used will be in the order of 2*(8^6). The first index of the second dimension represents that the number starts from the smaller number, and the second index represents that the number starts from the bigger number.
Let's say I want to generate a random number between 1 and 100, but I don't want to include 42. How would I do this without repeating the random method until it is not 42.
Updated for Swift 5.1
Excluding 1 value
var nums = [Int](1...100)
nums.remove(at: 42)
let random = Int(arc4random_uniform(UInt32(nums.count)))
print(nums[random])
Excluding multiple values
This extension of Range does provide a solution when you want to exclude more than 1 value.
extension ClosedRange where Element: Hashable {
func random(without excluded:[Element]) -> Element {
let valid = Set(self).subtracting(Set(excluded))
let random = Int(arc4random_uniform(UInt32(valid.count)))
return Array(valid)[random]
}
}
Example
(1...100).random(without: [40,50,60])
I believe the computation complexity of this second solution is O(n) where n is the number of elements included in the range.
The assumption here is the no more than n excluded values are provided by the caller.
appzYourLife has some great general purpose solutions, but I want to tackle the specific problem in a lightweight way.
Both of these approaches work roughly the same way: Narrow the range to the random number generator to remove the impossible answer (99 answers instead of 100), then map the result so it isn't the illegal value.
Neither approach increases the probability of an outcome relative to another outcome. That is, assuming your random number function is perfectly random the result will still be random (and no 2x chance of 43 relative to 5, for instance).
Approach 1: Addition.
Get a random number from 1 to 99. If it's greater than or equal to the number you want to avoid, add one to it.
func approach1()->Int {
var number = Int(arc4random_uniform(99)+1)
if number >= 42 {
number = number + 1
}
return number
}
As an example, trying to generate a random number from 1-5 that's not 3, take a random number from 1 to 4 and add one if it's greater than or equal to 3.
rand(1..4) produces 1, +0, = 1
rand(1..4) produces 2, +0, = 2
rand(1..4) produces 3, +1, = 4
rand(1..4) produces 4, +1, = 5
Approach 2: Avoidance.
Another simple way would be to get a number from 1 to 99. If it's exactly equal to the number you're trying to avoid, make it 100 instead.
func approach2()->Int {
var number = Int(arc4random_uniform(99)+1)
if number == 42 {
number = 100
}
return number
}
Using this algorithm and narrowing the range to 1-5 (while avoiding 3) again, we get these possible outcomes:
rand(1..4) produces 1; allowed, so Result = 1
rand(1..4) produces 2, allowed, so Result = 2
rand(1..4) produces 3; not allowed, so Result = 5
rand(1..4) produces 4, allowed, so Result = 4
i want a code to define the prompted number by user is prime or not . since it's an assignment
i'm not allowed to use ' isprime ' predefined code .
the following approach was not useful :
N = input( 'please enter a positive enteger value = ' ) ;
Quotient = floor(N - (mod(N,2)./2)) ;
for i = 1 : Quotient
if mod(N,i ) == 0
fprintf(' your prompted number is not prime ' ) ;
if mod(N,i) ~= 0
fprintf(' your prompted number is prime ' ) ;
end
end
end
for example if i enter a prime number like 13 it results in this :
your prompted number is prime
but if i enter a Non-prime num like 12 it repeats the ' your prompted number is prime ' message for 10 times .
for i = 1 : Quotient
if mod(N,i ) == 0
That will give you every number since x mod 1 is always zero. In other words, the remainder (when you divide any positive integer by one) is zero, since all of them divide perfectly.
You need to start at 2 rather than 1.
In addition, once you've found out the number is not prime, you should stop the loop since there's no possibility of it becoming prime again after that :-) And, for efficiency, you only need to go up to the square root of the number since, if it has a factor above that, you would have already found the equivalent factor below that.
The pseudo-code for such a beast would be:
set isprime to true
set chkval to 2
while chkval * chkval <= number:
if number mod chkval is zero:
set isprime to false
exit while
end if
increment chkval
end while
if isprime:
say number, " is prime"
else:
say number, " is composite"
Try to find factors and as soon as you find one you know it's not prime:
prime = true
for f = 2:ceil(sqrt(N)) %// Start from 2 as prime numbers DO have 1 as a factor. Anything larger than sqrt(N) will have to have a corresponding factor smaller than this so there is no point checking them
if mod(N,f) == 0
prime = false;
break;
end
end
There are 2 problems with your code. First, as already explained by paxdiablo, you need to start your loop from 2. Secondly you have nested your if statements, and since they are mutually exclusive conditions, the inner condition will never trigger.
I want to convert the decimal number 27 into binary such a way that , first the digit 2 is converted and its binary value is placed in an array and then the digit 7 is converted and its binary number is placed in that array. what should I do?
thanks in advance
That's called binary-coded decimal. It's easiest to work right-to-left. Take the value modulo 10 (% operator in C/C++/ObjC) and put it in the array. Then integer-divide the value by 10 (/ operator in C/C++/ObjC). Continue until your value is zero. Then reverse the array if you need most-significant digit first.
If I understand your question correctly, you want to go from 27 to an array that looks like {0010, 0111}.
If you understand how base systems work (specifically the decimal system), this should be simple.
First, you find the remainder of your number when divided by 10. Your number 27 in this case would result with 7.
Then you integer divide your number by 10 and store it back in that variable. Your number 27 would result in 2.
How many times do you do this?
You do this until you have no more digits.
How many digits can you have?
Well, if you think about the number 100, it has 3 digits because the number needs to remember that one 10^2 exists in the number. On the other hand, 99 does not.
The answer to the previous question is 1 + floor of Log base 10 of the input number.
Log of 100 is 2, plus 1 is 3, which equals number of digits.
Log of 99 is a little less than 2, but flooring it is 1, plus 1 is 2.
In java it is like this:
int input = 27;
int number = 0;
int numDigits = Math.floor(Log(10, input)) + 1;
int[] digitArray = new int [numDigits];
for (int i = 0; i < numDigits; i++) {
number = input % 10;
digitArray[numDigits - i - 1] = number;
input = input / 10;
}
return digitArray;
Java doesn't have a Log function that is portable for any base (it has it for base e), but it is trivial to make a function for it.
double Log( double base, double value ) {
return Math.log(value)/Math.log(base);
}
Good luck.