📅  最后修改于: 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;
}
以上两种方法都可用于求解每个元素左侧的较小素数,只需将数组顺序反转即可。