多么有趣的问题!
其他海报是正确的,它返回最小值的索引,但实际上比这更有趣。
如果您将数组视为循环的(即,当您越过结尾时,返回开头),该函数将返回最小词典子序列的起始索引。
如果只有一个元素是最小的,则返回该元素。如果多个元素是最小的,我们会比较每个最小元素的下一个元素。
例如,输入10
和{0, 1, 2, 1, 1, 1, 0, 0, 1, 0}
:
- 在索引 0、6、7 和 9 处有四个 0 的最小元素
- 这两个后面跟着一个 1(0 和 7 元素),两个后面跟着一个 0(6 和 9 元素)。请记住,数组是圆形的。
- 0 小于 1,所以我们只考虑 6 和 9 处的 0。
- 其中,从 6 开始的 3 个元素的序列是“001”,从 9 开始的序列也是“001”,所以它们仍然同样最小
- 查看 4 个元素的序列,我们从元素 6 开始有“0010”,从元素 9 开始有“0012”。因此,从 6 开始的序列更小,并返回 6。(我已经检查过是这种情况)。
重构和注释代码如下:
int findStartOfMinimumSubsequence(int length, char circular_array[])
{
#define AccessWithOffset(index) circular_array[(index + offset) % length]
int indicesStillConsidered[length], count_left = length, indicator[length], minIndex = 0;
for (int index = 0; index < length; index++)
{
indicesStillConsidered[index] = index;
indicator[index] = 1;
}
// Keep increasing the offset between pairs of minima, until we have eliminated all of
// them or only have one left.
for (int offset = 0; count_left >= 2; offset++)
{
// Find the index of the minimal value for the next term in the sequence,
// starting at each of the starting indicesStillConsidered
minIndex = indicesStillConsidered[0];
for (int i=0; i<count_left; i++)
minIndex = AccessWithOffset(indicesStillConsidered[i])<AccessWithOffset(minIndex) ?
indicesStillConsidered[i] :
minIndex;
// Ensure that indicator is 0 for indices that have a non-minimal next in sequence
// For minimal indicesStillConsidered[i], we make indicator 0 1+offset away from the index.
// This prevents a subsequence of the current sequence being considered, which is just an efficiency saving.
for (int i=0; i<count_left; i++){
offsetIndexToSet = AccessWithOffset(indicesStillConsidered[i])!=AccessWithOffset(minIndex) ?
indicesStillConsidered[i] :
(indicesStillConsidered[i]+offset+1)%length;
indicator[offsetIndexToSet] = 0;
}
// Copy the indices where indicator is true down to the start of the l array.
// Indicator being true means the index is a minimum and hasn't yet been eliminated.
for (int count_before=count_left, i=count_left=0; i<count_before; i++)
if (indicator[indicesStillConsidered[i]])
indicesStillConsidered[count_left++] = indicesStillConsidered[i];
}
return count_left == 1 ? indicesStillConsidered[0] : minIndex;
}
样品用途
很难说,真的。人为的例子:从一个循环的字母列表中,这将返回比任何其他相同长度的子序列更早出现在字典中的最短子序列的索引(假设所有字母都是小写的)。