题目
给你一个 山脉数组 mountainArr,请你返回能够使得 mountainArr.get(index) 等于 target 最小 的下标 index 值。
 如果不存在这样的下标 index,就请返回 -1。
 何为山脉数组?如果数组 A 是一个山脉数组的话,那它满足如下条件:
 首先,A.length >= 3
 其次,在 0 < i < A.length - 1 条件下,存在 i 使得:
 A[0] < A[1] < … A[i-1] < A[i]
 A[i] > A[i+1] > … > A[A.length - 1]
 你将 不能直接访问该山脉数组,必须通过 MountainArray 接口来获取数据:
 MountainArray.get(k) - 会返回数组中索引为k 的元素(下标从 0 开始)
 MountainArray.length() - 会返回该数组的长度
分析
分三步。
| 寻找最后一个nums[mid-1]<nums[mid]的mid,当长度大于等于2是,mid-1是左子数组最后一个元素,mid是右子数组第一个元素,两个子数组都不为空,所以索引不会非法。 | 
| 升序中寻找目标数,不一定存在 | 
| 降序中寻找目标值,不一定存在 | 
代码
核心代码
class Solution {
 public:
 int findInMountainArray(int target, MountainArray& mountainArr) {
 int iTopIndex = TopIndex(mountainArr);
 //左边找
 {
 int left = 0, right = iTopIndex;//左开右闭
 while (right - left > 1)
 {
 const auto mid = left + (right - left) / 2;
 const int midValue = mountainArr.get(mid);
 if (midValue == target)
 {
 return mid;
 }
 else if (midValue < target)
 {
 left = mid;
 }
 else
 {
 right = mid;
 }
 }
 if( mountainArr.get(left) == target)
 {
 return left;
 }
 }
 {//右边找
 int left = iTopIndex, right = mountainArr.length();//左开右闭
 while (right - left > 1)
 {
 const auto mid = left + (right - left) / 2;
 std::cout << mid << " ";
 const int midValue = mountainArr.get(mid);
 if (midValue == target)
 {
 return mid;
 }
 else if (midValue < target)
 {
 right = mid;
 }
 else
 {
 left = mid;
 }
 }
 if( mountainArr.get(left) == target)
 {
 return left;
 }
 return -1;
 }
 return iTopIndex;
 }
 int TopIndex( MountainArray& mountainArr)
 {
 int left = 0, right = mountainArr.length();
 while (right - left > 1)
 {
 const auto mid = left + (right - left) / 2;
 if (mountainArr.get(mid - 1) < mountainArr.get(mid))
 {
 left = mid;
 }
 else
 {
 right = mid;
 }
 }
 return left;
 }
 };
小幅优化后的代码
左半边寻找,可以理解为:寻找最后一个<=
 右半边寻找,可以理解为:寻找最后一个>=
 class Solution {
 public:
 int findInMountainArray(int target, MountainArray& mountainArr) {
 int iTopIndex = TopIndex(mountainArr);
 //左边找
 {
 int left = 0, right = iTopIndex;//左开右闭
 while (right - left > 1)
 {
 const auto mid = left + (right - left) / 2;
 const int midValue = mountainArr.get(mid);
 if (midValue <= target)
 {
 left = mid;
 }
 else
 {
 right = mid;
 }
 }
 if (mountainArr.get(left) == target)
 {
 return left;
 }
 }
 {//右边找
 int left = iTopIndex, right = mountainArr.length();//左开右闭
 while (right - left > 1)
 {
 const auto mid = left + (right - left) / 2;
 std::cout << mid << " ";
 const int midValue = mountainArr.get(mid);
 if (midValue >= target)
 {
 left = mid;
 }
 else
 {
 right = mid;
 }
 }
 if (mountainArr.get(left) == target)
 {
 return left;
 }
 return -1;
 }
 return iTopIndex;
 }
 int TopIndex(MountainArray& mountainArr)
 {
 int left = 0, right = mountainArr.length();
 while (right - left > 1)
 {
 const auto mid = left + (right - left) / 2;
 if (mountainArr.get(mid - 1) < mountainArr.get(mid))
 {
 left = mid;
 }
 else
 {
 right = mid;
 }
 }
 return left;
 }
 };
2022年12月旧代码
class Solution {
 public:
 int findInMountainArray(int target, MountainArray &mountainArr) {
 int iMaxK = FindMax(mountainArr,0, mountainArr.length());
 int iLeft = FindLeft(mountainArr, 0, iMaxK + 1, target);
 if (-1 != iLeft)
 {
 return iLeft;
 }
 return FindRight(mountainArr, iMaxK, mountainArr.length(), target);
 }
 int FindMax( MountainArray &mountainArr, int iMin, int iMax)
 {
 if (iMax - iMin <= 1)
 {
 return iMin;
 }
 int iMid = (iMin + iMax) / 2;
 if (mountainArr.get(iMid - 1) < mountainArr.get(iMid))
 {
 return FindMax(mountainArr, iMid, iMax);
 }
 return FindMax(mountainArr, iMin, iMid);
 }
 int FindLeft(MountainArray &mountainArr, int iMin, int iMax, int target)
 {
 if (iMax - iMin <= 1)
 {
 if (mountainArr.get(iMin) == target)
 {
 return iMin;
 }
 return -1;
 }
 int iMid = (iMin + iMax) / 2;
 const int iMidValue = mountainArr.get(iMid);
 if (iMidValue == target)
 {
 return iMid;
 }
 if (iMidValue < target)
 {
 return FindLeft(mountainArr, iMid, iMax,target);
 }
 return FindLeft(mountainArr, iMin, iMid, target);
 }
 int FindRight(MountainArray &mountainArr, int iMin, int iMax, int target)
 {
 if (iMax - iMin <= 1)
 {
 if (mountainArr.get(iMin) == target)
 {
 return iMin;
 }
 return -1;
 }
 int iMid = (iMin + iMax) / 2;
 const int iMidValue = mountainArr.get(iMid);
 if (iMidValue == target)
 {
 return iMid;
 }
 if (iMidValue < target)
 {
 return FindLeft(mountainArr, iMin, iMid, target);
 }
 return FindLeft(mountainArr, iMid, iMax, target); 
 }
 };