Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在一维数组/直方图中查找局部最小值/最大值_Java_Algorithm - Fatal编程技术网

Java 在一维数组/直方图中查找局部最小值/最大值

Java 在一维数组/直方图中查找局部最小值/最大值,java,algorithm,Java,Algorithm,我试图找到数组中所有局部极小值和极大值的指数 例如: int[] array = {5,4,3,3,3,3,3,2,2,2, 6,6,8,5,5,5,3,3,2,1, 1,4,4,7}; // | | | // Indices: 0,1,2,3,4,5,6,7,8,9, 10,1,2,3,4,5,6,7,8,9, 20,1,2,3 // Minima: 8, 20 // Maxima

我试图找到数组中所有局部极小值和极大值的指数

例如:

int[] array = {5,4,3,3,3,3,3,2,2,2,  6,6,8,5,5,5,3,3,2,1,  1,4,4,7};
//                             |         |                 |
// Indices:    0,1,2,3,4,5,6,7,8,9, 10,1,2,3,4,5,6,7,8,9, 20,1,2,3
// Minima: 8, 20
// Maxima: 12
我提出了一个算法,对此我有几个问题:

  • 有更好的吗?:)
  • 我用枚举的方法来实现这种二元论,即向上和向上都是“向上”。我觉得很乱。有什么建议吗
  • 你有更好的方法名吗?direction()(+返回值)某种程度上意味着stright不是dir。但同时它也是,因为它是欧洲货币联盟的一个组成部分。嗯
  • 它适用于给定的数组。你有没有看到一种情况,它没有
-

import java.util.ArrayList;
公共类MinMaxFinder{
私有int[]数组;
私有数组列表极小值;
私人ArrayList maxima;
私有枚举方向{
上,下,直上,直下,直;
公共方向(){
if(this==向上| | this==直线向上){
返回;
}else if(this==向下| | this==直线向下){
返回下来;
}否则{
直线返回;
}
}
公共布尔值isStraight(){
如果(this==直线向下| | this==直线向上| | this==直线){
返回true;
}否则{
返回false;
}
}
公共布尔值hasDifferentDirection(方向其他){
如果(this!=直线和其他!=直线和此.direction()!=其他.direction()){
返回true;
}
返回false;
}
}
公共MinMaxFinder(int[]数组){
this.array=数组;
}
公共无效更新(){
极小值=新数组列表();
maxima=新的ArrayList();
方向分段DIR=方向向下;
int indexOfDirectionChange=0;
int-prevVal=数组[0];
int arrayLength=array.length;

对于(inti=1;i考虑一组第一个差异
d[i]=a[i]-a[i-1]

如果
d[i]
为正,则
a
在上一步中增加,如果
d[i]
为负值,然后
a
减小。因此,
d
的符号从正变为负表示
a
的局部最大值正在增大,现在正在减小。类似地,从负变为正表示局部最小值。

类似的“应该”工作,概念上可能不太复杂。 扫描阵列一次,并注册mins和maxs

值得一提的事情:
1) if(direction<0){}else{}可能可以删除,但我没有时间考虑细节。
2) 关键思想是,根据第一个“方向”(无论我们首先看到的是最小值还是最大值),for循环顺序会发生变化。
3) 如果有多个项目,它将始终保留最后一个元素(最高索引)

if(a.长度<2){
返回;
}
List mins=new ArrayList();
List maxs=new ArrayList();
int i=1;
int prev=0;
int方向=0;

对于(intj=1,k=0;j我想我明白了。谢谢大家!你们的想法帮了我很大的忙

以下解决方案适合我:

    ArrayList<Integer> mins = new ArrayList<Integer>();
    ArrayList<Integer> maxs = new ArrayList<Integer>();

    int prevDiff = array[0] - array[1];
    int i=1;
    while(i<array.length-1){    
        int currDiff = 0;
        int zeroCount = 0;
        while(currDiff == 0 && i<array.length-1){
            zeroCount++;
            i++;
            currDiff = array[i-1] - array[i];
        }

        int signCurrDiff = Integer.signum(currDiff);
        int signPrevDiff = Integer.signum(prevDiff);
        if( signPrevDiff != signCurrDiff && signCurrDiff != 0){ //signSubDiff==0, the case when prev while ended bcoz of last elem
            int index = i-1-(zeroCount)/2;
            if(signPrevDiff == 1){
                mins.add( index );
            }else{
                maxs.add( index );
            }               
        }
        prevDiff = currDiff;
    }
ArrayList mins=new ArrayList();
ArrayList maxs=新的ArrayList();
int-prevDiff=数组[0]-数组[1];
int i=1;

虽然(iWhy)索引0(数字5)不是局部最大值?与索引23相同。第一个/最后一个数字永远不会是最大值/最小值吗?在重复值的情况下,您选择的索引中的哪一个?例如:a={5,6,6},“max”必须是2,或者它可以是1,2或3??同样,我同意@DaDaDom:7(索引23)应为maximumI think index=2(中间6)最接近“真实/模拟”最小值。这仅给出与其直接邻域相关的局部最小值/最大值。此外,还必须迭代两个数组。您的问题是局部最小值/最大值。如何定义局部最小值/最大值?注意,我为您草拟了一个想法。不必实际存储第一个差分数组,您只需计算它们当您遍历输入数组并跟踪符号的变化时。是的,我很感激您的建议!:)问题是这些值是离散的。1222221->索引3处的最大值。虽然两个相邻值都是2(在差异数组中,它将是0)。这就是为什么我对直线上升和直线下降进行区分。d[i]=a[i]-a[i-1]是Direction currentDir=currValprevVal?Direction.UP:Direction.diright);因此,问题是您想要一个相等值范围的中间索引?请在
d[i]处记录索引
更改符号,然后计算数字
n
,其中后续的
d
为零。您需要索引
i+n/2
。对。我也必须查看零右侧的符号。因为它可能类似于
{1,2,2,2,3,3,2,2,2}
所以有从1to2到2to3的变化,但两者都在上升。所以这两个序列不再有趣了。但是你让我走上了一条好的道路:)我用嵌套循环来尝试。谢谢!这很好。虽然第3点对我很重要。是的,我没有阅读我对你的问题的评论的后续内容。但是它是使用这种方法,计算“中值”指数相当容易。如果你对你的答案感到满意,那么你应该接受你的答案!
if(a.length < 2){
       return;
   }

   List<Integer> mins = new ArrayList<Integer>();
   List<Integer> maxs = new ArrayList<Integer>();
   int i=1;
   int prev = 0;

   int direction = 0;
   for(int j=1, k = 0;j<a.length && (direction = a[j]-a[k]) == 0;j++, k++);

   if(direction == 0){
       //Array contains only same value.
       return;
   }

   if(direction < 0){
       while(i<a.length){
           for(;i<a.length && a[prev] >= a[i];i++,prev++);
           mins.add(prev);
           for(;i<a.length && a[prev] <= a[i];i++,prev++);
           maxs.add(prev);
           i++;prev++;
       }    
   }
   else{
       while(i<a.length){
           for(;i<a.length && a[prev] <= a[i];i++,prev++);
           maxs.add(prev);
           for(;i<a.length && a[prev] >= a[i];i++,prev++);
           mins.add(prev);
           i++;prev++;
       }
   }

   //maxs and mins now contain what requested
    ArrayList<Integer> mins = new ArrayList<Integer>();
    ArrayList<Integer> maxs = new ArrayList<Integer>();

    int prevDiff = array[0] - array[1];
    int i=1;
    while(i<array.length-1){    
        int currDiff = 0;
        int zeroCount = 0;
        while(currDiff == 0 && i<array.length-1){
            zeroCount++;
            i++;
            currDiff = array[i-1] - array[i];
        }

        int signCurrDiff = Integer.signum(currDiff);
        int signPrevDiff = Integer.signum(prevDiff);
        if( signPrevDiff != signCurrDiff && signCurrDiff != 0){ //signSubDiff==0, the case when prev while ended bcoz of last elem
            int index = i-1-(zeroCount)/2;
            if(signPrevDiff == 1){
                mins.add( index );
            }else{
                maxs.add( index );
            }               
        }
        prevDiff = currDiff;
    }