我对第K个最小元素和第K个元素之间的确切区别感到困惑。
第K个元素=第k个元素是一个数组= array [k-1]
但是,第k个最小元素是什么?我有一个作业问题,我需要编写一种算法来找到2个排序数组中的第k个最小元素。我不是在这里要您做作业,您不需要给我任何算法或代码。我只想了解第k个最小元素的含义。第K个最小元素和第k个元素有什么区别。
我问这个的原因是: 我用Google搜索什么是第k个最小元素,该网站之一:
forward_iterator_tag
它与数组的第k个元素完全相同。答案是U B [k-1]。
另一个例子是:
template<class I>
concept ForwardIterator =
InputIterator<I> &&
DerivedFrom<ITER_CONCEPT(I), forward_iterator_tag> &&
Incrementable<I> &&
Sentinel<I, I>;
我正确吗?是否有第k个最小元素不在AUB [k-1]处的例外情况?如果是,请给我一个例子,并解释一下吗?
编辑:我刚刚看到有人说第k个最小元素是数组[k-1]升序。
我问老师一个问题:
当我们谈论第k个元素时,它是在a [k]还是a [k-1]
他的答案是:
仔细阅读问题说明。输出应该是S U T中2n个元素中第k个最小的元素。该输出不一定在任何一个列表的索引k处。为什么会这样呢?
我不明白。 输出不一定在任何一个列表的索引k上是什么意思?
答案 0 :(得分:1)
正如您已经指出的那样,这两个数组的并集将成为您要查找的内容。因此,这里是一个示例:
S = [0,4,5,7]
T = [1,2,8,9]
then A = S v T = [0,1,2,4,5,7,8,9]
现在,当您查看此数组时,您会发现第k个元素位于索引k-1
处。这是因为我们倾向于从 one 开始计数。所以我们说第一个元素,就是指索引为0
的元素。
接着,这也是您其他问题的答案。由于您有两个数组,因此第k个最小的数字将是A[k-1]
,但您的老师的意思是在两个数组中的任何一个中,因此S
和T
可能不会位于索引k-1
。在上面的示例中,第五个最小的数字是5
的索引4
上的A
,但它是S
或S[2]
中的第三个元素。
答案 1 :(得分:1)
输出不一定在任一列表的索引k上是什么意思?
这意味着您应该在不创建C
(也称为AUB
)的情况下解决问题。
您应该并行地迭代两个数组,直到找到第k个最小元素为止。
伪逻辑:
Ai = 0, Bi = 0
Loop K-1 times:
if A[Ai] < B[Bi] then Ai++ else Bi++
kth smallest = min(A[Ai], B[Bi])
示例
A = [10, 20, 40, 60], B =[15, 35, 50, 70, 100], K = 4
Ai = 0, Bi = 0: A[0] < B[0] so Ai++
Ai = 1, Bi = 0: A[1] > B[0] so Bi++
Ai = 1, Bi = 1: A[1] < B[1] so Ai++
Ai = 2, Bi = 1: min(A[2], B[1]) = 35
位于35
处的第4个最小值是 B[1]
。
如您所见,输出不在两个列表的索引3(= 4-1)上。
第K个最小元素和第K个元素?
并且因为您从不创建组合列表,而是直接在两个不同的列表上工作,所以没有Kth元素,因此标题中提出的问题毫无意义。
答案 2 :(得分:0)
两个数组的联合只是一个包含两个数组的所有元素的数组。
例如PROCEDURE p_buscar_salario_emp3
FUNCTION f_foo
以上2个数组的并集可能是A[1,20,40,70] and B[10,50,60,80]
现在,假设k的范围从1(含)开始,假设k = 3,则第k个元素为40,但第k个最小元素为20。
有效执行此操作的方法取决于您的处理方式。一种(不太高效)的方法可能只是使用k个嵌套迭代,然后从未排序的并集数组中找到第k个最小的元素。
另一种方法可能是在合并后对数组进行排序,另一种方法是简单地合并两个数组,以便对生成的联合进行排序(合并排序:合并过程)。在这种情况下,所得数组将具有与第k个元素相同的第k个最小元素。
答案 3 :(得分:0)
正如其他人所说,第K个最小的元素是arr[k]
,在 递增排序之后。
这也称为Selection algorithm,随机输入数组的最著名算法是Quick select,运行时间为O(n)
,与Quick Sort密切相关。
我碰巧最近写了一个实现,您可以看一下。
Java
QuickSelect.java
/**
* Find k-th smallest element from an array, via quick select.
*
* @author eric
* @date 3/24/19 3:49 PM
*/
public class QuickSelect {
/**
* Find k-th smallest element, of given array.
*
* @param arr input array, will be modified (sorted partially),
* @param k k-th, start from 0,
* @return index of k-th, in the array,
*/
public static int findKth(int[] arr, int k) {
if (k < 0 || k >= arr.length)
throw new IllegalArgumentException("array length = " + arr.length + ", thus k should < " + arr.length + ", but get: " + k);
return findKth(arr, k, 0, arr.length - 1);
}
/**
* Find k-th smallest element, of given sub array.
*
* @param arr input array, will be modified (sorted partially),
* @param k k-th, start from 0,
* @param start inclusive
* @param end inclusive
* @return index of k-th, in the array,
*/
public static int findKth(int[] arr, int k, int start, int end) {
if (start == end && start == k) return k; // base case,
int pvt = end; // index of pivot, initially taken from last element of sub array,
// check each element in sub array,
for (int i = start; i <= end; i++) {
if (i < pvt && arr[i] > arr[pvt]) { // on left of pivot, and it's larger,
if (pvt - i == 1) { // neighbor, just switch,
int tmp = arr[i];
arr[i] = arr[pvt];
arr[pvt] = tmp;
} else { // not neighbor,
// swap 3 positions,
int tmp = arr[i];
arr[i] = arr[pvt - 1];
arr[pvt - 1] = arr[pvt];
arr[pvt] = tmp;
pvt -= 1; // adjust pvt,
i--; // restart from i,
}
} else if (i > pvt && arr[i] < arr[pvt]) { // on right of pivot, and it's smaller,
if (i - pvt == 1) { // neighbor, just switch,
int tmp = arr[i];
arr[i] = arr[pvt];
arr[pvt] = tmp;
} else {
// swap 3 positions,
int tmp = arr[i];
arr[i] = arr[pvt + 1];
arr[pvt + 1] = arr[pvt];
arr[pvt] = tmp;
pvt += 1; // adjust pvt,
// continue from i+1;
}
}
}
int leftSize = pvt - start; // element count on left side of pivot, in sub array,
if (leftSize == k) { // pivot itself is k-th,
return pvt;
} else if (leftSize > k) {
return findKth(arr, k, start, pvt - 1); // find on left part,
} else {
return findKth(arr, k - leftSize - 1, pvt + 1, end); // find on right part,
}
}
}
QuickSelectTest.java
(测试用例,通过TestNG
)
import eric.algorithm.dynamic.ShufflePerfectly;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.Arrays;
/**
* QuickSelect test.
*
* @author eric
* @date 3/24/19 3:50 PM
*/
public class QuickSelectTest {
private int size = 20; // array size, should be even,
private int[] arr; // array with unique elements,
private int[] arrDup; // array with duplicated elements,
@BeforeMethod
private void setUp() {
// init - arr,
arr = new int[size];
for (int i = 0; i < size; i++) arr[i] = i;
ShufflePerfectly.shuffle(arr); // shuffle,
// System.out.printf("[initial] arr = %s\n", Arrays.toString(arr));
// init - arrDup,
arrDup = new int[size];
int halfIdx = size / 2;
for (int i = 0; i < halfIdx; i++) {
arrDup[i] = i;
arrDup[i + halfIdx] = i;
}
ShufflePerfectly.shuffle(arrDup); // shuffle,
// System.out.printf("[initial] arrDup = %s\n", Arrays.toString(arrDup));
}
@Test
public void test() {
System.out.printf("\n[initial]: arr = %s\n", Arrays.toString(arr));
for (int i = 0; i < arr.length; i++) {
// setUp(); // re-random array,
int idx = QuickSelect.findKth(arr, i);
Assert.assertEquals(idx, i); // check index,
Assert.assertEquals(arr[idx], i); // check value,
System.out.printf("[after %d-th]: arr = %s\n", i, Arrays.toString(arr));
}
}
@Test
public void test_dup() {
System.out.printf("\n[initial]: arrDup = %s\n", Arrays.toString(arrDup));
for (int i = 0; i < arr.length; i++) {
// setUp(); // re-random array,
int idx = QuickSelect.findKth(arrDup, i);
Assert.assertEquals(idx, i); // check index,
Assert.assertEquals(arrDup[idx], i / 2); // check value,
System.out.printf("[after %d-th]: arrDup = %s\n", i, Arrays.toString(arrDup));
}
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void test_invalid_outOfRange() {
QuickSelect.findKth(arr, arr.length);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void test_invalid_negative() {
QuickSelect.findKth(arr, -1);
}
}
提示:
由于您有2个已排序数组,因此不需要上述算法。
您可以简单地在一个循环中遍历2个数组,每个数组只有一个指针,然后在每个步骤中将值较小的指针相加1,直到总步数为k。