Java 修改在中间带快速排序的中间带中找到的第k个元素
注意:这个问题是昨天深夜发布的,没有得到足够的回答。我添加了一些细节并重新发布 作为一项任务,我的任务是创建一个中值排序,它还可以确定数组的第n个最小元素,即排序数组的索引0是第一个最小元素。这种类型是递归的,这导致我在理解它时遇到问题,因为我没有广泛使用递归 通过拼凑教程和学习算法,我已经非常接近于成功地创建该方法;但是,我当前返回的值是错误的。当我希望QSA,1的输入返回索引0处的值时,它将返回索引1处包含的值:Java 修改在中间带快速排序的中间带中找到的第k个元素,java,algorithm,sorting,time-complexity,median-of-medians,Java,Algorithm,Sorting,Time Complexity,Median Of Medians,注意:这个问题是昨天深夜发布的,没有得到足够的回答。我添加了一些细节并重新发布 作为一项任务,我的任务是创建一个中值排序,它还可以确定数组的第n个最小元素,即排序数组的索引0是第一个最小元素。这种类型是递归的,这导致我在理解它时遇到问题,因为我没有广泛使用递归 通过拼凑教程和学习算法,我已经非常接近于成功地创建该方法;但是,我当前返回的值是错误的。当我希望QSA,1的输入返回索引0处的值时,它将返回索引1处包含的值: public static int QS(int[] A, int k){
public static int QS(int[] A, int k){
List<Integer> AList = new ArrayList<Integer>();
if(k < 1 || k >= A.length){
System.out.println("Code called because k = "+k);
return -1;
}
for (int i = 0; i < A.length; i++){
AList.add(A[i]);
}
if (AList.size() < 14) {
Collections.sort(AList);
return AList.get(k);
}
ArrayList<Integer> medians = new ArrayList<Integer>();
for (int i = 0; i < AList.size() - AList.size() % 7; i = i + 7){
medians.add(medianFind(AList.subList(i, i + 7)));
}
int a = medianFind(medians);
ArrayList<Integer> left = partitionFind(AList, a, true);
ArrayList<Integer> right = partitionFind(AList, a, false);
int[] leftArray = new int[left.size()];
int[] rightArray = new int[right.size()];
for(int i = 0; i < left.size(); i++){
leftArray[i] = left.get(i);
}
for(int i = 0; i < right.size(); i++){
rightArray[i] = right.get(i);
}
if(left.size() + 1 == k){
return a;
}
else if(left.size() > k){
return QS(leftArray, k);
}
else{
return QS(rightArray, k - left.size());
}
}
/////////
public static int medianFind(List<Integer> AList) {
Collections.sort(AList);
return AList.get(AList.size() / 2);
}
/////////
public static ArrayList<Integer> partitionFind(List<Integer> AList, int b, boolean lessThan) {
ArrayList<Integer> store = new ArrayList<Integer>();
for (int element : AList)
if (element < b && lessThan)
store.add(element);
else if (element >= b && !lessThan)
store.add(element);
return store;
}
语句由于算法的递归性质。我已经做了很长一段时间,但没有成功,如果有任何迹象表明我应该解决这个问题,我将不胜感激
//returns the k^th smallest element in the array A for 0<k<A.length
public static int QuickSelect(int[] A, int k){
List<Integer> AList = new ArrayList<Integer>();
if(A.length<k||k<1){
System.out.println("k out of range, got k: "+k +", but A.length: "+A.length);
return -1;
}
for (int i = 0; i < A.length; i++){
AList.add(A[i]);
}
***您忘记查找最后一个AList.size-AList.size%7个元素的中间值
不完全确定本文其余部分的逻辑,但我认为以下内容更有意义,请注意,我修改了PartitionFind
if(left.size() >= k){
return QuickSelect(leftArray, k);
}
else if(left.size()+med<k){
return QuickSelect(rightArray, k-(left.size()+med));
}
else{
return a;
}
}
/////////
public static int medianFind(List<Integer> AList) {
Collections.sort(AList);
return AList.get(AList.size() / 2);
}
/////////
注意:我修改了它,这样子问题就变得更小了。例如,你可以将b作为列表中最大的元素,右边的数组仍然包含整个列表
public static ArrayList<Integer> partitionFind(List<Integer> AList, int b, boolean lessThan) {
ArrayList<Integer> store = new ArrayList<Integer>();
for (int element : AList)
if (element < b && lessThan)
store.add(element);
else if (element > b && !lessThan)
store.add(element);
return store;
}
让我知道这是否有效这可能意味着两件不同的事情。这可能意味着在else返回语句中递归调用k-left.size==0。但是,它也可能仅仅意味着在最初调用时要求该方法查找数组的第0个最小元素,这是非法的,应该返回-1.ifk<1 | | k>=A.length{System.out.printlnCode,因为k=+k;返回-1;}您不想返回[A.length-1]吗在k=A.length的情况下,我不能完全确定我是否遵循。我确实希望最终返回一个[A.length-1],但是如果k==A.length,这意味着它看起来比数组的最后一个元素高1度。为什么这两个概念是联系在一起的呢?嗨,mm8511,非常感谢你给出了这样一个全面的、有充分文件证明的答案,我没有想到要对k==0做一个特例,也没有想到要用一个med变量来跟踪,这是一个非常不同的世界。我仍在清理代码并测试数据集,但到目前为止还没有出现任何问题,所以我将接受这一解决方案。再次感谢您的回复@嗯,没问题。很高兴这有帮助。
if (AList.size() < 14) {
Collections.sort(AList);
return AList.get(k-1);
}
ArrayList<Integer> medians = new ArrayList<Integer>();
for (int i = 0; i < AList.size() - AList.size() % 7; i = i + 7){
medians.add(medianFind(AList.subList(i, i + 7)));
}
int a = medianFind(medians);
ArrayList<Integer> left = partitionFind(AList, a, true);
ArrayList<Integer> right = partitionFind(AList, a, false);
int med=AList.size()-(left.size()+right.size())
int[] leftArray = new int[left.size()];
int[] rightArray = new int[right.size()];
for(int i = 0; i < left.size(); i++){
leftArray[i] = left.get(i);
}
for(int i = 0; i < right.size(); i++){
rightArray[i] = right.get(i);
}
if(left.size() >= k){
return QuickSelect(leftArray, k);
}
else if(left.size()+med<k){
return QuickSelect(rightArray, k-(left.size()+med));
}
else{
return a;
}
}
/////////
public static int medianFind(List<Integer> AList) {
Collections.sort(AList);
return AList.get(AList.size() / 2);
}
/////////
public static ArrayList<Integer> partitionFind(List<Integer> AList, int b, boolean lessThan) {
ArrayList<Integer> store = new ArrayList<Integer>();
for (int element : AList)
if (element < b && lessThan)
store.add(element);
else if (element > b && !lessThan)
store.add(element);
return store;
}