二分搜索——从LeetCode题海中总结常见套路

翻车了,一题二分都没用上,gg

目录

LeetCode852.山脉数组的峰顶索引

LeetCode230.二叉搜索树中第K小的元素

LeetCode671.二叉树中第二小的节点

LeetCode1237.找出给定方程的正整数解

瞎暴力

剪枝优化

思考二分:

LeetCode287.寻找重复数

哈希表

木桶法

LeetCode面试题08.03魔术索引

瞎暴力

利用有序数组性质


LeetCode852.山脉数组的峰顶索引

笨方法当然是找到最大值的下标然后垫底

class Solution {
public:
    int peakIndexInMountainArray(vector<int>& A) {
        vector<int> a(A.begin(),A.end());
        sort(a.begin(),a.end());
        int b = a[a.size()-1];//找到最大值
        for(int i = 0;i<A.size();i++){
            if(A[i]==b)
                return i;//找到最大值的下标
        }
        return 0;
    }
};

忽然发现不同二分,直接从左向右遍历,遇到右比作左大的情况就找到了

class Solution {
public:
    int peakIndexInMountainArray(vector<int>& A) {
        for(int i=0;i<A.size();i++){
            if(A[i]>A[i+1])//山峰出现
                return i;
        }
        return 0;
    }
};

LeetCode230.二叉搜索树中第K小的元素

一分钟搞了个中序遍历AC,还是没有用到二分,很失望

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
private:
    vector<int> v;
public:
    int kthSmallest(TreeNode* root, int k) {
        InOrderTraver(root,k);
        return v[k-1];
    }
    void InOrderTraver(TreeNode* root,int k){
        if(root==NULL)
            return;
        InOrderTraver(root->left,k);
        v.push_back(root->val);
        if(v.size()==k)//到第K个就停下
            return;
        InOrderTraver(root->right,k);
    }
};

LeetCode671.二叉树中第二小的节点

又没用二分,遍历大法好,失望……

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
private:
    set<int> s;
public:
    int findSecondMinimumValue(TreeNode* root) {
        PreOrderTraver(root);
        if(s.size()<2)
            return -1;
        set<int>::iterator it = s.begin();
        it++;
        return *it;
    }
    void PreOrderTraver(TreeNode* root){
        if(root==NULL)
            return;
        s.insert(root->val);
        PreOrderTraver(root->left);
        PreOrderTraver(root->right);
    }
};

LeetCode1237.找出给定方程的正整数解

瞎暴力

一开始不很清楚,看一眼提示,瞬间用暴力AC

没有利用递增的性质,面试这么说就挂了

/*
 * // This is the custom function interface.
 * // You should not implement it, or speculate about its implementation
 * class CustomFunction {
 * public:
 *     // Returns f(x, y) for any given positive integers x and y.
 *     // Note that f(x, y) is increasing with respect to both x and y.
 *     // i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1)
 *     int f(int x, int y);
 * };
 */

class Solution {
public:
    vector<vector<int>> findSolution(CustomFunction& customfunction, int z) {
        vector<vector<int>> vv;
        for(int i=1;i<=1000;i++){
            for(int j=1;j<=1000;j++){
                vector<int> v;
                if(customfunction.f(i,j)==z){
                    v.push_back(i);
                    v.push_back(j);
                    vv.push_back(v);
                }
            }
        }
        return vv;
    }
};

剪枝优化

/*
 * // This is the custom function interface.
 * // You should not implement it, or speculate about its implementation
 * class CustomFunction {
 * public:
 *     // Returns f(x, y) for any given positive integers x and y.
 *     // Note that f(x, y) is increasing with respect to both x and y.
 *     // i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1)
 *     int f(int x, int y);
 * };
 */

class Solution {
public:
    vector<vector<int>> findSolution(CustomFunction& customfunction, int z) {
        vector<vector<int>> vv;
        for(int i=1;i<=1000;i++){
            for(int j=1;j<=1000;j++){
                vector<int> v;
                if(customfunction.f(i,j)==z){
                    v.push_back(i);
                    v.push_back(j);
                    vv.push_back(v);
                }else if(customfunction.f(i,j)>z){//利用递增的性质将不可能的解法剔除,属于剪枝
                    break;
                }
            }
        }
        return vv;
    }
};

思考二分:

因为是递增的,所有对每个x取值,最多只能由一个y值,再利用递增的性质,二分查找;

反过来,对于每个y取值,最多只能由一个x值满足;

所以,单独二分只能利用一个变量递增的性质,还是会有浪费啊!

最好的是双指针二分,这样一点时间浪费都没有,但是我懒啊,不做了哈哈哈下一题

还是贴一个别人的吧,其实思路构思出来的话一分钟也能A

vector<vector<int>> findSolution(CustomFunction& customfunction, int z) {
    vector<vector<int>> res = {};
    int x =1; int y = 1000;
    while(x<=1000 && y>=1 ){
        if(customfunction.f(x,y) == z) {
            res.push_back({x,y});
            ++x;--y;
        }
        else if(customfunction.f(x,y)<z){
            ++x;
        } else --y;
    }
    return res;
}

LeetCode287.寻找重复数

哈希表

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        map<int,int> m;
        for(int i=0;i<nums.size();i++){
            m[nums[i]]++;
            if(m[nums[i]]>=2)
                return nums[i];
        }
        return 0;
    }
};

木桶法

因为我们提前知道木桶下标值的范围,所以用木桶法代替哈希表法可以更为方便

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int a[nums.size()+1];
        for(int i=1;i<=nums.size();i++)
            a[i]= 0;
        for(int i=0;i<nums.size();i++){
            a[nums[i]]++;
            if(a[nums[i]]>=2)
                return nums[i];
        }
        return 0;
    }
};

LeetCode面试题08.03魔术索引

瞎暴力

遇事不决量子力学,啥也不会直接暴力

根本就没有利用有序数组的性质,面试gg

class Solution {
public:
    int findMagicIndex(vector<int>& nums) {
        int min = (1<<21);
        for(int i=0;i<nums.size();i++)
            if(nums[i]==i&&nums[i]<min)
                min = nums[i];
        if(min==(1<<21))
            return -1;
        return min;
    }
};

利用有序数组性质

直接从头开始找最小,二分太浪费了吧?

class Solution {
public:
    int findMagicIndex(vector<int>& nums) {
        for(int i=0;i<nums.size();i++)
            if(nums[i]==i)
                return nums[i];
        return -1;
    }
};
发布了377 篇原创文章 · 获赞 344 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/qq_41895747/article/details/105003717