zoukankan      html  css  js  c++  java
  • 数据结构与算法分析(1)

    1. 最大子序列和的问题

    输入样例:4 -3 5 -2 -1 2 6 -2
    输出:11

    1.1 二分法递归求解 - 时间复杂度:O(NlogN)

    int getMax3 (int a, int b, int c)
    {
        int max = a;
        if (max < b)
            max = b;
        if (max < c)
            max = c;
        return max;
    }
    int getMaxSum(const vector<int> &arr, int bgn, int end)
    {
        if (bgn >= end)
            return 0;
        int mid = (bgn + end) / 2;
        int leftMaxSum = getMaxSum(arr, bgn, mid);
        
        //此处的起始位置应设置为mid + 1,否则会造成无限递归
        int rightMaxSum = getMaxSum(arr, mid + 1, end);
        
        int leftMaxBorder = 0, leftTmp = 0;
        for (int i = mid; i >= bgn; --i)
        {
            leftTmp += arr[i];
            if (leftTmp > leftMaxBorder)
                leftMaxBorder = leftTmp;
        //    if (leftTmp < 0)    //这个地方不能提前退出,必须完全遍历
        //        break;
        }
        int rightMaxBorder = 0, rightTmp = 0;
        for (int i = mid + 1; i < end; ++i)
        {
            rightTmp += arr[i];
            if (rightTmp > rightMaxBorder)
                rightMaxBorder = rightTmp;
        //    if (rightTmp < 0)
        //        break;
        }
        return getMax3(leftMaxSum, rightMaxSum, leftMaxBorder + rightMaxBorder);
    }

    1.2 一次性遍历求解 - 时间复杂度:O(N)

    int getMaxSubSum(const vector<int> &arr, int bgn, int end)
    {
        int maxSum = 0;
        int sumTmp = 0;
        for (int i = bgn; i < end; ++i)
        {
            sumTmp += arr[i];
            if (sumTmp > maxSum)
                maxSum = sumTmp;
            else if (sum < 0)
                sumTmp = 0;
        }
        return maxSum;
    }

    2. 算法时间复杂度为O(logN)的典型问题:

    2.1 对分查找(binary search) - 时间复杂度:(<= log2N)

    int binSearch(const vector<int> &arr, int bgn, int end, int target)  //end-尾元素后一位置
    {
        int ret = -1;
        while (bgn < end)
        {
            int mid = (bgn + end) / 2;
            if (target == arr[mid])
            {
                ret = mid;
                break;
            }
            else if (target > arr[mid])
                bgn = mid + 1;
            else    
                end = mid;
        }
        return ret;
    }

    2.2 两个整数最大公约数求解(欧几里德算法) - 时间复杂度:(<= 2logN)

    unsigned int getGCD(unsigned int m, unsigned int n)
    {
        while (n > 0)
        {
            int rem = m % n;
            m = n;
            n = rem;
        }
        return m;
    }

      这里其实运用了递归的思想:m与n的最大公因子即是n与rem(m%n)的最大公因子...,那么,只需要说明n与rem的最大公因子就是m与n的最大公因子即可使这个递归进行下去。所以问题是n与rem的最大公因子为什么就是m与n的最大公因子?

    思路:假设m > n,又即使m < n,经过一次遍历后有m > n,m与n的最大公因子是A,则m = xA, n = yA。
       rem = m%n -> m-zn(z = m/n),当rem=0,n即是两者的最大公因子;rem>0,rem=xA - zyA,很显然rem%A = 0
      -> m与n的最大公因子即是n与rem的最大公因子,以此类推

    2.3 幂运算 - 时间复杂度:(<= 2logN)

    long long pow(long long x, unsigned int n)
    {
        if (0 == n)
            return 1;
        if (n % 2)
            return pow( x*x, n/2 ) * x;
        else
            return pow( x*x, n/2 );
    }

      以2^15为输入,则恰需要 2log(15) = 6 次乘法运算
      以2^16为输入,则仅需要 4+1(<2log(16)=8) 次乘法运算,也可以修改下代码添加出口判断(if (1 == n))使之成为4次乘法运算,不过需要每次进入pow多判断一次

      PS: 1. 书上以2^62为例,共需9次乘法运算,但所推演算法过程个人觉得有问题。实际过程应该是首先层层运算pow入口参数x*x的值,直至n == 0。然后,再逆序层层计算pow*x的值,直至算法结束运算
        2. 代码中语句pow( x*x, n/2 )可以用pow( x, n/2 )*pow( x, n/2 )代替,但是效率会非常低,因其进行了大量的重复性工作

    点滴记录 点滴成长 未雨绸缪 不乱于心
  • 相关阅读:
    原型链
    原型规则总结
    使用typeof能得到的哪些类型
    eslint 规则中文注释
    两张图片互相切换
    输入框获得焦点与失去焦点、阴影效果
    vue 写table的几种方式
    vue 注意事项
    angular 接口定义封装
    @NgModule
  • 原文地址:https://www.cnblogs.com/Glory-D/p/7562907.html
Copyright © 2011-2022 走看看