2、常见基础算法原理

1、贪心算法

贪心算法的指导思想是:每一步下的最优,也就是局部最优,一定情况下逼近全局最优。

对应刷题:买卖股票的最佳时机

(1)给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

class Solution:

    def maxProfit(self, prices: List[int]) -> int:

        #贪心算法

        max1=0

        k=len(prices)

        for i in range(1,k):

            max1=max1+max((prices[i]-prices[i-1]),0)

        return max1

(2)给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

class Solution:

    def maxProfit(self, prices: List[int]) -> int:

       if len(prices)<=1:

            return 0

       else:

        result=0

        min1=prices[0]

        for i in range(1,len(prices)):

            if prices[i]<min1:

                min1=prices[i]

            result=max(result,prices[i]-min1)

        return result

(3)中等 跳跃游戏

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个位置。

class Solution:

    def canJump(self, nums: List[int]) -> bool:

        mostright=0

        for i in range(len(nums)):

               if i<=mostright:

                   mostright=max(mostright,i+nums[i])

                   if mostright>=len(nums)-1:

                       return True

        return False

2、动态规划

用一句话解释动态规划就是 “记住你之前做过的事”,如果更准确些,其实是 “记住你之前得到的答案”。

动态规划解题四个步骤:

问题拆解,找到问题之间的具体联系

状态定义

递推方程推导

实现(初始化)

典型例题1:爬楼梯LeetCode 第 70 号问题:爬楼梯。

假设你正在爬楼梯。需要 n阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

时间优,空间不优。

class Solution:

    def climbStairs(self, n: int) -> int:

        reslut=[]

        reslut.append(1)

        reslut.append(2)

        for i in range(2,n):

             reslut.append(reslut[i-1]+reslut[i-2])

        return reslut[n-1]

典型例题2:LeetCode 第 53 号问题:最大子序和。

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

class Solution:

    def maxSubArray(self, nums: List[int]) -> int:

        smax=nums[0]

        tmp=nums[0]

        for i in range(1,len(nums)):

            tmp=max(tmp,0)

            smax=max(nums[i]+tmp,smax)

            tmp=tmp+nums[i]

        return smax

典型例题3:

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

class Solution:

    def rob(self, nums: List[int]) -> int:

       if len(nums)==0:

            return 0

       else:

        if len(nums)<=2:

            return max(nums)

        else:

            first=nums[0]

            second=max(nums[0],nums[1])

            for i in range(2,len(nums)):

                nums[i]=max(first+nums[i],second)

                first=second

                second=max(first,nums[i])

            return nums[len(nums)-1]

通过这几个简单的例子,相信你不难发现,解动态规划题目其实就是拆解问题,定义状态的过程,严格说来,动态规划并不是一个具体的算法,而是凌驾于算法之上的一种 思想

这种思想强调的是从局部最优解通过一定的策略推得全局最优解,从子问题的答案一步步推出整个问题的答案,并且利用空间换取时间。从很多算法之中你都可以看到动态规划的影子,所以,还是那句话 技术都是相通的,找到背后的本质思想是关键

参考网址:https://www.cxyxiaowu.com/6781.html

3、分治思想

分治策略:对于一个规模为 n 的问题,将其分解为 k 个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。

关键点:递归地解子问题,合并得到原问题的解,归并排序的典型思路。

典型例题1:二分查找。

x 的平方根:实现 int sqrt(int x) 函数。计算并返回 x 的平方根,其中 x 是非负整数。由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

class Solution:

    def mySqrt(self, x: int) -> int:

                l=0

                r=x

                ans=-1

                while l<=r:

                    m=int((l+r)/2)

                    if m*m<=x:

                        ans=m

                        l=m+1

                    else:

                        r=m-1

                return ans

典型例题2:归并排序。

归并排序,两路已经有序,合并成一路,关键点:如果两个数组是有序的,则可以便捷地计算两个数组的交集。

首先对两个数组进行排序,然后使用两个指针遍历两个数组。

初始时,两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,将该数字添加到答案,并将两个指针都右移一位。当至少有一个指针超出数组范围时,遍历结束。

给定两个数组,编写一个函数来计算它们的交集。

classSolution: defintersect(self, nums1: List[int], nums2: List[int])-> List[int]: nums1.sort()

        nums2.sort()

        result=[]

        length1=len(nums1)

        length2=len(nums2)

        index1=0        index2=0        while index1<length1 and index2<length2:

            if nums1[index1]<nums2[index2]:

                index1=index1+1            

            elif nums1[index1]>nums2[index2]:

                  index2=index2+1            

            else:

                  result.append(nums1[index1])

                  index1=index1+1                  

                   index2=index2+1        

          return result

归并排序:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。即先划分为两个部分,最后进行合并。

典型例题3:977. 有序数组的平方

给定一个按非递减顺序排序的整数数组 A,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。

low一点的版本:

class Solution:

    def sortedSquares(self, A: List[int]) -> List[int]:

        length=len(A)

        if length==0:

            return A

        else:

            result=[]

            l=0

            r=length-1

            while l<=r:

                tmp1=A[l]*A[l]

                tmp2=A[r]*A[r]

                if tmp1<tmp2:

                    result.insert(0,tmp2)

                    r=r-1

                elif tmp1>tmp2:

                    result.insert(0,tmp1)

                    l=l+1

                else:

                    result.insert(0,tmp1)

                    if l!=r:

                       result.insert(0,tmp2)

                    l=l+1

                    r=r-1

        return  result

优化后的版本:

class Solution:

    def sortedSquares(self, A: List[int]) -> List[int]:

        length=len(A)

        if length==0:

            return A

        else:

            result=[]

            l=0

            r=length-1

            while l<=r:

                tmp1=A[l]*A[l]

                tmp2=A[r]*A[r]

                if tmp1<tmp2:

                    result.insert(0,tmp2)

                    r=r-1

                else:

                    result.insert(0,tmp1)

                    l=l+1

        return  result

典型例题3:快速排序。

快速排序的基本思想:当前待排序的无序区为 A[low..high] ,利用分治法可将快速排序的基本思想描述为:

(1)分解:

在A[low..high]中任选一个记录作为基准(pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1) 和 R[pivotpos+1..high] ,并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字 pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置( pivotpos )上,它无须参加后续的排序。

(2)求解:

通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。

(3)合并:

因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。

总结分析:

分治法将规模为 n 的问题分成 k 个规模为 n/m 的子问题去解。设分解阀值 n0 = 1 ,且 adhoc 解规模为 1 的问题耗费 1 个单位时间。再设将原问题分解为 k 个子问题以及用 merge 将 k 个子问题的解合并为原问题的解需用 f(n) 个单位时间。用T(n)表示该分治法解规模为 |P| = n 的问题所需的计算时间,则有:

  T(n)= k T(n/m) + f(n)

4、递归算法

先下定义:递归算法是一种直接或者间接调用自身函数或者方法的算法。

通俗来说,递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解。它有如下特点:

1. 一个问题的解可以分解为几个子问题的解

2. 这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样

3. 存在递归终止条件,即必须有一个明确的递归结束条件,称之为递归出口。

典型例题1:汉诺塔问题


5、回溯算法



待补充:

查找算法

排序算法

搜索算法

字符串匹配算法

接下来是各种数据结构:

线性表、散列表、树、图


参考资料:

内容来自:https://zhuanlan.zhihu.com/p/137041568

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351