我有一个名为tournamentTreeKSelection
的函数,它找到数组中第K个最大的元素。该函数有三个参数,数组,同一个数组和K的值。发送数组的两个副本的目的是在递归调用期间,我可以修改数组的一个副本并仍保留原始数组在电话会议期间发送。这是代码:
import java.util.ArrayList;
import java.util.Arrays;
public class TournamentTree {
public static int max(int a, int b) {
return a > b ? a : b;
}
public static int[] toArray(ArrayList<Integer> list) {
int[] arr = new int[list.size()];
for(int i = 0; i < arr.length; ++i)
arr[i] = list.get(i);
return arr;
}
public static ArrayList<Integer> toList(int[] arr) {
ArrayList<Integer> list = new ArrayList<>();
for(int i : arr)
list.add(i);
return list;
}
public static int tournamentKSelection(int[] data, int[] data_copy, int k) {
ArrayList<Integer> winners = new ArrayList<>();
for(int i = 0; i < data.length; i += 2) {
winners.add(max(data[i], data[i + 1]));
}
if(k > 1 && winners.size() == 1) {
for(int i = 0; i < data_copy.length; i++)
if(data_copy[i] == winners.get(0))
data_copy[i] = -1;
return tournamentKSelection(data_copy, data_copy, --k);
}
if(winners.size() % 2 == 1 && winners.size() != 1) winners.add(-1);
if(winners.size() == 1) return winners.get(0);
return tournamentKSelection(toArray(winners), data_copy, k);
}
}
现在我要测试一下:
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {9, 10, 8, 7, 6, 500, 4, 3, 2, 1};
System.out.println(TournamentTree.tournamentKSelection(arr,arr,1));
System.out.println(TournamentTree.tournamentKSelection(arr,arr,2));
System.out.println(TournamentTree.tournamentKSelection(arr,arr,3));
}
}
这会产生以下结果:
500 // ok this is the first largest number
10 // ok this is the second largest number
8 // this is the fourth largest number, not the third
现在让我单独调用System.out.println(TournamentTree.tournamentKSelection(arr,arr,3));
而不调用k = 1和k = 2
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {9, 10, 8, 7, 6, 500, 4, 3, 2, 1};
System.out.println(TournamentTree.tournamentKSelection(arr,arr,3));
}
}
现在这会产生正确的结果,即9.正在发生什么?单独地,结果是正确的但是当我先前调用相同的函数时,后续结果是错误的。
我现在能想到的唯一解释是我的TournamentTree类中的某些内容是静态的,不应该是。
有什么见解?
答案 0 :(得分:2)
我认为你应该以这种方式调用你的函数:
System.out.println(TournamentTree.tournamentKSelection(arr.clone(), arr.clone(), 1));
我还推荐有关数组的有趣线程并将它们传递给函数:
答案 1 :(得分:1)
在调用TournamentTree.tournamentKSelection(arr,arr,3)
中,您为两个args传递相同的数组,因此即使您没有通过第二个参数更改数组,您也会通过第一个参数更改它。 Java使用传递引用,而不是按值传递。要保留原文,您必须制作副本并传入其中,例如:
public static void main(String[] args) {
int[] arr = {9, 10, 8, 7, 6, 500, 4, 3, 2, 1};
int[] arr_copy = java.util.Arrays.copyOf(arr, arr.length);
System.out.println(TournamentTree.tournamentKSelection(arr,arr_copy,3));
}