个人技术分享

704. 二分查找

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            }
        }
        return -1;
    }
};

278. 第一个错误的版本

// The API isBadVersion is defined for you.
// bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
        int left = 1, right = n;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (!isBadVersion(mid)) {
                left =  mid + 1; 
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
};

977. 有序数组的平方

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int len = nums.size();
        int left = 0, right = len - 1;
        
        vector<int> res(len);
        for (int i = len - 1; i >= 0; --i) {
            int leftVal = nums[left] * nums[left];
            int rightVal = nums[right] * nums[right];
            if (leftVal > rightVal) {
                res[i] = leftVal;
                left++;
            } else {
                res[i] = rightVal;
                right--;
            }
        }
        return res;
    }
};

35. 搜索插入位置

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;

        while (left <= right) {
            int mid  = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            }
        }
        // 二分没有找到插入的位置, 那么target 一定小于 left, 从left 位置插入既能满足题解。
        return left;
    }
};

34. 在排序数组中查找元素的第一个和最后一个位置

class Solution {
public:
    int leftBound(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while (left <= right) {
            int mid  = left + (right - left) / 2;
            if (nums[mid] == target) {
                right = mid - 1;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1; 
            }
        }

        // left越界,则不存在
        if (left >= nums.size()) {
            return -1;
        }
        return nums[left] == target ? left : -1;
    }

    int rightBound(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while (left <= right) {
            int mid  = left + (right - left) / 2;
            if (nums[mid] == target) {
                left = mid + 1;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1; 
            }
        }
        // right越界,则不存在
        if (right < 0) {
            return -1;
        }
        return nums[right] == target ? right : -1;
    }

    vector<int> searchRange(vector<int>& nums, int target) {
        if (nums.empty()) {
            return vector<int>({-1, -1});
        }
        int left = leftBound(nums, target);
        int right = rightBound(nums, target);
        return vector<int>({left, right});
    }
};

153. 寻找旋转排序数组中的最小值

旋转排序数组需要 和 right对比

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left= 0, right = nums.size() - 1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == nums[right]) {
                left = mid + 1;
            } else if (nums[mid] > nums[right]) {
                left = mid + 1;
            } else if (nums[mid] < nums[right]) {
                right = mid;
            }
        }
        return nums[right];
    }
};

33. 搜索旋转排序数组

寻找最小值的下标,分段处理,注意边界

旋转排序数组需要 和 right对比

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left= 0, right = nums.size() - 1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == nums[right]) {
                left = mid + 1;
            } else if (nums[mid] > nums[right]) {
                left = mid + 1;
            } else if (nums[mid] < nums[right]) {
                right = mid;
            }
        }
        return right;
    }

    int bsearch(vector<int>& nums, int left, int right, int target) {
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } else if (nums[mid] == target) {
                return mid;
            }
        }
        return -1;
    }

    int search(vector<int>& nums, int target) {
        int minIndex = findMin(nums);
        if (minIndex == 0) {
            return bsearch(nums, minIndex, nums.size() - 1, target);
        } else if (nums[0] < target) {
            return bsearch(nums, 0, minIndex - 1, target);
        } else if (nums[0] > target) {
            return bsearch(nums, minIndex, nums.size() - 1, target);
        } else {
            return 0;
        }
    }
};

直接二分查找,注意边界

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            }
            if (nums[mid] < nums[right]) {
                if (target > nums[mid] && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            } else {
                if (target >= nums[left] && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
        }
        return -1;
    }
};

74. 搜索二维矩阵

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        int n = matrix[0].size();
        int low = 0, high = m * n - 1;
        while (low <= high) {
            int mid = low + (high - low) / 2;
            int val = matrix[mid / n][mid % n];
            if (val == target) {
                return true;
            } else if (val < target) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return false;
    }
};

4. 寻找两个正序数组的中位数

class Solution {
public:
    double getKth(vector<int>& nums1, int start1, int end1, vector<int>& nums2, int start2, int end2, int k) {
        int len1 = end1 - start1 + 1;
        int len2 = end2 - start2 + 1;
        if (len1 > len2) {
            return getKth(nums2, start2, end2, nums1, start1, end1, k);
        }

        if (len1 == 0) {
            return nums2[start2 + k - 1];
        }

        if (k == 1) {
            return min(nums1[start1], nums2[start2]);
        }

        // 每次减少k/2
        int mid1 = start1 + min(len1, k / 2) - 1;
        int mid2 = start2 + min(len2, k / 2) - 1;

        if (nums1[mid1] < nums2[mid2]) {
            return getKth(nums1, mid1 + 1, end1, nums2, start2, end2, k - (mid1 - start1 + 1));
        } else {
            return getKth(nums1, start1, end1, nums2, mid2 + 1, end2, k - (mid2 - start2 + 1));
        }
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        int k1 = (m + n + 1) / 2;
        int k2 = (m + n + 2) / 2;
        return (getKth(nums1, 0, m - 1, nums2, 0, n - 1, k1) + getKth(nums1, 0, m - 1, nums2, 0, n - 1, k2)) * 0.5;
    }
};