• 二分查找模板


    二分法模板
    链接:https://blog.csdn.net/qq_19446965/article/details/82184672
    
    • 循环条件到底哪一个?
    	• start <= end
    	• start < end
    	• start + 1 < end
    • 指针变换到底哪一个
    	• start = mid
    	• start = mid + 1
    	• start = mid - 1
    
    弄不好就死循环,弄不好边界就失误
     
    例:nums = [1,1], target = 1
    使用start < end 会出现死循环
    
    模板:
    def bin_search(nums, target):
        if not nums or target < nums[0] or target > nums[-1]:
            return -1
     
        left = 0
        right = len(nums) - 1
        while left + 1 < right:      # 统一都用 <
            mid = left + (right - left)//2
            if target > nums[mid]:    # 左边界> 右边界>=
                left = mid            # 永远不动,全文通用
            elif target < nums[mid]:
                right = mid           # 永远不动,全文通用
            else:
                return mid            # 等号可以合并到 < 或 > 也可以单独考虑
     
        if nums[right] == target:
            return right
        if nums[left] == target:
            return left
     
        return -1                     # 较小的left,较大的righ
    		
    总结:
    1.判断是返回left,还是返回right
         因为我们知道最后跳出while (left + 1< right)循环条件是left+ 1 == right。
         最后left 和right一定是卡在"边界值"的左右两边
         以数组{1, 2, 3, 3, 4,5}为例,
         如果需要查找第一个等于或者小于3的元素下标,我们比较的key值是3,则最后left和right需要满足以下条件:
         left——>2, right ——>3
         我们比较的key值是3,所以此时我们需要返回left。
    
        所以,最后只需要判断left或right是否等于target即可。
    2.判断出比较符号
         左边界附近都是>
         右边界附近都>=
    
    ————————————————
    模板讲解:https://blog.csdn.net/qq_19446965/article/details/82184672
    模板套用练习题1:https://www.cnblogs.com/rnanprince/p/11743414.html
    二分查找(倍增法):https://blog.csdn.net/qq_19446965/article/details/102811021
    模板套用练习题2:https://www.cnblogs.com/rnanprince/p/11761940.html
    
    
    倍增:
    二分查找(倍增法):https://blog.csdn.net/qq_19446965/article/details/102811021
    
    首先特判一下首个元素. 然后设定 idx = 0 为查找的下标, jump = 1 为向后跳跃的长度.
    
    每次循环将 idx 向后移动 jump 个元素, 并将 jump 翻倍. 而如果移动后的位置不小于 target, 则 jump 缩小至一半.
    
    即我们在保证每次跳跃后的 idx 的位置都小于target的前提下, 倍增式地跳跃, 以此保证 O(logn) 的时间复杂度.
    
    循环终止的条件就是 jump == 0, 就是说, 这时 idx + 1 的位置以及不小于 target 了 (此时idx位置的仍然是小于target)
    
    也就是说, 到最后idx指向的元素是: 最大的小于target的元素. 返回答案前判断一下 idx + 1 是否 target 即可.
    ————————————————
    
    辗转相除法:
     又名欧几里德算法, 是求最大公约数的一种方法。它的具体做法是:用较大的数除以较小的数,再用除数除以出现的余数(第一余数),再用第一余数除以出现的余数(第二余数),如此反复,直到最后余数是0为止。如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。
     
     def gcd(big, small):
        if small != 0:
            return gcd(small, big % small)
        else:
            return big
    
    ————————————————
    
    快速幂算法
    计算x的n次方, 即计算x^n。
    
    由公式可知: x^n = x^{n/2} * x^{n/2}。
    
    如果我们求得x^{n/2}, 则可以O(1)求出x^n, 而不需要再去循环剩下的n/2次。
    
    以此类推,若求得x^{n/4}, 则可以O(1)求出x^{n/2}
     。。。。
    因此一个原本O(n)的问题,我们可以用O(logn)复杂度的算法来解决。
    
    递归版本的快速幂算法
    def power(x, n):
        if n == 0:
            return 1
        
        if n % 2 == 0:
            tmp = power(x, n // 2)
            return tmp * tmp
        else:
            tmp = power(x, n // 2)
            return tmp * tmp * x
    
    非递归版本
    def power(x, n):
        ans = 1
        base = x
        while n > 0:
            if n % 2 == 1:
                ans *= base
            base *= base
            n = n // 2
        return ans
    ————————————————
    
    斐波那契数列-求第n项
    非递归版
    def fibonacci(n):
        res = [0, 1]
        while len(res) <= n:
            res.append(res[-1]+res[-2])
        return res[n]
    
    递归版
    def fibonacci(n):
        if n == 0:
            return 0
        if n == 1 or n == 2:
            return 1
        return fibonacci(n - 1) + fibonacci(n - 2)
    题型参见:https://www.cnblogs.com/rnanprince/p/11600976.html
    

      

  • 相关阅读:
    ios 如何获得系统时间和日期
    IOS开发使用委托delegate在不同窗口之间传递数据
    集合视图UICollectionView 介绍及其示例程序
    iOS6新特征:UICollectionView介绍
    ios delegate和protocol
    iOS页面跳转及数据传递
    [转载]iOS6新特征:UICollectionView官方使用示例代码研究
    跟上潮流:十大移动应用开发平台
    UITextField 如何设置为密码方式显示?
    【转】 Android中Intent组件详解
  • 原文地址:https://www.cnblogs.com/bonelee/p/12588994.html
Copyright © 2020-2023  润新知