我需要学习如何使用多线程在未排序数组中正确查找第k个值。我将数组划分为子数组并在每个子数组中找到第k个值。但有时,这些值与真实答案不匹配。因此,我需要对每个子数组进行排序,然后对这些子数组进行一般排序,或者这里是使用多线程在未排序数组中查找第k个值的另一种算法?我的代码:
import java.util.*;
import java.util.stream.Stream;
public class SearchingItemThread implements Runnable{
private int[] arr;
private int left;
private int right;
private int k;
private int median;
public SearchingItemThread(int[] arr, int left, int right, int k){
this.arr = arr;
this.left = left;
this.right = right;
this.k = k;
}
@Override
public void run() {
median = select(0, arr.length - 1, k);
}
private int select(int left, int right, int k) {
if (left == right) {
return arr[left];
}
int pivotIndex = partition(left, right);
if (k == pivotIndex) {
return arr[k];
} else if (k < pivotIndex) {
return select(left, pivotIndex - 1, k);
} else {
return select(pivotIndex + 1, right, k);
}
}
private int partition(int left, int right) {
int pivotIndex = getPivot(left, right);
int pivotValue = arr[pivotIndex];
swap(pivotIndex, right);
int storeIndex = left;
for (int i = left; i < right; i++) {
if (arr[i] < pivotValue) {
swap(i, storeIndex);
storeIndex++;
}
}
swap(storeIndex, right);
return storeIndex;
}
private int getPivot(int left, int right) {
return new Random().nextInt(right - left + 1) + left;
}
private void swap(int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public int getMedian() {
return median;
}
}
public int findResultByMultithreading(int numberOfThreads, List<Integer> list, int target){
int[][] subArrays = new int[numberOfThreads][];
int subarraySize = list.size() / numberOfThreads;
for (int i = 0; i < numberOfThreads; i++) {
int startIndex = i * subarraySize;
int endIndex = (i == numberOfThreads - 1) ? list.size() : (i + 1) * subarraySize;
subArrays[i] = Arrays.copyOfRange(list.stream().mapToInt(Integer::intValue).toArray(), startIndex, endIndex);
}
Thread[] searcher = new Thread[numberOfThreads];
SearchingItemThread[] runnables = new SearchingItemThread[numberOfThreads];
List<Integer> medians = new ArrayList<>();
for (int i = 0; i <= numberOfThreads - 1; i++) {
runnables[i] = new SearchingItemThread(subArrays[i], 0, subArrays[i].length - 1, target);
searcher[i] = new Thread(runnables[i]);
searcher[i].start();
}
for (int i = 0; i < numberOfThreads; i++) {
try {
searcher[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < numberOfThreads; i++) {
medians.add(runnables[i].getMedian());
}
System.out.println(medians);
}
例如,我有一个数组:[4,7,2,9,5,1,6,8,3]和k = 3。如果我把这个数组分成三组,我会得到[4,7,2],[9,5,1]和[6,8,3]。在每个子数组中,第三个元素是[7,9,8]。这些值与真实答案不匹配- 3
2条答案
按热度按时间1sbrub3j1#
您使用并行快速选择来查找每个子数组中的第k个最小元素。这并不一定是所有子数组中第k个最少的元素。但是这些快速选择为你做的不仅仅是找到每个子数组中第k个最少的元素。它们重新排列数组,以便每个子数组中所有第k个最少的元素都在一端。在这些 nk 个元素中的某个地方是总体的第 k 个最小的。
有几种方法可以继续。例如,
1.您可以对每个子数组的 k 个最小元素进行排序(并行),然后使用类似于 n 路合并的方法来找到总体最小值(此部分较少或不并行)。
这些基于堆的部件可能需要全部串行化。
y1aodyip2#
你想使用k个线程找到第k个最小的元素,每个线程都有一个数组的分区。
找到每个分区的最小值。最小值中的最大值是结果的初始值。现在不再需要该线程。其他线程继续搜索其分区中的第二小项,并将其与当前候选项进行比较。无论哪个线程的第二小项大于当前候选项,都可以停止其工作。如果有一些线程的第二-如果最小项小于当前候选项,则可以继续搜索。
重复这种操作方式,直到没有更多的线索继续搜索,并且仍然站立的候选人是对问题的回答。