LintCode二分查找专辑

1. First Position of Target
class Solution {
public:
    /**
     * @param nums: The integer array.
     * @param target: Target to find.
     * @return: The first position of target. Position starts from 0.
     */
    int binarySearch(vector<int> &nums, int target) {
        if (nums.empty()) return -1;
        int lo = 0, hi = nums.size() - 1;
        // 退出的时候必需是有两个元素(或者长度为1的元素)
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (nums[mid] >= target) hi = mid; // 没有+1因为防止交叉
            else lo = mid; // 同样没有减1
        }
        // 对剩下的两个元素做判断
        if (target == nums[lo]) return lo;
        else if (target == nums[hi]) return hi;
        return -1;
    }
};
2. Search a 2D matrix
class Solution {
public:
    /**
     * @param matrix: matrix, a list of lists of integers
     * @param target: An integer
     * @return: a boolean, indicate whether matrix contains target
     */
    bool searchMatrix(vector<vector<int>> &matrix, int target) {
        for (auto vec: matrix) {
            if (binarySearch(vec, target)) return true;
        }
        return false;
    }

    bool binarySearch(const vector<int> &vec, int target) {
        if (vec.empty()) return false;
        int lo = 0, hi = vec.size() - 1;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (vec[mid] > target) hi = mid;
            else if (vec[mid] < target) lo = mid;
            else return true;
        }
        if (vec[lo] == target || vec[hi] == target) return true;
        return false;
    }
};
3. Search Insert Position
class Solution {
public:
    /**
     * @param A: an integer sorted array
     * @param target: an integer to be inserted
     * @return: An integer
     */
    int searchInsert(vector<int> &A, int target) {
        if (A.empty()) return 0;
        int lo = 0, hi = A.size() - 1;
        // 锁定两个元素的区间
        while (lo + 1 < hi) {
            int mid = lo + (hi - lo) / 2;
            if (A[mid] > target) hi = mid;
            else if (A[mid] < target) lo = mid;
            else return mid;
        }
        // 只有三种可能:
        //  x lo y hi z
        //  1. target smaller or equal to lo, return lo
        //  2. target in the middle of lo and (or equal to) hi return hi
        //  3. target larger than hi return hi + 1
        if (A[lo] >= target) return lo;
        if (A[lo] < target && A[hi] >= target) return hi;
        if (A[hi] < target) return hi + 1;
    }
};
4. Search for a Range
class Solution {
public:
    /**
     * @param A: an integer sorted array
     * @param target: an integer to be inserted
     * @return: a list of length 2, [index1, index2]
     */
    vector<int> searchRange(vector<int> &A, int target) {
        vector<int> res{-1, -1};
        if (A.empty()) return res;
        int lo = 0, hi = A.size() - 1;
        // search for the lower bound
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (target <= A[mid]) hi = mid;
            else lo = mid;
        }
        auto lo_b = -1;
        if (A[hi] == target) lo_b = hi; // 这里是找下届,因此要先hi后lo
        if (A[lo] == target) lo_b = lo;
        res[0] = lo_b;
        // search for th upper bound
        lo = 0, hi = A.size() - 1;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (target >= A[mid]) lo = mid;
            else hi = mid;
        }
        auto up_b = -1;
        if (A[lo] == target) up_b = lo; // 这里找上届,要先lo后hi
        if (A[hi] == target) up_b = hi;
        res[1] = up_b;
        return res;
    }
};

5. Search in Rotated Sorted Array

class Solution {
public:
    /**
     * @param A: an integer rotated sorted array
     * @param target: an integer to be searched
     * @return: an integer
     */
    int search(vector<int> &nums, int target) {
        if (nums.empty()) return -1;
        size_t lo = 0, hi = nums.size() - 1;
        while (hi - lo > 1) {
            auto mid = lo + (hi - lo) / 2;
            if (target == nums[mid]) return mid;
            if (target == nums[lo]) return lo;
            if (target == nums[hi]) return hi; //下面要用到这个判断
            if (nums[mid] < nums[hi]) { // right part
                if (target > nums[mid] && target < nums[hi]) { // increasing part
                    lo = mid;
                } else { // rotated part
                    hi = mid;
                }
            } else { // left part
                if (target < nums[mid] && target > nums[lo]) { // increasing part
                    hi = mid;
                } else { // rotated part
                    lo = mid;
                }
            }
        }
        if (target == nums[lo]) return lo;
        if (target == nums[hi]) return hi;
        return -1;
    }
};

6. Search in Rotated Sorted Array II

class Solution {
public:
    /**
     * @param A: an integer ratated sorted array and duplicates are allowed
     * @param target: An integer
     * @return: a boolean 
     */
    bool search(vector<int> &A, int target) {
        for (auto i = 0; i < A.size(); ++i) {
            if (target == A[i]) return true;
        }
        return false;
    }
};

7. Find Minimum in Rotated Sorted Array

class Solution {
public:
    /**
     * @param nums: a rotated sorted array
     * @return: the minimum number in the array
     */
    int findMin(vector<int> &nums) {
        // assume the vector is not empty
        size_t lo = 0, hi = nums.size() - 1;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            // 不要用lo比较,因为如果没有rotated的话找不到第一个点
            if (nums[mid] > nums[hi]) {
                lo = mid;
            } else if (nums[mid] < nums[hi]) {
                hi = mid;
            }
        }
        return std::min(nums[lo], nums[hi]);
    }
};

8. Find Minimum in Rotated Sorted Array II

class Solution {
public:
    /**
     * @param nums: a rotated sorted array
     * @return: the minimum number in the array
     */
    int findMin(vector<int> &nums) {
        size_t lo = 0, hi = nums.size() - 1;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (nums[mid] < nums[hi]) { // 不能这里移动,否则会跳过最小值
                hi = mid;
            } else if (nums[mid] > nums[hi]) { // 相等的时候移动左边(lo)
                lo = mid;
            } else {
                --hi;
            }
        }
        return std::min(nums[lo], nums[hi]);
    }
};

9. Find Bad Version

/**
 * class SVNRepo {
 *     public:
 *     static bool isBadVersion(int k);
 * }
 * you can use SVNRepo::isBadVersion(k) to judge whether 
 * the kth code version is bad or not.
*/

class Solution {
public:
    /*
     * @param n: An integer
     * @return: An integer which is the first bad version.
     */
    int findFirstBadVersion(int n) {
        int lo = 1, hi = n;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            // 不断挤压,直到两个元素的区间(N, Y)
            if (SVNRepo::isBadVersion(mid)) {
                hi = mid;
            } else {
                lo = mid;
            }
        }
        if (SVNRepo::isBadVersion(lo)) return lo;
        if (SVNRepo::isBadVersion(hi)) return hi;
    }
};

10. Find Peek Element

class Solution {
public:
    /*
     * @param A: An integers array.
     * @return: return any of peek positions.
     */
    int findPeak(vector<int>& nums) {
        // the key point is to determine whether mid is on
        // left side or right side
        size_t lo = 0, hi = nums.size() - 1;
        while (lo + 2 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (nums[mid] > nums[mid - 1] && nums[mid] < nums[mid + 1]) { // left side
                lo = mid;
            } else if (nums[mid] < nums[mid - 1] && nums[mid] > nums[mid + 1]) { // right side
                hi = mid;
            } else if (nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1]) { // peek
                return mid;
            } else {
                hi = mid; // valley, lo = mid is correct too
            }
        }
        return lo + 1;
    }
};

11. Sqrt(x)

class Solution {
public:
    /**
     * @param x: An integer
     * @return: The sqrt of x
     */
    int sqrt(int x) {
        if (x == 1) return 1;
        long lo = 0, hi = x / 2; // 注意这里的类型防止溢出
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (mid * mid > x) {
                hi = mid;
            } else if (mid * mid < x) {
                lo = mid;
            } else {
                return mid;
            }
        }
        // 先hi后lo判断
        if (hi * hi <= x) return hi;
        if (lo * lo <= x) return lo;
    }
};

12. Longest Increasing Subsequence

跟binary search 貌似没什么关系

class Solution {
public:
    /**
     * @param nums: An integer array
     * @return: The length of LIS (longest increasing subsequence)
     */
    int longestIncreasingSubsequence(vector<int> &nums) {
        // corner case
        if (nums.empty()) return 0;
        if (nums.size() == 1) return 1;
        // initialize the seq-length started from each element to 1
        vector<int> lens(nums.size(), 1);
        // scan from end to beginning, increasing the length
        for (int i = nums.size() - 2; i >= 0; --i) {
            auto maxLen = 0;
            for (int j = i + 1; j < nums.size(); ++j) {
                if (nums[j] > nums[i] && lens[j] > maxLen) {
                    maxLen = lens[j];
                }
            }
            lens[i] += maxLen;
        }
        return *std::max_element(lens.begin(), lens.end());
    }
};

13. wood cut

class Solution {
public:
    /**
     * @param L: Given n pieces of wood with length L[i]
     * @param k: An integer
     * @return: The maximum length of the small pieces
     */
    int woodCut(vector<int> &L, int k) {
        if (L.empty()) return 0;
        int res = *std::max_element(L.begin(), L.end());
        if (doCut(L, res) >= k) return res;

        // use hi as the outter loop
        int lo = 1, hi = res;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            auto cnt = doCut(L, mid);
            if (cnt >= k) {
                lo = mid;
            } else if (cnt < k) {
                hi = mid;
            }
        }
        if (doCut(L, hi) >= k) return hi;
        if (doCut(L, lo) >= k) return lo;
        return 0;
    }

    // calculate number of segments after cut by len
    int doCut(const vector<int> &L, int len) {
        int cnt = 0;
        for (auto l: L) {
            cnt += l / len;
        }
        return cnt;
    }
};

14. Interval Minimum Number

  • TLE
/**
 * Definition of Interval:
 * classs Interval {
 *     int start, end;
 *     Interval(int start, int end) {
 *         this->start = start;
 *         this->end = end;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param A: An integer array
     * @param queries: An query list
     * @return: The result list
     */
    vector<int> intervalMinNumber(vector<int> &A, vector<Interval> &queries) {
        vector<int> res;
        if (queries.empty()) return res;
        for (auto query: queries) {
            res.push_back(calcMin(A, query.start, query.end));
        }
    }

    // notice the index below, it's exactly the binary search
    //         (0, 2)
    //     (0, 1)  (1, 2)
    //  (0, 0) (1, 1) (2, 2)
    int calcMin(const vector<int> &A, int lo, int hi) {
        if (lo + 1 >= hi) return std::min(A[lo], A[hi]);
        auto mid = lo + (hi - lo) / 2;
        return std::min(
            calcMin(A, lo, mid),
            calcMin(A, mid, hi));
    }
};
  • MLE
/**
 * Definition of Interval:
 * classs Interval {
 *     int start, end;
 *     Interval(int start, int end) {
 *         this->start = start;
 *         this->end = end;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param A: An integer array
     * @param queries: An query list
     * @return: The result list
     */
    vector<int> intervalMinNumber(vector<int> &A, vector<Interval> &queries) {
        vector<int> res;
        if (queries.empty()) return res;
        vector<int> cache(A.size() * A.size(), INT_MAX);
        //buildMin(A, 0, A.size() - 1, cache);
        for (auto query: queries) {
            if (cache[hash(A, query.start, query.end)] == INT_MAX) {
                buildMin(A, query.start, query.end, cache);
            }
            res.push_back(cache[hash(A, query.start, query.end)]);
        }
    }

    int buildMin(const vector<int> &A, int lo, int hi,
                  vector<int> &cache) {
        if (lo + 1>= hi) {
            cache[hash(A, lo, lo)] = A[lo];
            cache[hash(A, hi, hi)] = A[hi];
            cache[hash(A, lo, hi)] = std::min(A[lo], A[hi]);
            return std::min(A[lo], A[hi]);
        }
        auto mid = lo + (hi - lo) / 2;
        auto min = std::min(buildMin(A, lo, mid, cache),
                            buildMin(A, mid, hi, cache));
        cache[hash(A, lo, hi)] = min;
        return min;
    }

    int hash(const vector<int> &A, int lo, int hi) {
        return lo * A.size() + hi;
    }

    // notice the index below, it's exactly the binary search
    //         (0, 2)
    //     (0, 1)  (1, 2)
    //  (0, 0) (1, 1) (2, 2)
    int calcMin(const vector<int> &A, int lo, int hi) {
        if (lo + 1 >= hi) return std::min(A[lo], A[hi]);
        auto mid = lo + (hi - lo) / 2;
        return std::min(
            calcMin(A, lo, mid),
            calcMin(A, mid, hi));
    }
};
  • AC
class Solution {
    struct Node {
        int lo, hi, min;
        struct Node *l, *r;
    };
public:
    /**
     * @param A: An integer array
     * @param queries: An query list
     * @return: The result list
     */
    vector<int> intervalMinNumber(vector<int> &A, vector<Interval> &queries) {
        vector<int> res;
        if (queries.empty()) return res;

        struct Node *root = buildMinTree(A, 0, A.size() - 1);
        for (auto query: queries) {
            res.push_back(searchMinTree(root, query.start, query.end));
        }
        return res;
    }

    Node *buildMinTree(const vector<int> &A, int lo, int hi) {
        if (lo == hi) {
            return new Node{lo, hi, A[lo], nullptr, nullptr};
        }
        auto mid = lo + (hi - lo) / 2;
        auto l = buildMinTree(A, lo, mid);
        auto r = buildMinTree(A, mid + 1, hi); // 不加1会导致(0, 1)区间无线循环
        return new Node{lo, hi, std::min(l->min, r->min), l, r};
    }

    int searchMinTree(Node *root, int lo, int hi) {
        // 找区间最小值,可以完全匹配是因为下边的mid + 1操作
        if (root->lo == lo && root->hi == hi) return root->min;
        auto mid = root->lo + (root->hi - root->lo) / 2;
        // 不过根节点的两种情况
        if (lo >= mid + 1) return searchMinTree(root->r, lo, hi);
        else if (hi <= mid) return searchMinTree(root->l, lo, hi);
        // 需要过根节点进行搜索
        return std::min(searchMinTree(root->l, lo, mid),
                        searchMinTree(root->r, mid + 1, hi));
    }
};

15. Interval Sum

/**
 * Definition of Interval:
 * classs Interval {
 *     int start, end;
 *     Interval(int start, int end) {
 *         this->start = start;
 *         this->end = end;
 *     }
 * }
 */

class Solution {
    struct Node {
        int lo, hi;
        long long sum; // !!
        Node *l, *r;
    };
public:
    /**
     * @param A: An integer list
     * @param queries: An query list
     * @return: The result list
     */
    vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
        vector<long long> res;
        if (queries.empty()) return res;
        auto root = buildSumTree(A, 0, A.size() - 1);
        for (auto query: queries) {
            res.push_back(searchSumTree(root, query.start, query.end));
        }
        return res;
    }

    Node *buildSumTree(const vector<int> &A, int lo, int hi) {
        if (lo == hi) return new Node{lo, hi, A[lo], nullptr, nullptr};
        auto mid = lo + (hi - lo) / 2;
        auto l = buildSumTree(A, lo, mid);
        auto r = buildSumTree(A, mid + 1, hi);
        return new Node{lo, hi, l->sum + r->sum, l, r};
    }

    long long searchSumTree(Node *root, int lo, int hi) {
        if (root->lo == lo && root->hi == hi) return root->sum;
        auto mid = root->lo + (root->hi - root->lo) / 2;
        if (lo >= mid + 1) return searchSumTree(root->r, lo, hi);
        if (hi <= mid) return searchSumTree(root->l, lo, hi);
        return searchSumTree(root->l, lo, mid) +
               searchSumTree(root->r, mid + 1, hi);
    }
};

16. Interval Sum II

class Solution {
    struct Node {
        int lo, hi;
        long long sum;
        Node *l, *r;
    };

    Node *root;
public:
    /* you may need to use some attributes here */

    /*
    * @param A: An integer array
    */
    Solution(vector<int> A) : root(nullptr) {
        if (!A.empty()) {
            root = build(A, 0, A.size() - 1);
        }
    }

    Node *build(const vector<int> &A, int lo, int hi) {
        if (lo == hi) return new Node{lo, hi, A[lo], nullptr, nullptr};
        auto mid = lo + (hi - lo) / 2;
        auto l = build(A, lo, mid);
        auto r = build(A, mid + 1, hi);
        return new Node{lo, hi, l->sum + r->sum, l, r};
    }

    long long query(Node * root, int lo, int hi) {
        if (root->lo == lo && root->hi == hi) return root->sum;
        auto mid = root->lo + (root->hi - root->lo) / 2;
        if (lo >= mid + 1) return query(root->r, lo, hi);
        if (hi <= mid) return query(root->l, lo, hi);
        return query(root->l, lo, mid) + query(root->r, mid + 1, hi);
    }

    long long modify(Node *root, int index, int val) {
        if (root->lo == index && root->hi == index) {
            auto diff = val - root->sum;
            root->sum = val;
            return diff;
        }
        auto diff = 0;
        auto mid = root->lo + (root->hi - root->lo) / 2;
        // 只用更新一个分支
        if (index >= mid + 1) diff = modify(root->r, index, val);
        if (index <= mid) diff = modify(root->l, index, val);
        root->sum += diff;
        return diff;
    }

    /*
     * @param start: An integer
     * @param end: An integer
     * @return: The sum from start to end
     */
    long long query(int start, int end) {
        if (!root) return 0;
        return query(root, start, end);
    }

    /*
     * @param index: An integer
     * @param value: An integer
     * @return: nothing
     */
    void modify(int index, int value) {
        if (root) modify(root, index, value);
    }
};

17. Count of Smaller Number

class SolutionV1 {
public:
    /**
     * @param A: An integer array
     * @param queries: The query list
     * @return: The number of element in the array that are smaller that the given integer
     */
    vector<int> countOfSmallerNumber(vector<int> &A, vector<int> &queries) {
        vector<int> res;
        if (A.empty()) {
            res.assign(queries.size(), 0);
            return res;
        }

        sort(A.begin(), A.end());
        for (auto query: queries) {
            res.push_back(search(A, query));
        }
        return res;
    }

    int search(const vector<int> &nums, int target) {
        size_t lo = 0, hi = nums.size() - 1;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (target <= nums[mid]) {
                hi = mid;
            } else {
                lo = mid;
            }
        }
        // 实际上是在找插入的位置
        if (target <= nums[lo]) return lo;
        if (target > nums[lo] && target <= nums[hi]) return hi;
        if (target > nums[hi]) return hi + 1;
        return 0;
    }
};

18. Count of Smaller Number II

class Solution {
    struct Node {
        int val;
        int cnt;
        Node *l, *r;
    };
public:
    /**
     * @param A: an integer array
     * @return: A list of integers includes the index of the first number and the index of the last number
     */
    vector<int> countOfSmallerNumberII(vector<int> &A) {
        // 1. build a binary tree, for each node instered into the node
        //    - if the val to be instered is on the right node, which is easy 
        //      to handle, just equals to 1 + cnt(root);
        //    - if the val is equal to the root, just update the root count
        //    - if the val is small than the root count, search to the right pos
        //      and pass the parent's cnt into current node
        // NOTICE: this is a top down approach, which means path is required
        vector <int> temp;  
        vector<int> res;  
        for (int i = 0; i < A.size(); i++) {  
            auto itr = lower_bound(temp.begin(), temp.end(), A[i]);  
            int count = itr - temp.begin();  
            res.push_back(count);  
            temp.insert(itr, A[i]);  
        }
    }
};

19. Divided Two Integers

class Solution {
public:
    /**
     * @param dividend: the dividend
     * @param divisor: the divisor
     * @return: the result
     */
     enum Sign {
         POS,
         NEG
     };

    int divide(int dd, int d) {
        long long dividend = dd;
        long long divisor = d;
        if (divisor == 0) return INT_MAX;
        if (dividend == INT_MIN && divisor == -1) return INT_MAX;
        if (dividend == 0) return 0;

        enum Sign sign = POS;
        if (dividend < 0 && divisor > 0) sign = NEG;
        if (dividend >0 && divisor < 0) sign = NEG;

        dividend = std::abs(dividend);
        divisor = std::abs(divisor);

        // max index
        // q = y / x
        // y = x * q
        // q = qi * 2 ^ i + ... + q0 * 2 ^ 0
        int i = 0;
        while ((divisor << (i + 1)) <= dividend) ++i;

        int res = 0;
        while (dividend > 0 && i >= 0) {
            if (dividend >= (divisor << i)) {
                dividend -= divisor << i;
                res += 1 << i;
            }
            i--;
        }
        return sign == NEG ? -res : res;
    }
};

20. Pow(x, n)

class Solution {
    #include <float.h>
public:
    /*
     * @param x: the base number
     * @param n: the power number
     * @return: the result
     */
    double myPow(double x, int n) {
        if (n == 0) return 1;
        int neg = 1;
        if (n < 0) {
            neg = -1;
            n = -n;
        }
        auto res = doPow(x, n);
        if (neg == -1) res = 1. / res;
        return res;
    }

    double doPow(double x, int n) {
        if (n == 0) return 1;
        auto res = doPow(x, n / 2);
        return (n % 2) ? (x * res * res) : (res * res);
    }
};
class Solution {
public:
    /*
     * @param nums: An integer array sorted in ascending order
     * @param target: An integer
     * @return: An integer
     */
    int findPosition(vector<int> &nums, int target) {
        if (nums.empty()) return -1;
        size_t lo = 0, hi = nums.size() - 1;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (target == nums[mid]) return mid;
            else if (target > nums[mid]) {
                lo = mid;
            } else {
                hi = mid;
            }
        }
        return -1;
    }
};

22. Find K Closet Elements

class Solution {
public:
    /**
     * @param A: an integer array
     * @param target: An integer
     * @param k: An integer
     * @return: an integer array
     */
    vector<int> kClosestNumbers(vector<int> &A, int target, int k) {
        // 1. search insert position of target
        // 2. merge k elements on left and k elements on right by their difference
        if (A.empty()) return vector<int>{};
        auto pos = insertPos(A, target);
        auto lpos = pos, rpos = pos + 1;
        vector<int> res;

        while (lpos >= 0 && rpos <= (A.size() - 1) && res.size() < k) {
            auto ldiff = abs(A[lpos] - target);
            auto rdiff = abs(A[rpos] - target);
            if (ldiff == rdiff) {
                // store the smaller of the two
                if (A[lpos] < A[rpos]) {
                    res.push_back(A[lpos--]);
                } else {
                    res.push_back(A[rpos++]);
                }
            } else if (ldiff > rdiff) {
                res.push_back(A[rpos++]);
            } else {
                res.push_back(A[lpos--]);
            }
        }

        while (lpos >= 0 && res.size() < k) {
            res.push_back(A[lpos--]);
        }

        while (rpos <= (A.size() - 1) && res.size() < k) {
            res.push_back(A[rpos++]);
        }

        return res;
    }

    int insertPos(const vector<int> &A, int target) {
        size_t lo = 0, hi = A.size() - 1;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (target == A[mid]) return mid;
            else if (target > A[mid]) lo = mid;
            else hi = mid;
        }

        return min(lo, hi);
    }
};

23. Intersection of two arrays

class Solution {
public:

    /*
     * @param nums1: an integer array
     * @param nums2: an integer array
     * @return: an integer array
     */
    vector<int> intersection(vector<int> nums1, vector<int> nums2) {
        if (nums1.empty() || nums2.empty()) return vector<int>{};
        set<int> res;
        sort(nums2.begin(), nums2.end());
        for (int n1: nums1) {
            if (binarySearch(nums2, n1)) {
                res.insert(n1);
            }
        }
        vector<int> r(res.begin(), res.end());
        return r;
    }

    bool binarySearch(const vector<int> &nums, int target) {
        size_t lo = 0, hi = nums.size() - 1;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            if (nums[mid] == target) return true;
            else if (nums[mid] < target) lo = mid;
            else hi = mid;
        }
        if (nums[lo] == target || nums[hi] == target) return true;
        return false;
    }
};

24. Intersection of two arrays II

class Solution {
public:

    /*
     * @param nums1: an integer array
     * @param nums2: an integer array
     * @return: an integer array
     */
    vector<int> intersection(vector<int> nums1, vector<int> nums2) {
        if (nums1.empty() || nums2.empty()) return vector<int>{};

        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());

        vector<int> res;
        int p1 = 0, p2 = 0;
        while (p1 < nums1.size() && p2 < nums2.size()) {
            if (nums1[p1] == nums2[p2]) {
                res.push_back(nums1[p1++]);
                ++p2;
            } else if (nums1[p1] > nums2[p2]) {
                ++p2;
            } else {
                ++p1;
            }
        }
        return res;
    }
};

25. guess number

// Forward declaration of guess API.
// @param num, your guess
// @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
int guess(int num);

class Solution {
public:
    /**
     * @param n an integer
     * @return the number you guess
     */
    int guessNumber(int n) {
        int lo = 0, hi = n;
        while (lo + 1 < hi) {
            auto mid = lo + (hi - lo) / 2;
            auto res = guess(mid);
            if (res == 0) return mid;
            else if (res > 0) lo = mid;
            else hi = mid;
        }
        if (guess(lo) == 0) return lo;
        if (guess(hi) == 0) return hi;
    }
};

26. Find the Duplicate Number

class Solution {
public:
    /**
     * @param nums: an array containing n + 1 integers which is between 1 and n
     * @return: the duplicate one
     * O(1) space: no hash, no array, no tree
     * O(n^2) time: no brute force, consider binary search
     * special condition: numbers 1...n
     */
    int findDuplicate(vector<int> &nums) {
        int lo = 1, hi = nums.size() - 1; // 1...n
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;
            int cnt = 0; // statistics numbers samller than mid
            for (auto num: nums) {
                if (num <= mid) {
                    ++cnt;
                }
            }
            // there are `mid` number smaller than mid in normal sequence
            // if there are `cnt` numbers larger than mid, then the duplicated
            // number is in the hi...size part
            if (cnt > mid) hi = mid;
            else lo = mid + 1;
        }
        return lo;
    }
};

27. Maximum Average Subarray II

class Solution {
public:
    /*
     * @param nums: an array with positive and negative numbers
     * @param k: an integer
     * @return: the maximum average
     */
     /*
    (nums[i]+nums[i+1]+…+nums[j])/(j-i+1)>x
    =>nums[i]+nums[i+1]+…+nums[j]>x*(j-i+1)
    =>(nums[i]-x)+(nums[i+1]-x)+…+(nums[j]-x)>0
    */
    double maxAverage(vector<int> &nums, int k) {
        double lo = *std::min_element(nums.begin(), nums.end());
        double hi = *std::max_element(nums.begin(), nums.end());
        while (hi - lo > 10e-7) { 
            double mid = (lo + hi) / 2; 
            if (check(nums, k, mid)) lo = mid;
            else hi = mid;
        } 
        return (lo + hi) / 2;
    }

    // k is the sliding window
    // S(i) = S(i-1) + Num(i) - Num(i - k + 1)
    double check(const vector<int> &nums, int k, double mid) {
        double sum = 0.0;
        for (int i = 0; i < k; i++)
            sum += nums[i] - mid; 

        double maxSum = sum, prev = nums[0] - mid;

        for (int i = k; i < nums.size(); i++) { 
            sum = sum - nums[i - k] + nums[i]; 
            maxSum = std::max(maxSum, std::max(sum, sum + prev)); 
            prev = std::max((double)nums[i - k + 1], nums[i - k + 1] + prev) - mid;
        }

        return maxSum >= 0;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值