zoukankan      html  css  js  c++  java
  • leetcode 二分查找

    最简单的二分查找。最基层!

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

      

    解1:

    思路:评论:

    简单二分。跟上题本质没啥不同。变换的是left,right,mid的决策条件。

    复制代码
    // Forward declaration of isBadVersion API.
    bool isBadVersion(int version);
    
    class Solution {
    public:
        int firstBadVersion(int n) {
            int left=1;
            int right=n;
            int mid=left+(right-left)/2;
            while(left<right){
                if(!isBadVersion(mid)){
                    left=mid+1;
                }
                else{
                    right=mid;
                }
                mid=left+(right-left)/2;
            }
            return left;
        }
    };
    复制代码

     

    解法1:(自己的代码!)

    思路:两次二分查找

    注意:开头的两个异常条件很重要,缺一不可。分别判断两个维度的数组是否为空

    复制代码
    class Solution {
    public:
        bool searchMatrix(vector<vector<int>>& matrix, int target) {
            if(matrix.empty()) return false;
            if(matrix[0].size()==0) return false;
            //先找到外层
            int m=matrix.size();
            int n=matrix[0].size();
            if(matrix[m-1][n-1]<target) return false;
            int i;
            for(i=0;i<m;i++){
                if(matrix[i][n-1]>=target){
                    break;
                }
            }
            //再找内层,把二维转化为一维
            int left=0,right=n-1;
            while(left<=right){
                int mid=left+(right-left)/2;
                if(matrix[i][mid]==target) return true;
                else if(matrix[i][mid]>target){
                    right=mid-1;
                }
                else if(matrix[i][mid]<target){
                    left=mid+1;
                }
            }
            return false;
        }
    };
    复制代码

     

    解法1:

    思路:。根据题示,所以如果假如序列是递增的,那么极值就是right。如果是递减的,那么极值就是left。

    而这又可以进一步得到化简。题目中说明只要求一个极值就可以。所以直接判断left 和 left+1 。right 和 right-1 。

    接下来就是直接取中间mid 。

    可以分为4种情况。

    1 3 5 

    1 3 2 

    5 3 1

    5 3 5 

    这4种。

    分别对应着:

    复制代码
                if((nums[mid-1]<nums[mid])&&(nums[mid]>nums[mid+1])) return mid;
                if((nums[mid-1]<nums[mid])&&(nums[mid]<nums[mid+1])){
                    left=mid;
                }
                if((nums[mid-1]>nums[mid])&&(nums[mid]>nums[mid+1])){
                    length=mid;
                }
                if((nums[mid-1]>nums[mid])&&(nums[mid]<nums[mid+1])){
                    left=mid;
                }
    复制代码

    复制代码
    class Solution {
    public:
        int findPeakElement(vector<int>& nums) {
            if(nums.empty()||nums.size()==1) return 0; 
            int left=0;
            int length=nums.size()-1;
            if(nums[left]>nums[left+1]) return left;
            if(nums[length]>nums[length-1]) return length;
            while(true){
                int mid=left+(length-left)/2;
                if((nums[mid-1]<nums[mid])&&(nums[mid]>nums[mid+1])) return mid;
                if((nums[mid-1]<nums[mid])&&(nums[mid]<nums[mid+1])){
                    left=mid;
                }
                if((nums[mid-1]>nums[mid])&&(nums[mid]>nums[mid+1])){
                    length=mid;
                }
                if((nums[mid-1]>nums[mid])&&(nums[mid]<nums[mid+1])){
                    left=mid;
                }
                
            }
            return left;
        }
    };
    复制代码

     

    解法1:自己写的代码没想到这么NB!
    思路:不好描述。自己再理解一下吧。觉得很快!尤其是添加了while循环中的前两句。主要是if(nums[left]==target) return left;这一句。

    二分法加双指针的感觉。如果left指向的不等于target。且left+(right-left)/2得到的mid的值也不等于target 。那么就把left++。再继续判断

    (感觉还可以继续优化)

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

     还应该参考一下别人的思路:

    这个题还没有掌握透彻。


     

     解法1:

    思路:没想到,和上一题同样的代码。只是返回的是布尔型。可以解决两道题

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

    同样的感觉没有领略到此题的精髓


    注意:依次遍历。时间复杂度为O(N) 会超时

    解法1:

    思路:同上两个题相同。时间复杂度同样没有达到O(logN)。而是O(N/2)

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

    解法2:

    思路:二分(来自官方题解)

     

    时间复杂度O(logN)

    复制代码
    class Solution {
    public:
        int findMin(vector<int>& nums) {
            if(nums.size()==1) return nums[0];
            int left=0;
            int right=nums.size()-1;
            //如果是有序数组
            if(nums[left]<nums[right]){
                return nums[left];
            }
            //二分查找:
            while(right>=right){
                int mid=left+(right-left)/2;
                if(nums[mid]>nums[mid+1]) return nums[mid+1];
                if(nums[mid-1]>nums[mid]) return nums[mid];
                if(nums[mid]>nums[left]){
                    left=mid+1;
                }
                else
                    right=mid-1;
            }
            return -1;
        }
    };
    复制代码

     

    解法1:

    复制代码
    class Solution {
    public:
        vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
            vector<int> res;
            for(int i = 0;i<nums1.size();i++){
                for(int j=0;j<nums2.size();j++){
                    if(nums1[i] == nums2[j]){
                        res.push_back(nums1[i]);
                        break;
                    }
                }
            }
            set<int> st(res.begin(),res.end());
            res.assign(st.begin(),st.end());//assign函数相当于拷贝函数
            return res;
        }
    };
    复制代码

     

     解法1:

    复制代码
    class Solution {
    public:
        vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
            sort(nums1.begin(),nums1.end());
            sort(nums2.begin(),nums2.end());
            int size1 = nums1.size();
            int size2 = nums2.size();
            int cur1 = 0, cur2 = 0;
            vector<int> result;
            while(cur1 < size1 && cur2 < size2){
                if(nums1[cur1] == nums2[cur2]){
                    result.push_back(nums1[cur1]);
                    cur1++;
                    cur2++;
                }
                else if(nums1[cur1] < nums2[cur2]){
                    cur1++;
                }
                else if(nums1[cur1] > nums2[cur2]){
                    cur2++;
                }
            }
            return result;
        }
    };
    复制代码

     

     解法1:效率低,递归。而且还使用了swap 函数,面试时不能使。

    复制代码
    class Solution {
    public:
        void reverseString(vector<char>& s) {
            if(s.empty()){
                return;
            }
            recursive(s,0,s.size()-1);
        }
        void recursive(vector<char>& s,int start,int end){
            if(start > end){
                return;
            }
            recursive(s,start+1,end-1);
            swap(s[start],s[end]);
        }
    };
    复制代码

    解法2:

    思路:迭代进行交换。双指针

    复制代码
    class Solution {
        public void reverseString(char[] s) {
            int start = 0, end = s.length-1;
            char temp;
            while(start < end){
                temp = s[start];//交换
                s[start] = s[end];
                s[end] = temp;
                start++;
                end--;
            }
            
        }
    }
    复制代码

    解法3:双指针 异或交换。

    普及一下知识:

    复制代码
    class Solution {
    public:
        void reverseString(vector<char>& s) {
            int i = 0, j = s.size() - 1;
            while(i < j){
                s[i] = s[i] ^ s[j];
                s[j] = s[i] ^ s[j];
                s[i] = s[i] ^ s[j];
                i++;
                j--;
            }
        }
    };
    复制代码

  • 相关阅读:
    在R语言中轻松创建关联网络
    在R语言中显示美丽的数据摘要summary统计信息
    R语言中不同类型的聚类方法比较
    R语言中的划分聚类模型
    R语言解释生存分析中危险率和风险率的变化
    Stata估算观测数据的风险比
    Stata 中Mata的st_view函数
    R语言多臂试验
    R语言使用倾向评分提高RCT(随机对照试验)的效率
    R语言在RCT中调整基线时对错误指定的稳健性
  • 原文地址:https://www.cnblogs.com/JasonPeng1/p/12118856.html
Copyright © 2011-2022 走看看