JAVA编程中,如何求2维数组中最大的K个值,并且记录K个值的位置?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA编程中,如何求2维数组中最大的K个值,并且记录K个值的位置?相关的知识,希望对你有一定的参考价值。

现在有二维数组,若干行,七千多列。
想要求出其中最大的k个值并且记录每个值对应的位置,k是程序中输入的(可变),求高手指教,不胜感激!
时间很紧张,最好一并附代码。 非常感谢。

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
* 角斗场,这是一个是骡子是马牵出来溜溜的,比罗(子)马那旮那个还要圆一点,还要血腥数十倍,疯狂上百倍的角斗场。所有的秘密都集中在那本古老而神秘的书--力量金卷之上...
*
* @author ???
*
*/
public class Colosseo
gladiator[] arena;//角斗场中央的大擂台,登上这个擂台就没有退路,因为这里的游戏规则是二进制的: one or zero, live or die.
int area;//擂台有多大就意味着生死之夜有多少人能够survive,不过谁都知道,能活下来的永远只是少数。
public double[][] powerScroll;//神秘的力量金卷--神力与能量的来源

Colosseo(int area, gladiator starter, String powerScrollKey)//开启力量金卷的钥匙--powerScrollKey
this.area = area;
arena = new gladiator[this.area];
for(int i = 0; i<arena.length;i++)
arena[i]=starter;

File Input = null;
//打开力量金卷
try
//
Input = new File(powerScrollKey);
catch(NullPointerException e)
System.out.println("WARNING:偷偷配的钥匙是打不开的!!!");
e.printStackTrace();


try
//
List<String> listReadResult = new ArrayList<String>();
String sTmp[][];//

FileReader fr = new FileReader(Input);
BufferedReader br = new BufferedReader(fr);
String strReadLine = "";
while ((strReadLine = br.readLine()) != null)
listReadResult.add(strReadLine);

//
int row =listReadResult.size();
powerScroll= new double[row][];
sTmp = new String[row][];
for(int i=0; i < row; i++)
sTmp[i] = ((String)listReadResult.get(i)).split(" ");
powerScroll[i]= new double[sTmp[i].length ];
for(int j=0; j<powerScroll[i].length;j++)
powerScroll[i][j] = Double.parseDouble(sTmp[i][j]);


br.close();
fr.close();
catch (FileNotFoundException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();


/*
* 挑战成功
*/
void triumph(int order, gladiator winner)//order是winner要在擂台上占据的位置
for(int i=arena.length-2;i>=order;i--)//擂上最后一位下擂(凡上擂且最终不能守擂成功的角斗士都要被处死),在order位置以及后面的角斗士循序向后移一位,为winner让出位置
arena[i+1]=arena[i];

arena[order] = winner;

/*
* 挑战者攻擂
*/
void complete(gladiator challenger)
for(int i = 0; i<arena.length;i++)
//挑战者从最强者开始依次发起挑战
if(powerScroll[challenger.row][challenger.col]>powerScroll[arena[i].row][arena[i].col])//刀光剑影的角逐和我存你亡的厮杀...
this.triumph(i, challenger);
break;



/*
* 颁奖典礼
*/
void awardCeremony()
System.out.println("——————————生存的权利永远只属于那些真正的勇者——————————");
System.out.println("Ladies and gentlemen,let's give the warmest plause to the champion of tonight: ");
System.out.println(arena[0].row+" "+arena[0].col+ ": "+this.powerScroll[arena[0].row][arena[0].col]);
System.out.println("the runner-up is:");
System.out.println(arena[1].row+" "+arena[1].col+ ": "+this.powerScroll[arena[1].row][arena[1].col]);
System.out.println("and the third place :");
System.out.println(arena[2].row+" "+arena[2].col+ ": "+this.powerScroll[arena[2].row][arena[2].col]);
System.out.println("and the other warriors who deserve to continue to live:");
for(int i = 3; i<arena.length;i++)
System.out.println(arena[i].row+" "+arena[i].col+ ": "+this.powerScroll[arena[i].row][arena[i].col]);

System.out.println("————————————————————————这个传说还在继续上演———————————————————————————");

/**
* @param args
*/
public static void main(String[] args)
// TODO Auto-generated method stub
gladiator starter = new gladiator(0,0);
Colosseo glory = new Colosseo(5, starter, "E:\\Data\\1.txt");
for(int i=0; i<glory.powerScroll.length;i++)
for(int j=0;j<glory.powerScroll[i].length;j++)
glory.complete(new gladiator(i,j));


glory.awardCeremony();




/**
* 角斗士
* @author ghn
*
*/
class gladiator
int row;//角斗士在力量金卷中的经目

int col;//角斗士在力量金卷中的纬目

gladiator(int row, int col)
this.row = row;
this.col = col;

参考技术A 我的想法是:将二维数组前k个值放在一个集合里并且按小到大排好序
然后从数组的第k+1个值n开始遍历,将n和集合里最小的值比较,如果n比集合最小的值大,那么再从这个集合里找到比n大的数,并插在那个位置,然后将集合最小的值删除,如果找不到比n大的数,那就插在最后面

求数组中 n 个元素的最大和,使得相邻的元素不超过 k 个

【中文标题】求数组中 n 个元素的最大和,使得相邻的元素不超过 k 个【英文标题】:find maximum sum of n elements in an array such that not more than k elements are adjacent 【发布时间】:2013-02-07 06:51:15 【问题描述】:

几乎和这个一样: find maximum sum of elements in an array such that not more than k elements are adjacent

除了我们可以选择的 n 个元素的限制。如何修改 DP 算法使其适用于此?

【问题讨论】:

【参考方案1】:

增加DP功能的新维度: f[i, j, l] - 前 i 个元素的最大总和,如果在总和中使用 j 个总元素和 最后 l 个元素

【讨论】:

您好,我在计算递推公式时遇到了麻烦,您能给出递推公式吗?谢谢 例如,P(v,i) = P(v-1,i-1) + C(v) if i &gt; 0 P(v,0) = max(P(v-1,i) for i = 0..min(k, v)) P(0,0) = 0 是我链接到的另一篇文章中的递归公式。你能提供 f[i, j, l] 函数的公式吗?【参考方案2】:

好吧,让我把它说得更清楚。

问题:求一个数组中n个元素的最大和,使得相邻的元素不超过K个

let int f[i][j][k] 表示前i个元素的最大总和,使用j个元素,最后k个元素被使用。 let bool g[i][j][k] 表示是否有可能得到某种组合。例如。 g[1][1][2] 是假的。这很重要,因为没有限制,f 可能会生成不可能答案。

最初,memset f 和 g 都为零,并将 g[0][0][0] 设置为 true。我们可以使用前向递归来解决这个DP问题。显然,每次遇到一个数字,你都有两个选择:选择它,或者放弃它。他们给出了递推公式:

f[i][j][k] can infer f[i+1][j+1][k+1], or
f[i][j][k] can infer f[i+1][j][0]

所以,伪代码如下:

memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
g[0][0][0]=true;
for (int i=0;i<array.size();i++)
    for (int j=0;j<=n;j++)
        for (int k=0;k<=K;k++) if (g[i][j][k]) 
            f[i+1][j][0]=max(f[i+1][j][0],f[i][j][k]);
            f[i+1][j+1][k+1]=max(f[i+1][j+1][k+1],f[i][j][k]+array[i]);
            g[i+1][j][0]=true;
            g[i+1][j+1][k+1]=true;
        

最终的结果是:

ans=0;
for (i=0;i<=K;i++)
    ans=max(ans,f[array.size()][n][i]);
return ans;

上面给出了恰好 j 个元素。如果你想得到最多j个元素,你可以这样改:

ans=0;
for (i=0;i<=n;i++)
    for (j=0;j<=K;j++)
        ans=max(ans,f[array.size()][i][j]);
return ans;

【讨论】:

@WilliamRookwood 首先,我认为我在原始代码中犯了一个小错误。我很快就会编辑我的帖子。 @WilliamRookwood 我回答你的问题了吗?您需要更多帮助吗?

以上是关于JAVA编程中,如何求2维数组中最大的K个值,并且记录K个值的位置?的主要内容,如果未能解决你的问题,请参考以下文章

求数组最大的前两个数,要求比较次数尽可能少

最左或最右取k个值,求最大值,同拿硬币

求数组中第K个最大的值

JAVA编程求数组最大值和最小值

JAVA单维数组与多维数组编程

UVA - 11997 思维