我现在一直在考虑这个家庭作业问题。给定一个大小为n的数组,设计一种能够找到最高和最低1.5n比较值的高和低值的算法。
我的第一次尝试是
int high=0
int low= Number.MaxValue //problem statement is unclear on what type of number to use
Number numList[0 . . n] //number array, assuming unsorted
for (i=0, i < n, i++) {
if (numList[i] > high)
high = numList[i]
else if (numList[i] < low)
low = numList[i]
}
我的问题是循环的每次迭代都有三种可能性之一:
因此,对于整个数组遍历,最多可以进行2n次比较,这与1.5n比较的问题最大要求相差甚远。
答案 0 :(得分:21)
从一对数字开始,找到本地最小值和最大值(n / 2比较)。接下来,从n / 2个局部最大值(n / 2个比较)中找到全局最大值,并从局部分钟(n / 2个比较)中找到类似的全局最小值。总比较:3 * n / 2!
For i in 0 to n/2: #n/2 comparisons
if x[2*i]>x[2*i+1]:
swap(x,2*i,2*i+1)
global_min = min( x[0], x[2], ...) # n/2 comparisons
global_max = max( x[1], x[3], ...) # n/2 comparisons
请注意,上述解决方案会更改数组。替代解决方案:
Initialize min and max
For i = 0 to n/2:
if x[2*i]<x[2*i+1]:
if x[2*i]< min:
min = x[2*i]
if x[2*i+1]> max:
max = x[2*i+1]
else:
if x[2*i+1]< min:
min = x[2*i+1]
if x[2*i]> max:
max = x[2*i]
答案 1 :(得分:4)
I know this has already been answered, but in case someone is looking for another way to think about this. This answer is similar to Lester's, but can handle odd values of n without breaking and will still make at most 1.5n comparisons. The secret is in the modulus. ;)
As a side effect of ensuring we place the last value in the proper sub array, the second element in the givenList will be compared and placed twice. However, since we are not changing the original array and we are only interested in the high and low of the set, this does not really make a difference.
Initialize lowArray and highArray
Initialize subArrayCounter to 0
For i = 0; i < n; i+=2
X = givenList[i];
Y = givenList[(i+1)%n];
If(x < y)
lowArray[subArrayCounter] = x;
highArray[subArrayCounter] = y;
subArrayCounter++;
else
lowArray[subArrayCounter] = y;
highArray[subArrayCounter] = x;
subArrayCounter++;
Initialize low to lowArray[0];
Initialize high to highArray[0];
For i = 1; i < lowArray.length; i++
If(lowArray[i] < low)
Low = lowArray[i];
For i = 1; i < highArray.length; i++
If(highArray[i] > high)
High = highArray[i]
答案 2 :(得分:2)
这与ElKamina的答案相同,但由于我已经开始编写伪代码,我以为我会完成并发布它。
我们的想法是比较对的值(n / 2比较),以获得一个高值数组和一个低值数组。对于每个数组,我们再次比较值对(2 * n / 2比较)以分别获得最高值和最低值。
n/2 + 2*n/2 = 1.5n comparisons
这是伪代码:
int[] highNumList;
int[] lowNumList;
for (i = 0, i < n, i+=2)
{
a = numList[i];
b = numList[i+1];
if (a > b)
{
highNumList.Add(a);
lowNumlist.Add(b);
}
else
{
highNumlist.Add(b);
lowNumList.Add(a);
}
}
int high = highNumList[0];
int low = lowNumList[0];
for (i = 0, i < n/2, i+=2)
{
if (highNumList[i] < highNumList[i+1])
high = highNumList[i+1]
if (lowNumList[i] > lowNumList[i+1])
low = lowNumList[i+1]
}
此代码不会导致n
不均匀或初始数组为空。
答案 3 :(得分:1)
这是我在面试中遇到的一个问题,我从面试官那里找到了一个小答案,即“你如何比较两个数字?” (它确实有帮助)。
以下是解释:
假设我有100个数字(您可以轻松地将其替换为n,但如果n是偶数,则该示例的效果更好)。我所做的就是把它分成50个2个数字的列表。对于每对夫妇,我进行一次比较并且我已经完成了(现在进行了50次比较)然后我只需要找到最小值(即49次比较)和最大值的最大值(这也是49次比较) )这样我们必须进行49 + 49 + 50 = 148比较。我们完成了!
备注:要找到最小值,我们按照以下步骤(伪代码):
n=myList.size();
min=myList[0];
for (int i(1);i<n-1;i++)
{
if (min>myList[i]) min=myList[i];
}
return min;
我们在(n-1)比较中找到它。最大的代码几乎相同。