Given two integers n and m, find the n-th root of m. The n-th root of m is an integer x such that x^n = m. If no such integer exists, return -1.
Examples:
Input: n = 3, m = 27
Output: 3
Explanation: 33 = 27Input: n = 3, m = 9
Output: -1
Explanation: 3rd root of 9 is not integer.
Table of Content
[Approach 1] Using Binary Search - O(n * log(m)) Time and O(1) Space
The idea is to search within the range from 1 to m. In each step, we do the following
- The middle value is raised to the power of n and compared to m. If it equals m, that value is the root.
- If it is greater, the search continues in the lower half; if smaller, in the upper half.
This process repeats until the root is found or the range is exhausted. If no exact integer root exists, the function returns -1.
#include <iostream>
#include <vector>
using namespace std;
// function to calculate base^expo
// returns early if result exceeds the
// given limit to avoid overflow
int power(int base, int expo, int limit) {
int result = 1;
for (int i = 0; i < expo; i++) {
result *= base;
if (result > limit)
return result;
}
return result;
}
// function to find the
// n-th root of m
int nthRoot(int n, int m) {
// n-th root of 0 is 0
if (m == 0) return 0;
// If n is 1, the answer
// is m itself
if (n == 1) return m;
// binary search to find
// the integer root
int low = 1, high = m;
while (low <= high) {
int mid = (low + high) / 2;
// compute mid^n and compare it with m
int val = power(mid, n, m);
if (val == m)
return mid;
else if (val < m)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
int main() {
int n = 3, m = 27;
int result = nthRoot(n, m);
cout << result << endl;
return 0;
}
class GfG {
// function to calculate base^expo
// returns early if result exceeds the
// given limit to avoid overflow
static int power(int base, int expo, int limit) {
int result = 1;
for (int i = 0; i < expo; i++) {
result *= base;
if (result > limit)
return result;
}
return result;
}
// function to find the
// n-th root of m
static int nthRoot(int n, int m) {
// n-th root of 0 is 0
if (m == 0) return 0;
// If n is 1, the answer
// is m itself
if (n == 1) return m;
// binary search to find
// the integer root
int low = 1, high = m;
while (low <= high) {
int mid = (low + high) / 2;
// compute mid^n and compare it with m
int val = power(mid, n, m);
if (val == m)
return mid;
else if (val < m)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
public static void main(String[] args) {
int n = 3, m = 27;
int result = nthRoot(n, m);
System.out.println(result);
}
}
# function to calculate base^expo
# returns early if result exceeds the
# given limit to avoid overflow
def power(base, expo, limit):
result = 1
for _ in range(expo):
result *= base
if result > limit:
return result
return result
# function to find the
# n-th root of m
def nthRoot(n, m):
# n-th root of 0 is 0
if m == 0:
return 0
# If n is 1, the answer
# is m itself
if n == 1:
return m
# binary search to find
# the integer root
low, high = 1, m
while low <= high:
mid = (low + high) // 2
# compute mid^n and compare it with m
val = power(mid, n, m)
if val == m:
return mid
elif val < m:
low = mid + 1
else:
high = mid - 1
return -1
if __name__ == "__main__":
n = 3
m = 27
result = nthRoot(n, m)
print(result)
using System;
class GfG{
// function to calculate base^expo
// returns early if result exceeds the
// given limit to avoid overflow
static int power(int baseVal, int expo, int limit){
int result = 1;
for (int i = 0; i < expo; i++){
result *= baseVal;
if (result > limit)
return result;
}
return result;
}
// function to find the
// n-th root of m
static int nthRoot(int n, int m){
// n-th root of 0 is 0
if (m == 0) return 0;
// If n is 1, the answer
// is m itself
if (n == 1) return m;
// binary search to find
// the integer root
int low = 1, high = m;
while (low <= high){
int mid = (low + high) / 2;
// compute mid^n and compare it with m
int val = power(mid, n, m);
if (val == m)
return mid;
else if (val < m)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
static void Main(string[] args){
int n = 3, m = 27;
int result = nthRoot(n, m);
Console.WriteLine(result);
}
}
// function to calculate base^expo
// returns early if result exceeds the
// given limit to avoid overflow
function power(base, expo, limit) {
let result = 1;
for (let i = 0; i < expo; i++) {
result *= base;
if (result > limit)
return result;
}
return result;
}
// function to find the
// n-th root of m
function nthRoot(n, m) {
// n-th root of 0 is 0
if (m === 0) return 0;
// If n is 1, the answer
// is m itself
if (n === 1) return m;
// binary search to find
// the integer root
let low = 1, high = m;
while (low <= high) {
let mid = Math.floor((low + high) / 2);
// compute mid^n and compare it with m
let val = power(mid, n, m);
if (val === m)
return mid;
else if (val < m)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
// Driver Code
const n = 3, m = 27;
const result = nthRoot(n, m);
console.log(result);
Output
3
[Approach 2] Using Newton's Method
This problem involves finding the real-valued function
A^{1/N} , which can be solved using Newton's method. The method begins with an initial guess and iteratively refines the result.
By applying Newton's method, we derive a relation between consecutive iterations:
According to Newton's method:
Here, we define the function f(x) as:
f(x) = xN- A
The derivative of f(x), denoted f'(x), is:
The value xk represents the approximation at the k-th iteration. By substituting f(x) and f'(x) into the Newton's method formula, we obtain the following update relation:
Using this relation, the problem can be solved by iterating over successive values of x until the difference between consecutive iterations is smaller than the desired accuracy.
Note: The code below returns the approx value so we use the check to find the if the real nth root is exact.
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
int nthRoot(int m, int n) {
if (n == 1) {
return m;
}
double xPre = rand() % 10 + 1;
// Smaller eps denotes more accuracy
double eps = 1e-3;
// Initializing difference
// between two roots
double delX = INT_MAX;
// xK denotes current value of x
double xK;
// Loop until we reach the
// desired accuracy
while (delX > eps) {
// Calculating the current value from
// the previous value by Newton's method
xK = ((n - 1.0) * xPre + (double)m / pow(xPre, n - 1)) / (double)n;
delX = abs(xK - xPre);
xPre = xK;
}
return (int)round(xK);
}
// Function to check if rootCandidate
// is exactly the nth root of m
int check(int m, int n, int rootCandidate) {
int result = 1;
for (int i = 0; i < n; i++) {
// Detect overflow
if (abs(result) > INT_MAX / abs(rootCandidate)) {
// overflow means it's not a valid perfect root
return -1;
}
result *= rootCandidate;
}
return (result == m) ? rootCandidate : -1;
}
int main() {
int n = 3, m = 27;
int nthRootValue = nthRoot(m, n);
int verifiedValue = check(m, n, nthRootValue);
cout << verifiedValue << endl;
return 0;
}
class GfG {
public static int nthRoot(int m, int n) {
if (n == 1) {
return m;
}
double xPre = (int)(Math.random() * 10) + 1;
// Smaller eps denotes more accuracy
double eps = 1e-3;
// Initializing difference
// between two roots
double delX = Integer.MAX_VALUE;
// xK denotes current value of x
double xK = 0;
// Loop until we reach the
// desired accuracy
while (delX > eps) {
// Calculating the current value from
// the previous value by Newton's method
xK = ((n - 1.0) * xPre + (double) m / Math.pow(xPre, n - 1)) / (double) n;
delX = Math.abs(xK - xPre);
xPre = xK;
}
return (int) Math.round(xK);
}
// Function to check if rootCandidate
// is exactly the nth root of m
public static int check(int m, int n, int rootCandidate) {
int result = 1;
for (int i = 0; i < n; i++) {
// Detect overflow
if (Math.abs(result) > Integer.MAX_VALUE / Math.abs(rootCandidate)) {
// overflow means it's not a valid perfect root
return -1;
}
result *= rootCandidate;
}
return (result == m) ? rootCandidate : -1;
}
public static void main(String[] args) {
int n = 3, m = 27;
int nthRootValue = nthRoot(m, n);
int verifiedValue = check(m, n, nthRootValue);
System.out.println(verifiedValue);
}
}
import math
import random
import sys
def nthRoot(m, n):
if n == 1:
return m
xPre = random.randint(1, 10)
# Smaller eps denotes more accuracy
eps = 1e-3
# Initializing difference
# between two roots
delX = sys.maxsize
# xK denotes current value of x
xK = 0
# Loop until we reach the
# desired accuracy
while delX > eps:
# Calculating the current value from
# the previous value by Newton's method
xK = ((n - 1.0) * xPre + float(m) / math.pow(xPre, n - 1)) / float(n)
delX = abs(xK - xPre)
xPre = xK
return int(round(xK))
# Function to check if rootCandidate
# is exactly the nth root of m
def check(m, n, rootCandidate):
result = 1
for _ in range(n):
# Detect overflow (Python ints can grow,
# but we mimic C++ int overflow detection)
if abs(result) > (2**31 - 1) // abs(rootCandidate):
# overflow means it's not a valid perfect root
return -1
result *= rootCandidate
return rootCandidate if result == m else -1
if __name__ == "__main__":
n = 3
m = 27
nthRootValue = nthRoot(m, n)
verifiedValue = check(m, n, nthRootValue)
print(verifiedValue)
using System;
class GfG {
static int nthRoot(int m, int n){
if (n == 1){
return m;
}
Random rand = new Random();
double xPre = rand.Next(1, 11);
// Smaller eps denotes more accuracy
double eps = 1e-3;
// Initializing difference
// between two roots
double delX = int.MaxValue;
// xK denotes current value of x
double xK = 0;
// Loop until we reach the
// desired accuracy
while (delX > eps){
// Calculating the current value from
// the previous value by Newton's method
xK = ((n - 1.0) * xPre + (double)m / Math.Pow(xPre, n - 1)) / (double)n;
delX = Math.Abs(xK - xPre);
xPre = xK;
}
return (int)Math.Round(xK);
}
// Function to check if rootCandidate
// is exactly the nth root of m
static int check(int m, int n, int rootCandidate){
int result = 1;
for (int i = 0; i < n; i++){
// Detect overflow
if (Math.Abs(result) > int.MaxValue / Math.Abs(rootCandidate)){
// overflow means it's not a valid perfect root
return -1;
}
result *= rootCandidate;
}
return (result == m) ? rootCandidate : -1;
}
static void Main(string[] args){
int n = 3, m = 27;
int nthRootValue = nthRoot(m, n);
int verifiedValue = check(m, n, nthRootValue);
Console.WriteLine(verifiedValue);
}
}
function nthRoot(m, n) {
if (n === 1) {
return m;
}
let xPre = Math.floor(Math.random() * 10) + 1; // Equivalent to rand() % 10 + 1
// Smaller eps denotes more accuracy
let eps = 1e-3;
// Initializing difference
// between two roots
let delX = Number.MAX_VALUE;
// xK denotes current value of x
let xK;
// Loop until we reach the
// desired accuracy
while (delX > eps) {
// Calculating the current value from
// the previous value by Newton's method
xK = ((n - 1.0) * xPre + m / Math.pow(xPre, n - 1)) / n;
delX = Math.abs(xK - xPre);
xPre = xK;
}
return Math.round(xK);
}
// Function to check if rootCandidate
// is exactly the nth root of m
function check(m, n, rootCandidate) {
let result = 1;
for (let i = 0; i < n; i++) {
// Detect overflow simulation (JS numbers won't overflow like C++)
if (Math.abs(result) > Number.MAX_SAFE_INTEGER / Math.abs(rootCandidate)) {
// overflow means it's not a valid perfect root
return -1;
}
result *= rootCandidate;
}
return (result === m) ? rootCandidate : -1;
}
// Driver Code
let n = 3, m = 27;
let nthRootValue = nthRoot(m, n);
let verifiedValue = check(m, n, nthRootValue);
console.log(verifiedValue);
Output
3
Time Complexity: O(log(eps)), where eps is the desired accuracy.
Space Complexity: O(1)