训练题:逆序对
题目:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
方法一:归并排序
- 时间复杂度:O(nlogn)
- 空间复杂度:O(n)
归并排序刚好是将左半有序部分和右半有序部分进行合并。在这个时候我们可以统计逆序对。
int reversePairs(vector<int>& nums) {if(nums.size() < 2) return 0;const auto size = nums.size();vector<int> tmpNums(size);return mergeSort(nums, tmpNums, 0, size - 1);}int mergeSort(vector<int>& nums, vector<int>& tmpNums, int start, int end){if(end <= start) return 0;int mid = start + ((end - start) >> 1);int left = start;int right = mid + 1;int k = left;int count = mergeSort(nums, tmpNums, start, mid) + mergeSort(nums, tmpNums, mid + 1, end);for(; left <= mid && right <= end;){if(nums[left] <= nums[right]) tmpNums[k++] = nums[left++];else{ // left > righttmpNums[k++] = nums[right++];// 此时比num[right]大的数是num[left] ... num[mid]这几个数。count += (mid - left + 1);}}for(; left <= mid; ++left, ++k) tmpNums[k] = nums[left];for(; right <= end; ++right, ++k) tmpNums[k] = nums[right];copy( tmpNums.begin() + start, tmpNums.begin() + end + 1, nums.begin() + start );return count;}
方法二:树状数组(待完成)
训练题:机器人运动范围
题目:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/
方法一:深度优先遍历(递归)
- 时间复杂度:O(mn)
- 空间复杂度:O(mn)

int count;int tmp;int movingCount(int m, int n, int k) {if(m < 1 || n < 1 || m > 100 || n > 100 || k < 0 || k > 20) return -1;// dataMap用于记录遍历过的地方。vector<vector<int>> dataMap(m, vector<int>(n, 0));traverse(dataMap, m, n, k, 0, 0);return count;}void traverse(int dataMap[][100], const int& m, const int& n, const int& k, int x, int y){if( x == m || y == n || dataMap[x][y]) return;dataMap[x][y] = 1;tmp = x % 10 + x / 10 + y % 10 + y / 10;if(tmp > k) return;++count;// 优化:从上图我们看出规律:从左上往右下遍历,必然能全部遍历到。// 往左(x-1)和往上(y-1)的遍历可以省去。traverse(dataMap, m, n, k, x + 1, y);traverse(dataMap, m, n, k, x, y + 1);// traverse(dataMap, m, n, k, x - 1, y);// traverse(dataMap, m, n, k, x, y - 1);}
方法二:广度优先遍历(队列)
int movingCount(int m, int n, int k) {if(m < 1 || n < 1 || m > 100 || n > 100 || k < 0 || k > 20) return -1;int count = 0; // 可到达的格子数vector<vector<int>> dataMap(m, vector<int>(n, 0)); // 访问记录,避免重复queue<pair<char, char>> q; // 广度优先q.push({0, 0});for(; !q.empty(); q.pop()){auto pos = q.front();// 无效坐标:坐标超范围、已经访问过、坐标值数位之和大于k的坐标。if(pos.first == m || pos.second == n || dataMap[pos.first][pos.second]) continue;if(pos.first % 10 + pos.first / 10 + pos.second % 10 + pos.second / 10 > k) continue;++count;dataMap[pos.first][pos.second] = 1;q.push({pos.first + 1, pos.second});q.push({pos.first, pos.second + 1});}return count;}
方法三:递推法
int movingCount(int m, int n, int k) {if(m < 1 || n < 1 || m > 100 || n > 100 || k < 0 || k > 20) return -1;int count = 0;// canVisited[i][j] = canVisited[i-1][j] | canVisited[i][j-1]// 即只能从左边或者上边的元素过来。vector<vector<char>> canVisited(m, vector<char>(n, 0));canVisited[0][0] = 1;for(char row = 0; row < m; ++row){for(char col = 0; col < n; ++col){if(row%10 + row/10 + col%10 + col/10 > k) continue;if(row - 1 >= 0) canVisited[row][col] |= canVisited[row-1][col];if(col - 1 >= 0) canVisited[row][col] |= canVisited[row][col-1];if(canVisited[row][col]) ++count;}}return count;}
训练题:数组组成最小数
string minNumber(vector<int>& nums) {const auto size = nums.size();int len = 0; // nums的元素个数int maxLen; // 最长元素长度vector<string> strs; // 将数字都转化成stringstrs.reserve(size);// 将所有数字转化成stringfor(int i = 0, tmpLen; i < size; ++i) {strs.push_back(to_string(nums[i]));tmpLen = strs.back().size();maxLen = max(maxLen, tmpLen); // 记录最长元素len += tmpLen; // 统计拼接成的string的总长度}// 对字符串数组进行排序,tmpStr1、tmpStr2是为了避免排序比较中的str1+str2<str2+str1的低性能代码。string tmpStr1, tmpStr2;tmpStr1.reserve(maxLen << 1);tmpStr2.reserve(maxLen << 1);sort(strs.begin(), strs.end(), [&](string &a, string &b) -> bool {// "3"和"34":"334" < "343"// "12"和9: "129" < "912"tmpStr1.resize(0);tmpStr2.resize(0);tmpStr1.append(a).append(b);tmpStr2.append(b).append(a);return tmpStr1 < tmpStr2;});// 将已排好序的vector<string>拼接成stringstring ret;ret.reserve(len);for(const auto& str: strs) {ret.append(str);}return ret;}
训练题:构建乘积数组
vector<int> constructArr(vector<int>& a) {const auto size = a.size();vector<int> ret(size,1);int left = 1, right = 1;for(int i = 1; i < size; ++i){ret[i] *= (left *= a[i - 1]);}for(int i = size - 2; i >=0; --i){ret[i] *= (right *= a[i + 1]);}return ret;}
训练题:找数字
场景一:数组中数字出现的次数
vector<int> singleNumbers(vector<int>& nums) {int a = 0, b = 0; // 待找出的两个数为a、bint XOR = 0; // XOR = a ^ bint div = 1; // div为XOR二进制数中最右边第一个1。// XOR的最终结果为a 异或 b的结果,相同的两个数异或=0for(const auto& num : nums) XOR ^= num;// div为XOR二进制数中最右边第一个1。while(!(XOR & div)) div <<= 1;// div = (~XOR + 1) & XOR;// div = XOR & (-XOR); // 负数为补码,补码 = 反码 + 1。// div表示,a、b在这个位上是不同的。我们以此来将数组分成两组分别进行异或即可找出这两个数。for(const auto & num: nums) {if(num & div) a ^= num;else b ^= num;}return {a, b};}
场景二
int singleNumber(vector<int>& nums) {// 保存所有数字在32位的每个位上1出现的次数unsigned short bits[32] = {0};char offset = 0;for(const auto& num : nums){for(char offset = 0; offset < 32; ++offset) {if(num & (1 << offset)) ++bits[offset];}}// 设任意位上的次数=n,则若n%3==0,则表示目标数字在该位置上是0,反之则为1。int fuck = 0;for(char idx = 0; idx < 32; ++idx){fuck |= (bits[idx] % 3) << idx;}return fuck;}
训练题:0~n-1中缺失的数
int missingNumber(vector<int>& nums) {int left = 0;// 二分查找法for(int right = nums.size() - 1, mid; left <= right;){mid = left + ((right - left) >> 1);if(nums[mid] == mid) left = mid + 1;else right = mid - 1;}return left;}
训练题:和为s的数
方法一:哈希表
vector<int> twoSum(vector<int>& nums, int target) {set<int> container;for(const auto& num : nums){if(container.count(num)){return {target - num, num};}else container.insert(target - num);}return {};}
方法二:双指针
vector<int> twoSum(vector<int>& nums, int target) {for(int left = 0, right = nums.size() - 1; left < right;){if(target - nums[left] == nums[right]) return {nums[left], nums[right]};else if(target - nums[left] > nums[right]) ++left;else --right;}return {};}
训练题:合并区间
按区间的左元素升序排序,得到的区间序列,其中连续的区间肯定是在一块的。
vector<vector<int>> merge(vector<vector<int>>& intervals) {if(intervals.size() < 2) return intervals;sort(intervals.begin(), intervals.end());vector<vector<int>> ret{intervals[0]};vector<int> *tmp = nullptr;for(const auto& vec : intervals){tmp = &ret.back();if((*tmp)[1] >= vec[0]) (*tmp)[1] = max((*tmp)[1], vec[1]);else ret.push_back(vec);}return ret;}
训练题:搜索插入位置
int searchInsert(vector<int>& nums, int target) {int left = 0;for(int right = nums.size() - 1, mid; left < right;){mid = ((left + right) >> 1);if(nums[mid] == target) return mid;else if(nums[mid] > target) right = mid;else left = mid + 1;}if(nums[left] < target) return left + 1;return left;}
训练题:中心下标
// leftSum: 左边和// idx: 当前遍历索引,左边就是左边和// total: 数组总和// leftSum * 2 + nums[idx] == totalint pivotIndex(vector<int>& nums) {int sum = 0, leftSum = 0;for(const auto& num : nums) sum += num;unsigned short size = nums.size();for(unsigned short idx = 0; idx < size; ++idx){if((leftSum * 2) + nums[idx] == sum) return idx;leftSum += nums[idx];}return -1;}
训练题:奇数在偶数的前面
方法一:双指针
vector<int> exchange(vector<int>& nums) {if( nums.size() < 2 ) { return nums; }// 快速排序的partition分区思想。for( unsigned short left = -1, right = nums.size();; ){while( ++left < right && (nums[left] & 0x1) );while( --right > left && !(nums[right] & 0x1) );if( left < right ) { std::swap( nums[left], nums[right] ); }else { break; }}return nums;}
方法二:快慢指针
- slow指向待插入奇数的位置。
- fast指向找到的奇数 ```cpp
vector
const auto size = nums.size();for( unsigned short slow = 0, fast = 0;; ){while( fast < size && !( nums[fast] & 0x1 ) ) { ++fast; }if( fast < size ) { std::swap( nums[fast++], nums[slow++] ); }else { break; }}return nums;
}
<a name="FCNIY"></a># 训练题:旋转数组的最小数字题目:[http://t.cn/A6V4bma7](http://t.cn/A6V4bma7)```cppint minArray(vector<int>& numbers) {if(numbers.empty()) return INT_MIN;int left = 0, right = numbers.size() - 1, mid;for(;left < right;){mid = left + ((right - left) >> 1);if(numbers[mid] < numbers[right]) right = mid;else if(numbers[mid] == numbers[right]) right -= 1;else left = mid + 1;}return numbers[left];}
训练题:重复的数字
方法一
遍历数组的过程中,让nums[idx]的值在nums[nums[idx]]位置上,即元素值和索引值相同。
时间复杂度:O(n)
空间复杂度:O(1)
int findRepeatNumber(vector<int>& nums) {const auto size = nums.size();for( int idx = 0; idx < size; ++idx ){if( idx != nums[idx] ){if( nums[idx] == nums[nums[idx]] ) { return nums[idx]; }else { std::swap( nums[nums[idx]], nums[idx] ); }}}return -1;}
方法二:set集合
时间复杂度:O(n)
空间复杂度:O(n)
int findRepeatNumber(vector<int>& nums) {set<int> shit;for( auto &num : nums ){if( shit.count( num ) ) { return num; }else { shit.insert( num ); }}return -1;}
训练题:超过一半的数字
方法一:排序
先排序,然后返回中间那个数,这里我们假设一定存在这样一个数。
- 时间复杂度:O(nlogn)
- 空间复杂度:O(1)
方法二:哈希
用一个哈希统计每个数出现的次数。
- 时间复杂度:O(n)
- 空间复杂度:O(n)
int MoreThanHalfNum_Solution( vector<int> numbers ){map<int, unsigned short> shit;const auto size = numbers.size() >> 1;for( const auto &num : numbers ) if( ++shit[num] > size ) { return num; }return -1;}
方法三
- 时间复杂度:O(n)
- 空间复杂度:O(n)
int MoreThanHalfNum_Solution( vector<int> numbers ){unsigned short size = numbers.size();// 遍历数组,当target与当前数不同,count-1,count=0,就将target赋值为当前数// 当target与当前数相同则count+1,遍历到最后一个数,target必定为目标数unsigned short count = 1; //int target = numbers[0]; // 当前数目for( unsigned short idx = 1; idx < size ; ++idx ){target == numbers[idx] ? ++count : --count;if( !count ){target = numbers[idx];count = 1;}}return target;}
训练题:两数之和
typedef int Value;typedef int Index;/**** @param numbers int整型vector* @param target int整型* @return int整型vector*/vector<int> twoSum( vector<int> &numbers, int target ){if( numbers.size() < 2 ) { return {}; }map<Value, Index> shit;int index2 = -1;for( int index1 = 0; index1 < numbers.size(); index1++ ){if( shit.find( target - numbers[index1] ) != shit.end() ){index2 = shit[target - numbers[index1]];return {index2 + 1, index1 + 1};}shit.insert( make_pair( numbers[index1], index1 ) );}return{};}
训练题:三数之和
题目:https://leetcode-cn.com/problems/3sum/
方法一:降维成两数之和
vector<vector<int>> threeSum(vector<int>& nums) {if(nums.size() < 3) return {};sort(nums.begin(), nums.end());if(nums[0] > 0) return {};const auto size = static_cast<short>(nums.size());vector<vector<int>> ret;for(short first = 0; first < size - 2; ++first){// 先取第一个数,问题就变成在数组中找两数之和的问题,用双指针搞定。// 当前取的first和上一轮的相同,那这个first就重复了。if(first > 0 && nums[first] == nums[first - 1]) continue;int target = 0 - nums[first]; // 目标和int left = first + 1, right = size - 1; // 左右指针while(left < right){// 这里其实还if(nums[left] + nums[right] < target) ++left; // 右移左指针else if(nums[left] + nums[right] > target) --right; // 左移右指针else{ // 找到目标ret.push_back({nums[first], nums[left++], nums[right--]});// 排序之后,相等的数都相邻,找到目标之后,需要做去重操作。for(; left < right && nums[left] == nums[left-1]; ++left); // 当前的left指针和目标和的left指针相同,跳过for(; left < right &&nums[right] == nums[right+1]; --right);}}}return ret;}
训练题:最接近三数之和
题目:https://leetcode-cn.com/problems/3sum-closest/
同上理。
int threeSumClosest(vector<int>& nums, int target) {sort(nums.begin(), nums.end());const auto size = nums.size();int ret = nums[0] + nums[1] + nums[2];if(ret == target) return ret;for(int first = 0; first < size - 2; ++first){if(first > 0 && nums[first] == nums[first - 1]) continue;for(int left = first+1, right = size - 1, tmpSum; left < right; ) {tmpSum = nums[first] + nums[left] + nums[right];if(tmpSum == target) return target;else {if(abs(ret - target) > abs(tmpSum - target)) ret = tmpSum;if(tmpSum > target) for(--right; left < right && nums[right] == nums[right+1]; --right);else for(++left; left < right && nums[left] == nums[left-1]; ++left);}}}return ret;}
训练题:最大累加和
动态规划。
连续子数组的最大累加和肯定是以某个元素结尾。
我们设dp[i]是以i位置元素结尾的最大累加和。按dp思想,我们就要从dp[i-1]来求dp[i]。
int maxSubArray(vector<int>& nums) {int maxSum = nums[0]; // 当前的最大累加和。for(int i = 1; i < nums.size(); i++){// nums[i]存储以nums[i]元素结尾的连续最大累加和。// 如果nums[i - 1]<=0,则nums[i]的最大累加和就等于nums[i]元素,// 如果nums[i - 1]>0,则nums[i]的最大累加和=nums[i-1] + nums[i]nums[i] += max(nums[i - 1], 0);// 比较当前记录的最大累加和,和nums[i]位置处的最大累加和。maxSum = max(maxSum, nums[i]);}return maxSum;}
训练题:合并有序数组
- 时间复杂度:O(n)
- 空间复杂度:O(1)
void merge(int A[], int m, int B[], int n) {// 逆序遍历A、B数组。将最大者保存到tail中for( int tail = m + n - 1, tailA = m - 1, tailB = n - 1; tail >= 0; --tail ){if( tailA >= 0 && ( tailB < 0 || B[tailB] < A[tailA] ) ){A[tail] = A[tailA--];}else{A[tail] = B[tailB--];}}}
训练题:有序数组查找数字
二分查找算法
有序数组查找数字,就不得不想到二分查找法。
二分查找算法的使用心得,将left、right、mid当成二分搜索的动力,nums[mid]与target比较时,mid的赋值决定了搜索的方向(如果找到相同的,是往右边继续搜,还是往左边)。
// nums是升序的,target是需要找的数字// 返回目标数字在数组nums中的索引,如果没有找到返回-1int search(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;for(int mid; left <= right;) {// 可选逻辑:先行判断,减少计算量if(nums[left] == target) return left;else if(nums[right] == target) return right;// 写成mid = (left + right) >> 1有整型溢出风险。// >>位移运算符的优先级很低,请加括号mid = left + ((right - left) >> 1);if(nums[mid] == target) return mid;else if(nums[mid] > target) right = mid - 1;else left = mid + 1;}// 到这一步,left > right,没有找到。return -1;}
算法变形一
// nums是升序的,找到target从索引0开始的第一次出现时的索引,没有返回-1。// 找区域的左边界。int search(vector<int>& nums, int target) {int start = -1;for(int left = 0, right = nums.size() - 1, mid; left <= right;){mid = left + ((right - left) >> 1);if(nums[mid] == target) start = mid;if(nums[mid] >= target) right = mid - 1; // 找到相同的,继续往左边搜。else left = mid + 1;}return start;}
算法变形二
// nums是升序的,找到target从末尾往前第一次出现的索引。不存在返回-1// 找区域的右边界。int search(vector<int>& nums, int target) {int end = -1;for(int left = 0, right = nums.size() - 1, mid; left <= right;){mid = left + ((right - left) >> 1);if(nums[mid] == target) end = mid;if(nums[mid] <= target) left = mid + 1; // 找到相同的继续往右边搜。else right = mid - 1;}return end;}
场景一:查找数字
int search(vector<int>& nums, int target) {int targetIdx = -1;for( int left = 0, right = nums.size() - 1, mid; left <= right; ){mid = left + ((right - left) >> 1);if(nums[mid] == target) ret = mid;if(nums[mid] >= target) right = mid - 1;else { left = mid + 1; }}return targetIdx;}
场景二:搜索插入位置
int searchInsert(vector<int>& nums, int target) {int targetIdx = 0;for(int left = 0, right = nums.size() - 1, mid; left <= right;){mid = left + ((right - left) >> 1);if(nums[mid] == target) return mid;if(nums[mid] > target) targetIdx = mid;else targetIdx = mid + 1;if(nums[mid] > target) right = mid - 1;else left = mid + 1;}return targetIdx;}
场景三:统计数字个数
int search(vector<int>& nums, int target) {// 通过二分查找法找到target区域的左右边界int targetLeftIdx = -1, targetRightIdx = -1;// 找左边界for(int left = 0, right = nums.size() - 1, mid; left <= right;){mid = left + ((right - left) >> 1);if(nums[mid] == target) targetLeftIdx = mid;if(nums[mid] >= target) right = mid - 1;else left = mid + 1;}// 找到右边界for(int left = 0, right = nums.size() - 1, mid; left <= right;){mid = left + ((right - left) >> 1);if(nums[mid] == target) targetRightIdx = mid;if(nums[mid] <= target) left = mid + 1;else right = mid - 1;}// 没有找到targetif(targetLeftIdx == -1) return 0;// 找到target,索引相减 + 1return targetRightIdx - targetLeftIdx + 1;}
训练题:移动零
题目:https://leetcode-cn.com/problems/move-zeroes/
void moveZeroes(vector<int>& nums) {if(nums.size() < 2) return;const auto size = nums.size();// 双指针// p_0: 指向从头开始的第一个0。// p_num: 指向p_0之后的第一个非零数字。int p_0 = 0, p_num = 0;// 指向第一个0for(; p_0 < size && nums[p_0] != 0; ++p_0);p_num = p_0 + 1;while(true){// 指向第一个0for(; p_0 < size && nums[p_0] != 0; ++p_0);// 指向p_0之后的第一个非0for(; p_num < size && nums[p_num] == 0; ++p_num);// 交换了之后,p_0肯定是非0,p_num肯定是0。// 因此将p_0和p_num右移一位if(p_0 < size && p_num < size) swap(nums[p_0++], nums[p_num++]);else break;}}
void moveZeroes(vector<int>& nums) {const auto size = nums.size();int left = 0, right = 0;// left: left指向第一个非0// right: right指向第一个0。for(int left = 0, right = 0; right < size; ++right){if(nums[right]) swap(nums[right], nums[left++]);}}
训练题:两个正序数组的中位数
题目:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/
方法一:模拟法
遍历中位数的位置。
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {if(nums1.empty() && nums2.empty()) return 0;const auto size1 = nums1.size();const auto size2 = nums2.size();// 设:// nums1 = [1, 3, 5];// nums2 = [2, 4, 6];// remainCount = 4;// 按从小到大的顺序,移动tmpIdx1、tmpIdx2索引,得:// tmpIdx1 = 2,即移动到了tmpIdx1-1=1索引处,为3。// tmpIdx2 = 2,即移动到了tmpIdx2-1=1索引处,为4。int remainCount = ((size1 + size2) >> 1) + 1;int tmpIdx1 = 0, tmpIdx2 = 0;for(; tmpIdx1 < size1 && tmpIdx2 < size2 && remainCount ; --remainCount){if(nums1[tmpIdx1] < nums2[tmpIdx2]) ++tmpIdx1;else ++tmpIdx2;}if(remainCount && tmpIdx1 < size1) tmpIdx1 += remainCount;if(remainCount && tmpIdx2 < size2) tmpIdx2 += remainCount;// 若为奇数,则取tmpIdx1-1和tmpIdx2-1索引处更大者。if((size1 + size2) & 1) {if(tmpIdx1 > 0 && tmpIdx2 > 0) return max(nums1[tmpIdx1-1], nums2[tmpIdx2-1]);if(tmpIdx1 > 0) return nums1[tmpIdx1-1];return nums2[tmpIdx2-1];}else{// 若为偶数,则取tmpIdx-1、tmpIdx1-2、tmpIdx2-1、tmpIdx2-2中最大的两个。priority_queue<int> q;if(tmpIdx1 > 0) q.push(nums1[tmpIdx1-- - 1]);if(tmpIdx1 > 0) q.push(nums1[tmpIdx1 - 1]);if(tmpIdx2 > 0) q.push(nums2[tmpIdx2-- - 1]);if(tmpIdx2 > 0) q.push(nums2[tmpIdx2 - 1]);int mid1 = q.top();q.pop();return (mid1 + q.top()) / 2.0;}}
方法二:模拟法
class Solution {public:double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {if(nums1.empty() && nums2.empty()) return 0;const auto size1 = nums1.size();const auto size2 = nums2.size();int remainCount = (size1 + size2) / 2 + 1;int tmpIdx1 = 0, tmpIdx2 = 0;for(; tmpIdx1 < size1 && tmpIdx2 < size2 && remainCount ; --remainCount){if(nums1[tmpIdx1] < nums2[tmpIdx2]) ++tmpIdx1;else ++tmpIdx2;}if(remainCount && tmpIdx1 < size1) tmpIdx1 += remainCount;if(remainCount && tmpIdx2 < size2) tmpIdx2 += remainCount;if((size1 + size2) & 1) {if(tmpIdx1 > 0 && tmpIdx2 > 0) return max(nums1[tmpIdx1-1], nums2[tmpIdx2-1]);if(tmpIdx1 > 0) return nums1[tmpIdx1-1];return nums2[tmpIdx2-1];}else{// 与上一种方法的区别主要在于偶数情况时的动作。// 去tmpIdx1-1和tmpIdx1-2的情况有两种// 一、tmpIdx2无效// 二、tmpIdx>1且tmpIdx2-1<tmpIdx1-2if(tmpIdx1 > 0 && tmpIdx2 == 0 || tmpIdx1 > 1 && tmpIdx2 > 0 && nums2[tmpIdx2-1] <= nums1[tmpIdx1-2])return (nums1[tmpIdx1-1] + nums1[tmpIdx1-2]) / 2.0;else if(tmpIdx2 > 0 && tmpIdx1 == 0 || tmpIdx2 > 1 && tmpIdx1 > 0 && nums1[tmpIdx1-1] <= nums2[tmpIdx2-2])return (nums2[tmpIdx2-1] + nums2[tmpIdx2-2]) / 2.0;return (nums1[tmpIdx1 - 1] + nums2[tmpIdx2-1]) / 2.0;}}};
方法三:模拟法
double findMedianSortedArrays( vector<int> nums1, vector<int> nums2 ){const auto size1 = static_cast<int>( nums1.size() );const auto size2 = static_cast<int>( nums2.size() );bool even = ( ( size1 + size2 ) & 1 ) == 0;if( size1 == 0 && size2 == 0 ) { return 0; }if( size1 == 1 && size2 == 1 ) { return ( nums1[0] + nums2[0] ) / 2.0; }if( size1 == 0 ) { return even ? ( nums2[size2 >> 1] + nums2[( size2 - 1 ) >> 1] ) / 2.0 : nums2[( size2 >> 1 )] ; }if( size2 == 0 ) { return even ? ( nums1[size1 >> 1] + nums1[( size1 - 1 ) >> 1] ) / 2.0 : nums1[( size1 >> 1 )] ; }int remainCount = ( size1 + size2 ) / 2 + 1;int val1 = 0, val2 = 0;int tmpIdx1 = 0, tmpIdx2 = 0;for( ; tmpIdx1 < size1 && tmpIdx2 < size2 && remainCount; --remainCount ){if( even ) { val2 = val1; }if( nums1[tmpIdx1] < nums2[tmpIdx2] ) { val1 = nums1[tmpIdx1++]; }else { val1 = nums2[tmpIdx2++]; }}for( ; tmpIdx1 < size1 && remainCount; --remainCount, ++tmpIdx1 ){if( even ) { val2 = val1; }val1 = nums1[tmpIdx1];}for( ; tmpIdx2 < size2 && remainCount; --remainCount, ++tmpIdx2 ){if( even ) { val2 = val1; }val1 = nums2[tmpIdx2];}if( !even ) { return val1; }else { return ( val1 + val2 ) / 2.0; }}

