I was solving Nth root of M problem and I solved it with Java and here is the solution:
public int NthRoot(int n, int m)
{
// code here
int ans = -1;
if (m == 0)
return ans;
if (n == 1 || n == 0)
return m;
if (m == 1)
return 1;
int low = 1;
int high = m;
while (low < high) {
int mid = (low + high) / 2;
int pow = (int)Math.pow(mid, n);
if (pow == m) {
ans = mid;
break;
}
if (pow > m) {
high = mid;
} else {
low = mid + 1;
}
}
return ans;
}
It passed all the test cases. But, when I solved it using C++, some test cases didn't pass. Here is the C++ solution:
int NthRoot(int n, int m)
{
// Code here.
int ans = -1;
if (m == 0)
return ans;
if (n == 1 || n == 0)
return m;
if (m == 1)
return 1;
int low = 1;
int high = m;
while (low < high) {
int mid = (low + high) / 2;
int po = (int)pow(mid, n);
if (po == m) {
ans = (int)mid;
break;
}
if (po > m) {
high = mid;
} else {
low = mid + 1;
}
}
return ans;
}
One of the test cases it didn't pass is:
6 4096
Java's output is 4 (Expected result)
C++'s output is -1 (Incorrect result)
When I traced it using paper and pen, I got a solution the same as Java's.
But, when I used long long int in the C++ code, it worked fine – but the size of Int/int in both Java and C++ are the same, right? (When I print INT_MAX and Integer.MAX_VALUE in C++ and Java, it outputs the same value.)
As you have probably guessed, the problem is due to the attempt to convert a double value to an int value, when that source is larger than the maximum representable value of an int. More specifically, it relates to the difference between how Java and C++ handle the cast near the start of your while loop: int po = (int)pow(mid, n);.
For your example input (6 4096), the value returned by the pow function on the first run through that loop is 7.3787e+19, which is too big for an int value. In Java, when you attempt to cast a too-big value to an integer, the result is the maximum value representable by the integer type, as specified in this answer (bolding mine):
The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest
representable value of type int or long.
However, in C++, when the source value exceeds INT_MAX, the behaviour is undefined (according to this C++11 Draft Standard):
7.10 Floating-integral conversions [conv.fpint]
1 A prvalue of a floating-point
type can be converted to a prvalue of an integer type. The conversion
truncates; that is, the fractional part is discarded. The behavior is
undefined if the truncated value cannot be represented in the
destination type.
However, although formally undefined, many/most compilers/platforms will apply 'rollover' when this occurs, resulting in a very large negative value (typically, INT_MIN) for the result. This is what MSVC in Visual Studio does, giving a value of -2147483648, thus causing the else block to run … and keep running until the while loop reaches its terminating condition – at which point ans will never have been assigned any value except the initial -1.
You can fix the problem readily by checking the double returned by the pow call and setting po to INT_MAX, if appropriate, to emulate the Java bevahiour:
while (low < high) {
int mid = (low + high) / 2;
double fpo = pow(mid, n);
int po = (int)(fpo);
if (fpo > INT_MAX) po = INT_MAX; // Emulate Java for overflow
if (po == m) {
ans = (int)mid;
break;
}
if (po > m) {
high = mid;
}
else {
low = mid + 1;
}
}
Related
I am trying Leetcode Question - 69. Sqrt(x)
Given a non-negative integer x, compute and return the square root of x.
Since the return type is an integer, the decimal digits are truncated, and only the integer part of the result is returned.
Note: You are not allowed to use any built-in exponent function or operator, such as pow(x, 0.5) or x ** 0.5.
class Solution {
public int mySqrt(int x) {
int ans = 0;
int i=1;
while(i*i<=x){
ans = i;
i++;
}
return ans;
}
}
This is the code I came up with. But the testcase input=2147395600 is not passing.
My Output = 289398
Expected Output = 46340
I'm confused as I have put the condition i*i<=x, then how can ans be more than the sqrt value?
Since you are comparing i * i with the input x, if the input x is too close to Integer.MAX_VALUE (2.147.483.647), like in that test case, i * i will be bigger than the maximum value allowed for an int to have and i*i<=x will be true.
Possible solutions:
Implement a binary search algorithm where max would be the floor(sqrt(Integer.MAX_VALUE)) or 46340.
Implement a algorithm where ans, i and x are declared locally as long type variables and in the return line you return the value cast to int using return (int)ans;
By running the following algorithm you can see the limit of a java int exploding and what happens afterwards.
int x = 2;
while(true) {
System.out.println(x);
x *= 2;
}
Not pretending to be fast, just the idea that (n+1)2=n2 + 2n + 1:
public static int mySqrt(int x) {
int i = 0;
while (x >= 0) {
x -= (i++ << 1) + 1;
}
return i - 1;
}
My JavaScript Solution
var mySqrt = function(x) {
var ans = 1;
if(x === 0){
ans = 0;
} else {
for (let i = 1; i< x;i++){
if(i*i === x){
ans = i;
break;
}
if(i*i >x){
ans = i - 1;
break;
}
}
}
return ans;
};
Using recursion, If n is 123, the code should return 4 (i.e. 1+3). But instead it is returning the last digit, in this case 3.
public static int sumOfOddDigits(NaturalNumber n) {
int ans = 0;
if (!n.isZero()) {
int r = n.divideBy10();
sumOfOddDigits(n);
if (r % 2 != 0) {
ans = ans + r;
}
n.multiplyBy10(r);
}
return ans;
}
It isn't clear what NaturalNumber is or why you would prefer it to int, but your algorithm is easy enough to follow with int (and off). First, you want the remainder (or modulus) of division by 10. That is the far right digit. Determine if it is odd. If it is add it to the answer, and then when you recurse divide by 10 and make sure to add the result to the answer. Like,
public static int sumOfOddDigits(int n) {
int ans = 0;
if (n != 0) {
int r = n % 10;
if (r % 2 != 0) {
ans += r;
}
ans += sumOfOddDigits(n / 10);
}
return ans;
}
One problem is that you’re calling multiplyBy on n and not doing anything with the result. NaturalNumber seems likely to be immutable, so the method call has no effect.
But using recursion lets you write declarative code, this kind of imperative logic isn’t needed. instead of mutating local variables you can use the argument list to hold the values to be used in the next iteration:
public static int sumOfOddDigits(final int n) {
return sumOfOddDigits(n, 0);
}
// overload to pass in running total as an argument
public static int sumOfOddDigits(final int n, final int total) {
// base case: no digits left
if (n == 0)
return total;
// n is even: check other digits of n
if (n % 2 == 0)
return sumOfOddDigits(n / 10, total);
// n is odd: add last digit to total,
// then check other digits of n
return sumOfOddDigits(n / 10, n % 10 + total);
}
I'm writing a program that determines how many comparisons it takes to run a binary search algorithm for a given number and sorted array. What I don't understand is what counts as a comparison.
// returns the number of comparisons it takes to find key in sorted list, array
public static int binarySearch(int key, int[] array) {
int left = 0;
int mid;
int right = array.length - 1;
int i = 0;
while (true) {
if (left > right) {
mid = -1;
break;
}
else {
mid = (left + right)/2;
if (key < array[mid]) {
i++;
right = mid - 1;
}
else if (key > array[mid]) {
i++;
left = mid + 1;
}
else {
break; // success
}
}
}
return i;
}
The function returns i, which is supposed to be the total number of comparisons made in finding the key in array. But what defines a comparison? Is it any time there is a conditional?
Thanks for any help, just trying to understand this concept.
Usually, a comparison occurs each time the key is compared to an array element. The code seems to not be counting that, though. It is counting how many times one of the search boundaries (left or right) is changed. It's not exactly the same thing being counted, but it's pretty close to the same thing, since the number of times a boundary is shifted is directly related to the number of times through the loop and hence to the number of times a comparison is made. At most, the two ways of counting will be off by 1 or 2 (I didn't bother to figure that out exactly).
Note also that if one were to use the usual definition, the code could be rewritten to use Integer.compare(int,int) do a single comparison of key with array[mid] to determine whether key was less than, equal to, or greater than array[mid].
public static int binarySearch(int key, int[] array) {
int left = 0;
int mid;
int right = array.length - 1;
int i = 0;
while (left <= right) {
mid = (left + right)/2;
int comp = Integer.compare(key, array[mid]);
i++;
if (comp < 0) {
right = mid - 1;
}
else if (comp > 0) {
left = mid + 1;
}
else {
break; // success
}
}
return i;
}
I am working on the LeetCode question No.69 named sqrt(x)(https://leetcode.com/problems/sqrtx/). It asked me to return the square root of the integer also in another integer. Below is my solution.
public class Solution {
public int mySqrt(int x) {
int i = 0;
if(x==0)
{
return 0;
}
for(i = 1;i<x/2;i++)
{
if(((i*i)<=x)&&((i+1)*(i+1)>x))
{
break;
}
}
return i;
}
}
After I submit the code, all the test cases where x >= 2147395600 are all failed. When x = 2147395600, it is returning a 289398 instead of 46340, which is the right answer. What is the problem with my code?
You can try my code:
public int mySqrt(int x) {
long i = 0;
long j = x;
int mid = 0;
if (x == 0) {
return 0;
}
if (x == 1) {
return 1;
}
while (i <= j) {
mid = (int)(i + j)/2;
if (x/mid == mid) {
return (int)mid;
} else if (x/mid > mid) {
i = mid + 1;
} else if (x/mid < mid) {
j = mid - 1;
}
}
return (int)j;
}
Instead of int, use long. This is because int only goes up to 2147395600, while long goes much higher than that. However, the expense is that you would have to convert to long, then back to int.
I had the same problem but simply by add a typecast (long) in front of the ii expression, I solved it. The problem lay with the fact that ii was exceeding the limit of the value that can be held by int and hence a garbage value was being returned.
PS: This solution is super slow so do consider other solutions like Binary Search provided above.
You have declared i as an int and trying to do sqaure of i, which will throw error as int cannot hold such large values, use long to declare i or caste it i to long. But why do this when you can do it in O(log n) using Binary Search.
I have a peculiar problem for which I am looking for an efficient solution. I have a byte array which contains the most significant n bytes of an unsigned 4 byte integer (most sig byte first). The value of the remaining bytes (if any) are unknown. I need to check whether the partially known integer value could fall within a certain range (+ or - x) of a known integer. It's also valid for the integer represented by the byte array under test to wrap around.
I have a solution which works (below). The problem is that this solution performs way more comparisons than I believe is necessary and a whole load of comparisons will be duplicated in the scenario in which least sig bytes are unknown. I'm pretty sure it can be done more efficiently but can't figure out how. The scenario in which least significant bytes are unknown is an edge case so I might be able to live with it but it forms part of a system which needs to have low latency so if anyone could help with this that would be great.
Thanks in advance.
static final int BYTES_IN_INT = 4;
static final int BYTE_SHIFT = 010;
// partial integer byte array length guaranteed to be 1-4 so no checking necessary
static boolean checkPartialIntegerInRange(byte[] partialIntegerBytes, int expectedValue, int range)
{
boolean inRange = false;
if(partialIntegerBytes.length == BYTES_IN_INT)
{
// normal scenario, all bytes known
inRange = Math.abs(ByteBuffer.wrap(partialIntegerBytes).getInt() - expectedValue) <= range;
}
else
{
// we don't know least significant bytes, could have any value
// need to check if partially known int could lie in the range
int partialInteger = 0;
int mask = 0;
// build partial int and mask
for (int i = 0; i < partialIntegerBytes.length; i++)
{
int shift = ((BYTES_IN_INT - 1) - i) * BYTE_SHIFT;
// shift bytes to correct position
partialInteger |= (partialIntegerBytes[i] << shift);
// build up mask to mask off expected value for comparison
mask |= (0xFF << shift);
}
// check partial int falls in range
for (int i = -(range); i <= range; i++)
{
if (partialInteger == ((expectedValue + i) & mask))
{
inRange = true;
break;
}
}
}
return inRange;
}
EDIT: Thanks to the contributors below. Here is my new solution. Comments welcome.
static final int BYTES_IN_INT = 4;
static final int BYTE_SHIFT = 010;
static final int UBYTE_MASK = 0xFF;
static final long UINT_MASK = 0xFFFFFFFFl;
public static boolean checkPartialIntegerInRange(byte[] partialIntegerBytes, int expectedValue, int range)
{
boolean inRange;
if(partialIntegerBytes.length == BYTES_IN_INT)
{
inRange = Math.abs(ByteBuffer.wrap(partialIntegerBytes).getInt() - expectedValue) <= range;
}
else
{
int partialIntegerMin = 0;
int partialIntegerMax = 0;
for(int i=0; i < BYTES_IN_INT; i++)
{
int shift = ((BYTES_IN_INT - 1) - i) * BYTE_SHIFT;
if(i < partialIntegerBytes.length)
{
partialIntegerMin |= (((partialIntegerBytes[i] & UBYTE_MASK) << shift));
partialIntegerMax = partialIntegerMin;
}
else
{
partialIntegerMax |=(UBYTE_MASK << shift);
}
}
long partialMinUnsigned = partialIntegerMin & UINT_MASK;
long partialMaxUnsigned = partialIntegerMax & UINT_MASK;
long rangeMinUnsigned = (expectedValue - range) & UINT_MASK;
long rangeMaxUnsigned = (expectedValue + range) & UINT_MASK;
if(rangeMinUnsigned <= rangeMaxUnsigned)
{
inRange = partialMinUnsigned <= rangeMaxUnsigned && partialMaxUnsigned >= rangeMinUnsigned;
}
else
{
inRange = partialMinUnsigned <= rangeMaxUnsigned || partialMaxUnsigned >= rangeMinUnsigned;
}
}
return inRange;
}
Suppose you have one clockwise interval (x, y) and one normal interval (low, high) (each including their endpoints), determining whether they intersect can be done as (not tested):
if (x <= y) {
// (x, y) is a normal interval, use normal interval intersect
return low <= y && high >= x;
}
else {
// (x, y) wraps
return low <= y || high >= x;
}
To compare as unsigned integers, you can use longs (cast up with x & 0xffffffffL to counteract sign-extension) or Integer.compareUnsigned (in newer versions of Java) or, if you prefer you can add/subtract/xor both operands with Integer.MIN_VALUE.
Convert your unsigned bytes to an integer. Right-shift by 32-n (so your meaningful bytes are the min bytes). Right-shift your min/max integers by the same amount. If your shifted test value is equal to either shifted integer, it might be in the range. If it's between them, it's definitely in the range.
Presumably the sign bit on your integers is always zero (if not, just forcibly convert the negative to zero, since your test value can't be negative). But because that's only one bit, unless you were given all 32 bits as n, that shouldn't matter (it's not much of a problem in that special case).