leetcode
leetcode 2501 ~ 2550
双模幂运算

双模幂运算

难度:

标签:

题目描述

You are given a 0-indexed 2D array variables where variables[i] = [ai, bi, ci, mi], and an integer target.

An index i is good if the following formula holds:

  • 0 <= i < variables.length
  • ((aibi % 10)ci) % mi == target

Return an array consisting of good indices in any order.

 

Example 1:

Input: variables = [[2,3,3,10],[3,3,3,1],[6,1,1,4]], target = 2
Output: [0,2]
Explanation: For each index i in the variables array:
1) For the index 0, variables[0] = [2,3,3,10], (23 % 10)3 % 10 = 2.
2) For the index 1, variables[1] = [3,3,3,1], (33 % 10)3 % 1 = 0.
3) For the index 2, variables[2] = [6,1,1,4], (61 % 10)1 % 4 = 2.
Therefore we return [0,2] as the answer.

Example 2:

Input: variables = [[39,3,1000,1000]], target = 17
Output: []
Explanation: For each index i in the variables array:
1) For the index 0, variables[0] = [39,3,1000,1000], (393 % 10)1000 % 1000 = 1.
Therefore we return [] as the answer.

 

Constraints:

  • 1 <= variables.length <= 100
  • variables[i] == [ai, bi, ci, mi]
  • 1 <= ai, bi, ci, mi <= 103
  • 0 <= target <= 103

代码结果

运行时间: 21 ms, 内存: 16.1 MB


/*
 * 思路:
 * 对于每个变量组 [a, b, c, m],计算 (a^b % 10)^c % m 并判断是否等于 target。
 * 使用 Java Stream 处理数组。
 */

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SolutionStream {
    public List<Integer> findGoodIndices(int[][] variables, int target) {
        return IntStream.range(0, variables.length)
                .filter(i -> {
                    int a = variables[i][0];
                    int b = variables[i][1];
                    int c = variables[i][2];
                    int m = variables[i][3];
                    // 计算 (a^b % 10)
                    int mod = (int) (Math.pow(a, b) % 10);
                    // 计算 (mod^c) % m
                    int value = (int) (Math.pow(mod, c) % m);
                    // 判断是否等于 target
                    return value == target;
                })
                .boxed()
                .collect(Collectors.toList());
    }

    public static void main(String[] args) {
        SolutionStream solution = new SolutionStream();
        int[][] variables = {{2, 3, 3, 10}, {3, 3, 3, 1}, {6, 1, 1, 4}};
        int target = 2;
        System.out.println(solution.findGoodIndices(variables, target)); // 输出: [0, 2]
    }
}

解释

方法:

对于每个元素 [ai, bi, ci, mi],首先计算 a^b 的最后一位数字,这是通过 a^b % 10 实现的。接下来,计算这个结果的 ci 次幂,然后取模 mi,即 ((a^b % 10)^c) % mi。如果这个结果等于 target,那么这个索引 i 就是一个好下标。算法对每个元素进行此操作,并将所有好下标收集到结果列表中。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在双模幂运算中,为什么先计算 a^b % 10 而不是直接计算整个 a^b 的值?
在计算 a^b 时,如果 b 非常大,直接计算 a^b 可能会导致非常大的数值,这不仅增加了计算的复杂性,也可能导致计算机无法处理如此大的数字(即溢出)。通过首先计算 a^b % 10,我们实际上是在利用模运算的性质,即 (x^y) % z = ((x % z)^y) % z,来减少计算量并避免处理大数。这样我们只需关心最后一位数的幂运算,从而简化了问题和计算过程。
🦆
对于算法中的幂运算,有没有可能因为 b 或 c 的值很大而导致计算过程中的溢出问题?
是的,b 或 c 的值如果非常大,直接进行幂运算可能会导致数值溢出,特别是在不进行任何模运算的情况下。这就是为什么在题解中使用了模运算来处理 a^b 和 ((a^b % 10)^c) 的计算,通过模运算可以有效地降低结果的数值范围,避免溢出。此外,使用模运算也可以保持计算结果在一个可管理的数值范围内,从而防止运算过程中的资源耗尽。
🦆
题解中提到的算法对于每个元素都进行了幂运算和模运算,是否考虑过使用快速幂算法来优化这些计算?
快速幂算法是一种高效的计算 x^n 的方法,特别是当 n 很大时。它通过将幂运算分解成更小的部分,利用迭代的方法减少乘法的次数。在题解中,确实可以考虑使用快速幂来优化幂运算的过程,特别是当 b 和 c 的值很大时。通过快速幂,我们可以在对数时间复杂度内完成幂运算,这将显著提高算法的效率和处理大规模数据的能力。
🦆
题解中的算法在实现时未提及对于输入数据的特殊边界情况(如空数组或极大的数值),这会不会影响算法的鲁棒性或导致运行错误?
确实,没有处理特殊的边界情况可能会影响算法的鲁棒性。例如,如果输入数组为空,算法应该返回一个空的结果列表而不是产生错误。同样,对于极大的数值,算法应该能够正确处理或至少提供明确的错误消息。在实际应用中,应当在算法的开始阶段添加对输入数据的验证,确保输入数据在预期范围内,并且处理任何异常情况,以保证算法的稳定性和可靠性。

相关问题