《程序员面试金典》(第六版)习题:仅为记录一下以加强印象,不为商业用途,如有侵权请联系删除。以下源码和解释参考了书中源码以及解释。
次优解先将数组按升序排序,然后从
i
n
d
e
x
=
1
index=1
index=1开始,每次以加2的方式迭代交换
i
n
d
e
x
−
1
index-1
index−1和
i
n
d
e
x
index
index处的元素。
//次优解,谷位于index为1、3处(index从0开始算起)
void swap(vector<int> &myArray,int left,int right)
{
int temp = myArray[left];
myArray[left]= myArray[right];
myArray[right] = temp;
}
void sortValleyPeak(vector<int> &myArray)
{
sort(myArray.begin(), myArray.end());
for (int i=1;i<myArray.size();i+=2)
{
swap(myArray, i - 1, i);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/db47eed8ac1d3852f36345f9a55caa34.png)
最优解没有首先将数组排序而是直接从 i n d e x = 1 index=1 index=1开始,每次以加2的方式迭代,每次将其左右的值和其本身三个元素中值最大的元素和当前 i n d e x index index处的元素交换。因此这种情况下峰位于index为1、3等奇数索引处(index从0开始算起)。在下一次迭代过程中不会改变前一次迭代过程中已经构建的峰谷排序。在下一次迭代过程中如果要改变前一次迭代过程中已经构建的峰谷排序,则这一次迭代过程中左边的元素(即上一次迭代中的右边的元素)必须被交换,因为如果不出现交换的话就不会改变前一次迭代过程中已经构建的峰谷排序。因此这一次迭代中的三个元素中的最大值必须位于这一次迭代中的左边的元素(即上一次迭代中的右边的元素)。交换过后这一次迭代中的左边的元素小于这一次迭代中的中间的元素,也肯定小于上一次迭代中的中间元素。如果要在下一次迭代过程中如果要改变前一次迭代过程中已经构建的峰谷排序,交换过后这一次迭代中的左边的元素必须要大于大于上一次迭代中的中间的元素,这就互相矛盾了。所以在下一次迭代过程中不会改变前一次迭代过程中已经构建的峰谷排序。
//最优解,峰位于index为1、3处(index从0开始算起)
int max(int a,int b)
{
if (a > b)
return a;
else
return b;
}
void swap(vector<int> &myArray,int left,int right)
{
int temp = myArray[left];
myArray[left]= myArray[right];
myArray[right] = temp;
}
int maxIndex(vector<int>& myArray, int left, int middle, int right)
{
int len = myArray.size();
int leftValue = left >= 0 && left < len ? myArray[left] : numeric_limits<int>::min();
int middleValue = middle >= 0 && middle < len ? myArray[middle] : numeric_limits<int>::min();
int rightValue = right >= 0 && right < len ? myArray[right] : numeric_limits<int>::min();
int maxV = max(leftValue, max(middleValue, rightValue));
if (leftValue == maxV)
{
return left;
}
else if (middleValue == maxV)
{
return middle;
}
else
{
return right;
}
}
void sortValleyPeak(vector<int> &myArray)
{
for (int i=1;i<myArray.size();i+=2)
{
int biggestIndex = maxIndex(myArray, i - 1, i, i + 1);
if (i != biggestIndex)
{
swap(myArray, i, biggestIndex);
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/223f50be5105772f3bc6f40cec8df831.png)
最优解2与最优解基本相同,只不过它没有调用额外的函数来寻找临近的三个元素中最大的哪一个。最优解2中谷位于index为1、3处(index从0开始算起)。
//最优解2,谷位于index为1、3处(index从0开始算起)
void swap(vector<int>& myArray, int left, int right)
{
int temp = myArray[left];
myArray[left] = myArray[right];
myArray[right] = temp;
}
void sortValleyPeak(vector<int>& myArray)
{
for (int i = 1; i < myArray.size(); i += 2)
{
if (myArray[i - 1] < myArray[i])
{
swap(myArray, i - 1, i);
}
if (i + 1 < myArray.size() && myArray[i + 1] < myArray[i])
{
swap(myArray, i + 1, i);
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/db47eed8ac1d3852f36345f9a55caa34.png)