Start learning free

LESSON 278 OF 410 · RECURSION

Power Calculation in Java with Time Complexity Analysis

Practice O(log n) Read the full explanation

Given two positive integers a and n, calculate an modulo 1337.

Example 1:

Input: a = 2, n = 3
Output: 8

Example 2:

Input: a = 2, n = 10
Output: 1024

Example 3:

Input: a = 1, n = 1000
Output: 1

Example 4:

Input: a = 2147483647, n = 200
Output: 1198

 

Constraints:

  • 1 <= a, n <= 231 - 1

STEP 1 OF 6
    Ctrl + Enter to check

    JAVA · RECURSION

    Power in Java, explained

    Understanding the Problem

    The core challenge of this problem is to compute large powers efficiently. Direct computation of an can result in extremely large numbers, especially given the constraints where a and n can be as large as 231 - 1. This necessitates an efficient algorithm to handle such large computations.

    Common applications of this problem include cryptography, computer graphics, and numerical simulations where modular exponentiation is frequently used.

    Potential pitfalls include integer overflow and inefficient algorithms that do not scale well with large inputs.

    Approach

    To solve this problem, we can use the method of Exponentiation by Squaring, which is an efficient way to compute large powers modulo some number. This method reduces the time complexity significantly compared to the naive approach.

    Naive Solution

    The naive solution involves multiplying a by itself n times and then taking the result modulo 1337. This approach is not feasible for large values of n due to its time complexity of O(n) and the risk of integer overflow.

    Optimized Solution: Exponentiation by Squaring

    Exponentiation by squaring reduces the time complexity to O(log n). The idea is to break down the power computation into smaller parts using the properties of exponents:

    • If n is even, an = (an/2)2
    • If n is odd, an = a * an-1

    This approach allows us to compute the power in a logarithmic number of steps.

    Algorithm

    Here is a step-by-step breakdown of the Exponentiation by Squaring algorithm:

    1. Initialize the result as 1.
    2. While n is greater than 0:
      • If n is odd, multiply the result by a and take modulo 1337.
      • Square a and take modulo 1337.
      • Divide n by 2.
    3. Return the result.

    Code Implementation

    public class PowerCalculation {
        // Function to calculate (a^n) % 1337
        public static int powerMod(int a, int n) {
            int mod = 1337;
            int result = 1;
            a = a % mod; // Update a if it is more than or equal to mod
    
            while (n > 0) {
                // If n is odd, multiply a with result
                if ((n & 1) == 1) {
                    result = (result * a) % mod;
                }
                // n must be even now
                n = n >> 1; // n = n / 2
                a = (a * a) % mod; // Change a to a^2
            }
            return result;
        }
    
        public static void main(String[] args) {
            // Test cases
            System.out.println(powerMod(2, 3)); // Output: 8
            System.out.println(powerMod(2, 10)); // Output: 1024
            System.out.println(powerMod(1, 1000)); // Output: 1
            System.out.println(powerMod(2147483647, 200)); // Output: 1198
        }
    }
    

    Complexity Analysis

    The time complexity of the Exponentiation by Squaring algorithm is O(log n) because we halve the exponent in each step. The space complexity is O(1) as we use a constant amount of extra space.

    Compared to the naive approach with a time complexity of O(n), the optimized solution is significantly faster and more efficient for large values of n.

    Edge Cases

    Potential edge cases include:

    • a = 1 and any n: The result is always 1.
    • n = 0: The result is 1 (by definition of any number to the power of 0).
    • Very large values of a and n: The algorithm handles these efficiently due to modular arithmetic and logarithmic time complexity.

    Testing

    To test the solution comprehensively, include a variety of test cases:

    • Simple cases: a = 2, n = 3
    • Large exponents: a = 2, n = 1000
    • Edge cases: a = 1, n = 1000
    • Maximum constraints: a = 2147483647, n = 200

    Use testing frameworks like JUnit for automated testing.

    Thinking and Problem-Solving Tips

    When approaching such problems:

    • Understand the problem constraints and requirements.
    • Consider the limitations of naive solutions and look for optimized algorithms.
    • Break down the problem into smaller, manageable parts.
    • Practice similar problems to improve problem-solving skills.

    Conclusion

    In this blog post, we discussed how to efficiently compute large powers modulo a number using the Exponentiation by Squaring algorithm. This method significantly reduces the time complexity and handles large inputs effectively. Understanding and implementing such algorithms is crucial for solving complex computational problems efficiently.

    Additional Resources

    For further reading and practice:

    Keep going with JavaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free