二分算法及其公式

二分查找

  • 二分查找是大多数人第一个接触到的算法,很多人都认为只有有序的数组可以使用二分查找,但这种思想其实是错误的,二分查找是可以用于拥有二段性的数组,而且二分算法是由模板做参考的,所以只要掌握就可以解决大多二分查找的问题

题目

请添加图片描述

class Solution {
public:

    //二分查找算法不一定是要使用严格的升序或者降序,只要区间可以划分为二段性就可以使用
    vector<int> searchRange(vector<int>& nums, int target) {
        //其实可以分别寻找第一个位置和最后一个位置
        int left = 0, right = nums.size()-1, sz = nums.size(), mid = 0;
        vector<int> ret;
        //寻找左边界
        while(left <= right){
            mid = left + (right-left+1)/2;
            if(nums[mid] == target && (mid == 0 || nums[mid-1] != target)){
                ret.emplace_back(mid);
                break;
            }

            if(nums[mid] > target || nums[mid] == target) right = mid-1;
            if(nums[mid] < target) left = mid+1;
        }
        //寻找右边界
        left = mid, right = nums.size()-1;
        while(left <= right){
            mid = left + (right-left+1)/2;
            if(nums[mid] == target && (mid == sz-1 || nums[mid+1] != target)){
                ret.emplace_back(mid);
                break;
            }

            if(nums[mid] > target) right = mid-1;
            if(nums[mid] < target || nums[mid] == target) left = mid+1;
        }

        if(ret.empty()){
            return {-1,-1};
        }

        return ret;
    }
};

​ 这是我最开始写的代码,最开始其实我不屑于看什么模板,感觉这些用if else 语句都可以解决,但多做了几道发现if else语句会让你的代码变得非常的臃肿,而且有一种面向测试用例编程的感觉,所以在在这里我想斗胆给各位好好讲一下二分查找算法

查找左端点

请添加图片描述

  • 首先,这里我们将区间分为小于和大于等于,这样二段性就出来了,你可能会问,为什么不划分为小于等于和大于这两个区间,因为我们查找的是左端点,划分为小于等于和大于还怎么找左端点

算法原理

  1. x  < t(target) left = mid +1 (这里可以=mid+1因为左区间划分是小于,所以最终结果一定不在左区间,所以left = mid + 1)
  1. x >= t  right = mid (这里不可以是 right = mid-1)因为如果right = mid-1的话很可能会出现right超出区间的情况,这样就会导致没法判断到结果

细节处理

  • 循环条件:

    • left < right

    为什么不是left <= right,大家可以看下图,如果此时ret > target这是就会执行第二种语句,right=mid,那就会造成死循环

请添加图片描述

  • 找中点的操作

    mid = left + (right-left)/2 这种情况是如果只有两个元素会找左边的那一个

    为什么不是 mid = left + (right-left+1)/2

    大家看下图如果是找右边的且nums[right]>=t那不是又会出现死循环吗。

请添加图片描述

寻找右端点

  • 这里的基本操作都是一样的,出了找中点还有算法(left与right的移动)不一样,所以不多赘述,各位可以自行画图处理,下面给大家一个模板,大家可以参考。

请添加图片描述

完整代码

class Solution {
public:
    //二分查找算法不一定是要使用严格的升序或者降序,只要区间可以划分为二段性就可以使用
    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.empty()) return{-1, -1};
        //其实可以分别寻找第一个位置和最后一个位置
        int left = 0, right = nums.size()-1, sz = nums.size(), mid = 0, begin = 0;
        //寻找左边界
        while(left < right){
            mid = left + (right-left)/2;

            if(nums[mid] >= target) right = mid;
            if(nums[mid] < target) left = mid+1;
        }
        //判断
        if(nums[left] != target) return {-1, -1};
        begin = left;

        //寻找右边界
        right = nums.size()-1;
        while(left < right){
            mid = left + (right-left+1)/2;

            if(nums[mid] > target) right = mid-1;
            if(nums[mid] <= target) left = mid;
        }
        return {begin, right};
    }
};
  • 12
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
EMD正交性指标是用来评估两个独立的经验模态分解(EMD)组分之间正交性的指标。其计算公式为: $$ O = \frac{\sum_{i=1}^{n}\sum_{j=1}^{m}\langle IMF_i, IMF_j\rangle^2}{\left(\sum_{i=1}^{n}\sum_{j=1}^{m}\langle IMF_i, IMF_i\rangle^2\right)^{1/2}\left(\sum_{i=1}^{n}\sum_{j=1}^{m}\langle IMF_j, IMF_j\rangle^2\right)^{1/2}} $$ 其中 $IMF_i$ 和 $IMF_j$ 分别表示第 $i$ 和第 $j$ 个独立的经验模态分解组分,$\langle\cdot,\cdot\rangle$ 表示内积运算,$n$ 和 $m$ 分别表示两个独立的经验模态分解组分的数量。 下面是Python实现代码: ```python import numpy as np def emd_orthogonality(imfs1, imfs2): """ 计算两个独立的经验模态分解组分之间的EMD正交性指标. :param imfs1: array-like, shape (n_imfs1, n_samples) 第一个独立的经验模态分解组分. :param imfs2: array-like, shape (n_imfs2, n_samples) 第二个独立的经验模态分解组分. :return: float EMD正交性指标. """ n_imfs1 = imfs1.shape[0] n_imfs2 = imfs2.shape[0] # 计算内积矩阵 inner_products = np.zeros((n_imfs1, n_imfs2)) for i in range(n_imfs1): for j in range(n_imfs2): inner_products[i, j] = np.dot(imfs1[i], imfs2[j]) # 计算EMD正交性指标 numerator = np.sum(inner_products ** 2) denominator = np.sqrt(np.sum(inner_products ** 2)) * np.sqrt(np.sum(inner_products ** 2, axis=0)) return numerator / denominator ``` 其中 `imfs1` 和 `imfs2` 分别表示两个独立的经验模态分解组分矩阵,其每一行对应一个经验模态分解组分,每一列对应一个样本点。函数返回计算得到的EMD正交性指标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值