Java 使用中值算法O(n)查找未排序数组(包含重复项)中第n个最大数时出错
如果一个数组包含1,7,7,3,6,并且如果用户询问第二大元素是什么,那么输出应该是7(而不是6),因为重复的值被视为不同的。Java 使用中值算法O(n)查找未排序数组(包含重复项)中第n个最大数时出错,java,Java,如果一个数组包含1,7,7,3,6,并且如果用户询问第二大元素是什么,那么输出应该是7(而不是6),因为重复的值被视为不同的。 这是我的代码。 我正在使用确定性搜索来找到合适的轴心。 其复杂度为O(n)。 我被代码生成的错误卡住了。 请帮帮我 import java.util.Random; import java.util.Scanner; public class deven { public static void main(String args[]){
这是我的代码。
我正在使用确定性搜索来找到合适的轴心。
其复杂度为O(n)。
我被代码生成的错误卡住了。
请帮帮我
import java.util.Random;
import java.util.Scanner;
public class deven {
public static void main(String args[]){
Scanner in=new Scanner(System.in);
int len=in.nextInt();
int n=in.nextInt();
int array[]=new int[len];
for (int i = 0; i < len; i++) {
array[i]=in.nextInt();
}
System.out.println(select(array,len,n));
}
static int below[];
static int above[];
static int pivot;
static int i;
static int j;
static int x;
static int y;
static int index;
static Random rand=new Random();
static int select(int array[],int len,int n){
if(len==1)
return array[0];
pivot=pivot(array, len);
below=new int[len];
above=new int[len];
//System.out.println("Block");
x=0;
y=0;
int temp=0;
for(i=0;i<len;i++){
if(array[i]>pivot){
below[x++]=array[i];
}
else if(array[i]<pivot){
above[y++]=array[i];
}
else {
if(temp!=0){
below[x++]=array[i];
}
temp=1;
}
}
i = x;
j = len - y;
if(n<i) return select(below,x,n);
else if(n>=j) return(select(above,y,n-j));
else return(pivot);
}
static int pivot(int array[],int len){
if(len==1){
return array[0];
}
int numOfGroups=len/5;
if(len%5!=0){
numOfGroups++;
}
int setOfMedians[]=new int[numOfGroups];
for (int i = 0 ; i < numOfGroups ; i++)
{
int[] subset;
if(array.length % 5 > 0)
{
if (i == numOfGroups - 1)
{
subset = new int[array.length % 5];
}
else
{
subset = new int[5];
}
}
else
{
subset = new int[5];
}
for (int j = 0; j < subset.length ; j++)
{
subset[j] = array[5*i+j];
}
setOfMedians[i] = median(subset);
}
int goodpivot=select(setOfMedians, numOfGroups,numOfGroups/2 );
return goodpivot;
}
static int median(int[] array)
{
if (array.length == 1)
{
return array[0];
}
int smallerCount = 0;
for (int i = 0 ; i < array.length ; i++)
{
for (int j = 0 ; j < array.length ; j++)
{
if (array[i] < array[j])
{
smallerCount++;
}
}
if (smallerCount == (array.length - 1)/2)
{
return array[i];
}
smallerCount = 0;
}
return -1;
}
}
问题是你的中值法。它不应该返回-1。在中值法的最后一行,而不是
return -1;
换成
return array[rand.nextInt(array.length)];
请注意,此修复只是试图修复您的错误。从中位数方法不返回中位数的意义上说,这不是一个好的解决方案。我认为应用程序应该重构。修复的思想实际上是在pivot方法中。好的支点是中位数。但是,如果无法有效地找到中间值,则枢轴可以是阵列中的随机选择
更新:
让我们修正中值法:
static int median(int[] array) {
if (array.length == 0) {
throw new IllegalArgumentException("array cannot be empty.");
}
int mid = array.length / 2;
for (int candidate : array) {
int lower = 0;
int higher = 0;
for (int value : array) {
if (value < candidate) {
lower++;
}
else if (value > candidate) {
higher++;
}
}
if (lower <= mid && higher <= mid) {
return candidate;
}
}
throw new IllegalStateException();
}
静态整数中值(int[]数组){
如果(array.length==0){
抛出新的IllegalArgumentException(“数组不能为空”);
}
int mid=array.length/2;
for(int候选:数组){
整数下限=0;
int更高=0;
for(int值:数组){
if(值<候选值){
低级++;
}
else if(值>候选值){
高级++;
}
}
如果(lower如果您在smallerCount之外还保留了一个EqualCount,那么您应该能够检测到您的候选值是否是中位数,同时它也是一个重复值
(解释)
当中位数方法意外失败时,您似乎故意将-1作为无效值返回。抛出某种异常更合适,但您真正希望的是它永远不会达到该点
当中位数重复时,您的算法将失败。例如,在集合{1,2,2,2,3}中,2是明显的中位数,但从来没有一个点正好有2个值“小于”任何正在验证的值
如果同时计算较小和相等的值,那么如果当前测试通过,或者较小的计数小于中点,且较小+相等的计数大于中点,则可以知道您的候选对象是中位数。这不是整个堆栈跟踪,对吗?耶..我刚刚引用了小部分:)我没有得到..你能重新解释吗。@cdev--我根据要求添加了一个解释。你是对的,但如何更正它。我怎样才能消除我在使用你的“返回数组[rand.nextInt(array.length)];”建议时得到的逻辑错误。@cdev我包括了一个中值方法的修改版本。
static int median(int[] array) {
if (array.length == 0) {
throw new IllegalArgumentException("array cannot be empty.");
}
int mid = array.length / 2;
for (int candidate : array) {
int lower = 0;
int higher = 0;
for (int value : array) {
if (value < candidate) {
lower++;
}
else if (value > candidate) {
higher++;
}
}
if (lower <= mid && higher <= mid) {
return candidate;
}
}
throw new IllegalStateException();
}