Algorithm 如何在O(n*logk)时间内对平均长度为K的n个排序列表进行排序?
如何在O(n*logk)时间内对平均长度为K的n个排序列表进行排序?您可以调整合并排序来完成此工作。合并排序利用了将已排序的列表合并到新的排序列表的便利性 您可以调整合并排序来执行此任务。合并排序利用了将已排序的列表合并到新的排序列表的便利性 正如在对您的问题的评论中提到的,O(nlog(k))是不可能的,但是这里有两个算法可以有效地完成您的任务;这里有一个: 取每个列表的第一个元素 并创建一个堆(大小为k)。弹出 最小元素。从中查找数组 元素来了(假设它来了) 从清单一开始)。下一个 元素,并将其推入 堆对于中的每个元素 合并列表,我们花费了日志(k)时间。所以 时间复杂度为O(N*logk),其中 N是表中元素的总数 所有的K名单 -作者:Algorithm 如何在O(n*logk)时间内对平均长度为K的n个排序列表进行排序?,algorithm,Algorithm,如何在O(n*logk)时间内对平均长度为K的n个排序列表进行排序?您可以调整合并排序来完成此工作。合并排序利用了将已排序的列表合并到新的排序列表的便利性 您可以调整合并排序来执行此任务。合并排序利用了将已排序的列表合并到新的排序列表的便利性 正如在对您的问题的评论中提到的,O(nlog(k))是不可能的,但是这里有两个算法可以有效地完成您的任务;这里有一个: 取每个列表的第一个元素 并创建一个堆(大小为k)。弹出 最小元素。从中查找数组 元素来了(假设它来了) 从清单一开始)。下一个 元素,并
正如在对您的问题的评论中所提到的,O(nlog(k))是不可能的,但是这里有几个算法可以有效地完成您的任务;这里有一个: 取每个列表的第一个元素 并创建一个堆(大小为k)。弹出 最小元素。从中查找数组 元素来了(假设它来了) 从清单一开始)。下一个 元素,并将其推入 堆对于中的每个元素 合并列表,我们花费了日志(k)时间。所以 时间复杂度为O(N*logk),其中 N是表中元素的总数 所有的K名单 -作者:
合并排序是关键。假设N是要合并的元素总数,K是包含它们的容器数:
- 将所有已排序的序列追加到单个向量中,但要记住追加它们的位置。更好的方法是,如果您按照第一个元素的值对它们进行排序,将加快下一篇文章的速度
- 然后,您可以在适当的位置合并已排序序列对(如果您使用C++,则std::inplace\u merge)。每个合并都是Na+Nb,所以每个步骤都是N。您必须执行logK步骤
因此,NlogK 合并排序是关键。假设N是要合并的元素总数,K是包含它们的容器数:
- 将所有已排序的序列追加到单个向量中,但要记住追加它们的位置。更好的方法是,如果您按照第一个元素的值对它们进行排序,将加快下一篇文章的速度
- 然后,您可以在适当的位置合并已排序序列对(如果您使用C++,则std::inplace\u merge)。每个合并都是Na+Nb,所以每个步骤都是N。您必须执行logK步骤
因此,NlogK 我相信实现O(N*log(K))是可能的,但不是在最坏的情况下 考虑对这些列表进行排序:
{0,1,2,3,4,5,6,7,8,9,10},
{10,11,12,13,14,15,16,17,18,19,20},
{20,21,22,23,24,25,26,27,28,29,30}
我的人脑可以轻松地对这些列表进行排序,而无需读取每个值,因此应该有一种算法可以做到这一点。我们需要合并,同时使用修改的二进制搜索来查找值的范围
在最坏的情况下,得到O(N*K),因为每个值都必须进行比较。例如:
{0,2,4,6,8},
{1,3,5,7,9}
这是我在Go中的解决方案,我只会在知道排序列表通常具有相对于K较小的重叠区域时使用:
// variation of binary search that finds largest
// value up to and including max
func findNext(a []int, imin int, vmax int) int {
imax := len(a) - 1
best := -1
for imin <= imax {
imid := imin + ((imax - imin) / 2)
if a[imid] == vmax {
return imid
} else if a[imid] < vmax {
best = imid
imin = imid + 1
} else {
imax = imid - 1
}
}
return best
}
func sortNSortedLists(in [][]int) []int {
var out []int
cursors := make([]int, len(in))
for {
// Find the array indices that have the smallest
// and next to smallest value (may be same) at
// their current cursor.
minIdx1 := -1
minIdx2 := -1
minVal1 := math.MaxInt32
minVal2 := math.MaxInt32
for i, cursor := range cursors {
if cursor >= len(in[i]) {
continue
}
if in[i][cursor] < minVal1 {
minIdx2 = minIdx1
minVal2 = minVal1
minIdx1 = i
minVal1 = in[i][cursor]
} else if in[i][cursor] < minVal2 {
minIdx2 = i
minVal2 = in[i][cursor]
}
}
if minIdx1 == -1 {
// no values
break
}
if minIdx2 == -1 {
// only one array has values, so append the
// remainder of it to output
out = append(out, in[minIdx1][cursors[minIdx1]:]...)
break
}
// If inVal1 is smaller than inVal2,
// append to output all values from minVal1 to minVal2 found in
// the minIdx1 array, and update the cursor for the minIdx1 array.
if minVal1 < minVal2 {
firstCursor := cursors[minIdx1]
lastCursor := findNext(in[minIdx1], firstCursor, minVal2)
if lastCursor != -1 {
out = append(out, in[minIdx1][firstCursor:lastCursor+1]...)
cursors[minIdx1] = lastCursor+1
continue
}
}
// Append the single value to output
out = append(out, minVal1)
cursors[minIdx1]++
}
return out
}
//查找最大值的二进制搜索的变体
//最大值(含最大值)
func findNext(a[]int,imin int,vmax int)int{
imax:=len(a)-1
最佳:=-1
对于imin=len(in[i]){
持续
}
如果在[i][cursor]
我相信实现O(N*log(K))是可能的,但不是在最坏的情况下
考虑对这些列表进行排序:
{0,1,2,3,4,5,6,7,8,9,10},
{10,11,12,13,14,15,16,17,18,19,20},
{20,21,22,23,24,25,26,27,28,29,30}
我的人脑可以轻松地对这些列表进行排序,而无需读取每个值,因此应该有一种算法可以做到这一点。我们需要合并,同时使用修改的二进制搜索来查找值的范围
在最坏的情况下,得到O(N*K),因为每个值都必须进行比较。例如:
{0,2,4,6,8},
{1,3,5,7,9}
这是我在Go中的解决方案,我只会在知道排序列表通常具有相对于K较小的重叠区域时使用:
// variation of binary search that finds largest
// value up to and including max
func findNext(a []int, imin int, vmax int) int {
imax := len(a) - 1
best := -1
for imin <= imax {
imid := imin + ((imax - imin) / 2)
if a[imid] == vmax {
return imid
} else if a[imid] < vmax {
best = imid
imin = imid + 1
} else {
imax = imid - 1
}
}
return best
}
func sortNSortedLists(in [][]int) []int {
var out []int
cursors := make([]int, len(in))
for {
// Find the array indices that have the smallest
// and next to smallest value (may be same) at
// their current cursor.
minIdx1 := -1
minIdx2 := -1
minVal1 := math.MaxInt32
minVal2 := math.MaxInt32
for i, cursor := range cursors {
if cursor >= len(in[i]) {
continue
}
if in[i][cursor] < minVal1 {
minIdx2 = minIdx1
minVal2 = minVal1
minIdx1 = i
minVal1 = in[i][cursor]
} else if in[i][cursor] < minVal2 {
minIdx2 = i
minVal2 = in[i][cursor]
}
}
if minIdx1 == -1 {
// no values
break
}
if minIdx2 == -1 {
// only one array has values, so append the
// remainder of it to output
out = append(out, in[minIdx1][cursors[minIdx1]:]...)
break
}
// If inVal1 is smaller than inVal2,
// append to output all values from minVal1 to minVal2 found in
// the minIdx1 array, and update the cursor for the minIdx1 array.
if minVal1 < minVal2 {
firstCursor := cursors[minIdx1]
lastCursor := findNext(in[minIdx1], firstCursor, minVal2)
if lastCursor != -1 {
out = append(out, in[minIdx1][firstCursor:lastCursor+1]...)
cursors[minIdx1] = lastCursor+1
continue
}
}
// Append the single value to output
out = append(out, minVal1)
cursors[minIdx1]++
}
return out
}
//查找最大值的二进制搜索的变体
//最大值(含最大值)
func findNext(a[]int,imin int,vmax int)int{
imax:=len(a)-1
最佳:=-1
对于imin=len(in[i]){
持续
}
如果在[i][cursor]