嗨我有一个大小为N的数组。数组值总是只有1,2,3个整数值。现在我需要找到给定范围的数组索引之间的最小数字。因此对于例如array = 2 1 3 1 2 3 1 3 3 2. [2-4] = 1,[4-5] = 2,[7-8] = 3等范围的最低值。
以下是我的代码:
static void Main(String[] args) {
string[] width_temp = Console.ReadLine().Split(' ');
int[] width = Array.ConvertAll(width_temp,Int32.Parse); // Main Array
string[] tokens_i = Console.ReadLine().Split(' ');
int i = Convert.ToInt32(tokens_i[0]);
int j = Convert.ToInt32(tokens_i[1]);
int vehicle = width[i];
for (int beg = i+1; beg <= j; beg++) {
if (vehicle > width[beg]) {
vehicle = width[beg];
}
}
Console.WriteLine("{0}", vehicle);
}
上面的代码工作正常。但我担心的是效率问题。在上面我只是采用一组数组范围,但实际上会有n个范围,我必须返回每个范围的最低值。现在问题是如果有一个像[0-N]这样的范围,N是数组大小,那么我最终会比较所有项目的最低值。所以我想知道是否有办法优化代码的效率???
答案 0 :(得分:2)
我认为这是一个RMQ(范围最小查询),并且有几个实现可能适合您的方案。
这是一个很好的TopCoder Tutorial涵盖了很多,我推荐其中两个:
使用教程中的符号,将<P, T>
定义为<Preprocess Complexity, Query Complexity>
,有两个着名且常见的实现/数据结构可以处理RMQ:平方生根阵列&amp;的 Segment Tree 即可。
Segment Tree很有名但很难实现,它可以解决<O(n), O(lg n)>
中的RMQ,它比Square Rooting Array(<O(n), O(sqrt(n))>
)具有更好的复杂性
方根生成数组(<O(n), O(sqrt(n))>
)
请注意,这不是该技术的正式名称,也不是任何数据结构,事实上我不知道这项技术是否有任何官方命名,因为我学到了...但是我们这里去了
对于查询时间,它绝对不是解决RMQ的最佳方法,但它有一个优点:易于实现! (与细分树相比......)
以下是它如何运作的高级概念:
让 N 为数组的长度,我们将数组拆分为 sqrt(N)组,每组包含 sqrt(N)元件。
现在我们使用O(N)
时间查找每个组的最小值,将它们存储到另一个数组调用中M
所以使用上面的数组M[0] = min(A[0..2]), M[1] = min(A[3..5]), M[2] = min(A[6..8]), M[3] = min(A[9..9])
(TopCoder教程中的图像存储了最小元素的索引)
现在让我们看看如何查询:
对于任何范围[p..q]
,我们总是可以将此范围最多分为3个部分。
左边界的两个部分,其中一些部分留在不能形成整个组的元素上。
一部分是两者之间的元素,形成一些群体。
使用相同的示例,RMQ(2,7)
可以分为3部分:
A[2]
A[6], A[7]
A[3],A[4],A[5]
请注意,对于元素之间的元素,我们已经使用M
预处理了它们的最小值,因此我们不需要查看每个元素,我们可以查看并比较M
,而不是大多数O(sqrt(N))
他们(M
毕竟的长度
对于边界部分,因为根据定义它们不能形成整个组,意味着它们中最多有O(sqrt(N))
个(它是一个整个组的长度)
因此,结合两个边界部分,其中一部分位于元素之间,我们只需要比较O(3*sqrt(N)) = O(sqrt(N))
元素
您可以参考本教程获取更多详细信息(即使是某些伪代码)。
答案 1 :(得分:0)
答案 2 :(得分:0)
形成如下循环:
int[] inputArray = { 2, 1, 3, 1, 2, 3, 1, 3, 3, 2 };
int minIndex = 2;
int maxIndex = 5;
int minVal = 3;
for (int i = minIndex; i <= maxIndex; i++)
{
if (inputArray[i] <= minVal)
minVal = inputArray[i];
}
Console.WriteLine("Minimum value in the Given range is ={0}", minVal);
答案 3 :(得分:0)
这似乎是一个有趣的小问题。我的第一点是扫描固定阵列的速度非常快(每秒数百万),因此您需要大量数据来保证更复杂的解决方案。
显而易见的第一件事就是当你找到一个1时,从循环中断开,因为你已经找到了你的最低值。
如果你想要更先进的东西。
这就是我的意思。采取以下阵列。
int[] intialArray = new int[] { 3, 3, 3, 3, 2, 2, 2, 1 };
int[] searchArray = new int[] { 4, 4, 4, 4, 7, 7, 7, 7 };
所以我们的想法是在0-7之间找到最低点。
从initialArray[0]
开始,获得价值3
读取searchArray[0]
并获取值4. 4是数字较低的下一个索引。
阅读initialArray[4]
并获取值2.
等
所以基本上你需要付出一些努力去构建searcharray,但是如果完成它你会更快地扫描每个范围。