我写了一个反转计数的实现。这是在线课程中执行的任务。但我得到的输入是不正确的,根据我所拥有的程序具有正确的语法。我不知道我错了 下面的程序是我的实现
import java.io.*;
class CountInversions {
//Create an array of length 1 and keep expanding as data comes in
private int elements[];
private int checker = 0;
public CountInversions() {
elements = new int[1];
checker = 0;
}
private boolean isFull() {
return checker == elements.length;
}
public int[] getElements() {
return elements;
}
public void push(int value) {
if (isFull()) {
int newElements[] = new int[elements.length * 2];
System.arraycopy(elements, 0, newElements, 0, elements.length);
elements = newElements;
}
elements[checker++] = value;
}
public void readInputElements() throws IOException {
//Read input from file and until the very last input
try {
File f = new File("IntegerArray.txt");
FileReader fReader = new FileReader(f);
BufferedReader br = new BufferedReader(fReader);
String stringln;
while ((stringln = br.readLine()) != null) {
push(Integer.parseInt(stringln));
}
System.out.println(elements.length);
fReader.close();
} catch (Exception e) {//Catch exception if any
System.err.println("Error: " + e.getMessage());
} finally {
// in.close
}
}
//Perform the count inversion algorithm
public int countInversion(int array[],int length){
int x,y,z;
int mid = array.length/2 ;
int k;
if (length == 1){
return 0;
}else{
//count Leftinversion and count Rightinversion respectively
int left[] = new int[mid];
int right[] = new int[array.length - mid];
for(k = 0; k < left.length;k++){
left[k] = array[k];
}
for(k = 0 ;k < right.length;k++){
right[k] = array[mid + k];
}
x = countInversion(left, left.length);
y = countInversion(right, right.length);
int result[] = new int[array.length];
z = mergeAndCount(left,right,result);
//count splitInversion
return x + y + z;
}
}
private int mergeAndCount(int[] left, int[] right, int[] result) {
int count = 0;
int i = 0, j = 0, k = 0;
int m = left.length, n = right.length;
while(i < m && j < n){
if(left[i] < right[j]){
result[k++] = left[i++];
}else{
result[k++] = right[j++];
count += left.length - i;
}
}
if(i < m){
for (int p = i ;p < m ;p++){
result[k++] = left[p];
}
}
if(j < n){
for (int p = j ;p < n ;p++){
result[k++] = right[p];
}
}
return count;
}
}
class MainApp{
public static void main(String args[]){
int count = 0;
CountInversions cIn = new CountInversions();
try {
cIn.readInputElements();
count = cIn.countInversion(cIn.getElements(),cIn.getElements().length);
System.out.println("Number of Inversios: " + count);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
答案 0 :(得分:2)
如果数组长度为2的幂,则代码可以工作(实际上,我不确定是否这样,请参见下面的第二点)。
读取输入时,如果数组已满,则将数组大小加倍,但是从不将其大小调整为实际读取的项目数,这些项目存储在checker
中。所以你的数组长度是2的幂,如果从文件读取的int
的数量不是2的幂,你有一个太长的数组,其中一些尾随0
元素对应于已分配但未从文件填充的地点。由于您使用数组的长度调用countInversions
而不是读取项的数量,因此这些0
也会被排序,从而产生一些虚假的反转。
读取输入后,分配一个新数组
int[] copy = new int[checker];
for(int i = 0; i < checker; ++i) {
copy[i] = elements[i];
}
elements = copy;
复制元素,并丢弃容量错误的旧数组。
您的算法中的另一个问题是您永远不会更改原始数组,因为您为合并结果分配了一个新数组,
int result[] = new int[array.length];
z = mergeAndCount(left,right,result);
所以你要合并未排序的数组,这也可能会扭曲反转计数。由于您将输入数组的一半复制到新数组以进行递归调用,因此可以毫无问题地将合并结果放入传入的数组中,因此用
替换上面两行z = mergeAndCount(left,right,array);
获取一个实际对数组进行排序并计算反转的方法。
答案 1 :(得分:1)
这篇文章正在解决使用Java进行计数反转的问题(除了文件阅读,你已经做好了) - Counting inversions in an array