📌  相关文章
📜  计算每个数组元素右侧的较小素数(1)

📅  最后修改于: 2023-12-03 15:28:03.903000             🧑  作者: Mango

计算每个数组元素右侧的较小素数

在编程过程中,经常需要求解数组中每个元素在该数组中右侧的第一个较小素数。本篇介绍两种常用的求解方法。

方法一:暴力枚举法

此法时间复杂度为O(n^2),不适用于大规模数据。

/**
 * 暴力枚举法
 * @param nums 目标数组
 * @return 每个元素右侧的第一个较小素数
 */
public int[] findNextSmaller(int[] nums) {
    int[] result = new int[nums.length];
    for (int i = 0; i < nums.length; i++) {
        int j = i + 1;
        while (j < nums.length && nums[j] >= nums[i]) {
            j++;
        }
        if (j == nums.length) {
            result[i] = -1; // 未找到较小素数
        } else {
            int k = j + 1;
            while (k < nums.length && !isPrime(nums[k])) {
                k++;
            }
            if (k == nums.length) {
                result[i] = -1;
            } else {
                result[i] = nums[k];
            }
        }
    }
    return result;
}

/**
 * 判断是否为素数
 * @param num 待判断的数
 * @return true表示为素数,false表示非素数
 */
private boolean isPrime(int num) {
    if (num <= 1) {
        return false;
    }
    for (int i = 2; i <= Math.sqrt(num); i++) {
        if (num % i == 0) {
            return false;
        }
    }
    return true;
}
方法二:单调栈法

此法时间复杂度为O(n),适用于大规模数据。

单调栈法的基本思路是维护一个单调不升的栈,在处理一个新的元素时,从栈顶开始弹出比该元素大的元素,并记录各弹出元素右侧第一个较小素数即为该新元素。若栈为空,则说明不存在右侧较小素数。然后将该新元素入栈。

/**
 * 单调栈法
 * @param nums 目标数组
 * @return 每个元素右侧的第一个较小素数
 */
public int[] findNextSmaller(int[] nums) {
    int[] result = new int[nums.length];
    Stack<Integer> stack = new Stack<>();
    for (int i = nums.length - 1; i >= 0; i--) {
        while (!stack.empty() && stack.peek() >= nums[i]) {
            stack.pop();
        }
        if (stack.empty()) {
            result[i] = -1;
        } else {
            int k = stack.peek() + 1;
            while (k < nums.length && !isPrime(nums[k])) {
                k++;
            }
            if (k == nums.length) {
                result[i] = -1;
            } else {
                result[i] = nums[k];
            }
        }
        stack.push(nums[i]);
    }
    return result;
}

/**
 * 判断是否为素数
 * @param num 待判断的数
 * @return true表示为素数,false表示非素数
 */
private boolean isPrime(int num) {
    if (num <= 1) {
        return false;
    }
    for (int i = 2; i <= Math.sqrt(num); i++) {
        if (num % i == 0) {
            return false;
        }
    }
    return true;
}

以上两种方法都可用于求解每个元素左侧的较小素数,只需将数组顺序反转即可。