二维数组峰值检测java实现

本文介绍了一种寻找二维数组中峰值的有效算法。首先,通过遍历数组找出所有可能的一维峰值,然后对这些峰值进行排序,最后从中筛选出满足二维峰值条件的前五名,解决了在大规模数据集上快速定位峰值的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

up以前参加的集成电路设计大赛,题目是这样的:

一个单口RAM连续存储着 32*20=640个数的二维数组。单口RAM每个时钟周期只能读取一个数,要求在最短的时间内筛选出五个最大的峰值,并将峰值的坐标输出来。	

数组是随机的,当时我用的是Verilog写 的,思路如下:
处理返回坐标时,由于Verilog没有对象的概念,所有是将所有数据进行再加工,比如二维数组第13行21列的数是9,将他转化为91321。即将每个数向左平移四位,再将后四位由该数的坐标填充。
硬件语言并没有java那样灵活,使用9个寄存器来读取数组,每个寄存器存放一个数据再在这组寄存器中筛选出九个数,其中,这九个数有一个是二位数组中间的数,其余八个为它周围的数。如图:
在这里插入图片描述
将这九个数据高16位进行比较,最后,比较得出来的二维峰值,筛选出最大的五个二维峰值,顺带将它的位置输出。

现在学习了java,当然也可以用java来实现。
问题分析:
一个二维数组如下
在这里插入图片描述
二维峰值是指一个数,比它周围的八个数都要大。比如数组中的244就是一个二维峰值。
最先想到的是将数组遍历,再进行条件判断。
假设峰值为a[x][y],在满足边界条件x>=1,y>=1的那它一定满足
a[x][y]>a[x+1][y]
a[x][y]>a[x-1][y]
a[x][y]>a[x][y+1]
a[x][y]>a[x][y-1]
a[x][y]>a[x+1][y+1]
a[x][y]>a[x+1][y-1]
a[x][y]>a[x-1][y+1]
a[x][y]>a[x-1][y-1]
我们还要考虑x=0,y=0,x=31,y=15时的边界条件。
想到这里,我们就发现这种方式实在太过繁琐。我们需要更懒的方法。
object [][] array ;
array.length 就是行数row
array [0].length 就是列数col

通过观察,可以看到,二维峰值比周围的数大,作为一个二维峰值,他一定属于一维峰值。可以先找出所有的一维峰值,再从一维峰值中找出符合条件的二维峰值。
一维数组的峰值可以用for循环直接查找,简单暴力。

package com.test.demo1;


import java.util.ArrayList;

class Number{
	int x; 
	int y;
	int value;
}

class Test{
	public ArrayList Find(int [][] array) {
		
		Number number = new Number();
		
		//int a = array.length;//32 hang
		//int b = array[0].length;//16 lie
		ArrayList<Number> List = new ArrayList<Number>();//存放峰值	
		for (int i = 0; i < array.length; i++) {
			if (array[i][0]>array[i][1]) {//判断每一行的第一个数是否为峰值
				
				number.y = i;
				number.x = 0;
				number.value = array[i][0];
				
				List.add(number);
				
			}
			
			for (int j = 1; j < array[0].length-1; j++) {//判断每一行的峰值
				if ((array[i][j]>array[i][j+1])&&(array[i][j]>array[i][j-1])) {
					number.y = i;
					number.x = j;
					number.value = array[i][j];
					
					List.add(number);	
				}
			}
			if (array[i][array[0].length-2]<array[i][array[0].length-1]) {//判断每一行的最后数是否为峰值
				number.y = i;
				number.x = array[0].length-1;
				number.value = array[i][array[0].length-1];
				
				List.add(number);
			}	
		}
		for(Number number2 : List ){
 			System.out.println(number2.x+","+number2.y+","+number2.value);
 		}
		//return List;
		return List;
    }
	public int [][]initArray(int array[][],int x,int y) {
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[0].length; j++) {
				array[i][j]=(int)(Math.random()*100);
				}
			}
		
		return array;
		
	}
	public void display(int [][]array){
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[0].length; j++) {
				System.out.print(array[i][j]+",");
				
			}
			System.out.println();
		}
		System.out.println("print over");
	}
    public static void main(String[] args) {
    	 Test s = new Test();
    	 int a[][] = new int[32][16];
    	 s.initArray(a,32, 16);
    	 s.display(a);
    	
    	 s.Find(a);
    	 
    	 
    }
}

在这里插入图片描述
发生了一点小bug,检查后得知,我只创建了一个number对象,number对象存放入ArrayLis后,新查询到的数据覆盖前面的数据,再次存放入ArrayList中后,指向的都是同一个对象,所以打印出来的都是相同的数据。
修改如下(其实就是每找出一个值,就new一个Number对象):

package com.test.demo1;


import java.util.ArrayList;

class Number{
	int x; 
	int y;
	int value;
}

class Test{
	public ArrayList Find(int [][] array) {
		
		Number number;
		
		//int a = array.length;//32 hang
		//int b = array[0].length;//16 lie
		ArrayList<Number> List = new ArrayList<Number>();//存放峰值	
		for (int i = 0; i < array.length; i++) {
			if (array[i][0]>array[i][1]) {//判断每一行的第一个数是否为峰值
				number = new Number();
				number.y = i;
				number.x = 0;
				number.value = array[i][0];
				
				List.add(number);
				
			}
			
			for (int j = 1; j < array[0].length-1; j++) {//判断每一行的峰值
				if ((array[i][j]>array[i][j+1])&&(array[i][j]>array[i][j-1])) {
					number = new Number();
					number.y = i;
					number.x = j;
					number.value = array[i][j];
					
					List.add(number);	
				}
			}
			if (array[i][array[0].length-2]<array[i][array[0].length-1]) {//判断每一行的最后数是否为峰值
				number = new Number();
				number.y = i;
				number.x = array[0].length-1;
				number.value = array[i][array[0].length-1];
				
				List.add(number);
			}	
		}
		for(Number number2 : List ){
 			System.out.println(number2.x+","+number2.y+","+number2.value);
 		}
		//return List;
		return List;
    }
	public int [][]initArray(int array[][],int x,int y) {
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[0].length; j++) {
				array[i][j]=(int)(Math.random()*100);
				}
			}
		
		return array;
		
	}
	public void display(int [][]array){
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[0].length; j++) {
				System.out.print(array[i][j]+",");
				
			}
			System.out.println();
		}
		System.out.println("print over");
	}
    public static void main(String[] args) {
    	 Test s = new Test();
    	 int a[][] = new int[32][16];
    	 s.initArray(a,32, 16);
    	 s.display(a);
    	
    	 s.Find(a);
    	 
    	 
    }
}

在找到行的峰值后,再在一维峰值中找出那个二维峰值。
思路如下:
先将找出来的峰值进行排序,从大到小进行判断是否满足峰值条件,取到5个峰值后结束。

到这里,需要解决一个问题,如何将存储在ArrayList中的number对象的属性进行排序?
这里我使用了内部匿名类的方法对number对象进行排序。

public ArrayList sort(ArrayList<Number> list){
		System.out.println("print over1111111111111111");
		
		Collections.sort(list, new Comparator<Number>() {
            @Override
            public int compare(Number o1, Number o2) {
            	 //降序
                return o2.getValue().compareTo(o1.getValue());
            }
        });//匿名内部类,重写compare方法,
		
		for (Number number2 : list) {
			System.out.println( number2.value );
		}
		
		return list;
	}

在排序完成后,从ArrayList的第一个number对象开始判断,是否满足二维数组的峰值条件。

public ArrayList top(ArrayList<Number> list,int Array[][]){
		Number number3;
		int n=0;
		ArrayList<Number> list2 = new ArrayList();
		for (int i = 0; i < list.size(); i++) {
			new Number();
			number3.value = list.get(i).value;
			int x = number3.x = list.get(i).x;
			int y = number3.y = list.get(i).y;
			if ( (x==0)&&(number3.value > Array[1][y])){
				list2.add(number3);
				n++;
				if (n==4) {
					break;
				}
			}
			
			if( 	  (number3.value > Array[x][y-1])
					&&(number3.value > Array[x][y+1])
					&&(number3.value > Array[x-1][y-1])
					&&(number3.value > Array[x+1][y+1])
					&&(number3.value > Array[x-1][y+1])
					&&(number3.value > Array[x+1][y-1])
					&&(x>=1)
					
			){
				list2.add(number3);
				n++;
				if (n==4) {
					break;
				}
			}
			if ( (x==31)&&(number3.value > Array[31][y])) {
				n++;
				list2.add(number3);
			}
		}
		for (Number object : list2) {
			System.out.println(object.value+","+object.x+","+object.y);
		}
		
		return list2;
	}

综合在一起,搞定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值