算法学习之路(一)

1、买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

class Solution:
    def maxProfit(self, prices: list[int]) -> int:
        length = len(prices)
        if len == 0:
            return 0
        have = [0] * length  # 表示第i天持有股票所得最多现金
        no = [0] * length  # 表示第i天不持有股票所得最多现金
        have[0] = -prices[0]  # 此时的持有股票就一定是买入股票了
        no[0] = 0  # 不持有股票那么现金就是0
        for i in range(1, length):
            have[i] = max(have[i - 1], -prices[i])
        #   have[i] = max(have[i-1], no[i-1] - prices[i]) (买卖股票的最佳时机2)
            no[i] = max(no[i - 1], prices[i] + have[i - 1])
        return no[-1]


if __name__ == '__main__':
    solu = Solution()
    prices = [7,1,5,3,6,4]
    print(solu.maxProfit(prices))

2、买卖股票的最佳时机 2

给定一个数组 prices ,其中 prices[i] 表示股票第 i 天的价格。

在每一天,你可能会决定购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以购买它,然后在 同一天 出售。
返回 你能获得的 最大 利润 。

示例 1:

输入: prices = [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
示例 2:

输入: prices = [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:

输入: prices = [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

class Solution:
    def maxProfit(self, prices: list[int]) -> int:
        length = len(prices)
        if len == 0:
            return 0
        have = [0] * length  # 表示第i天持有股票所得最多现金
        no = [0] * length  # 表示第i天不持有股票所得最多现金
        have[0] = -prices[0]  # 此时的持有股票就一定是买入股票了
        no[0] = 0  # 不持有股票那么现金就是0
        for i in range(1, length):
        #   have[i] = max(have[i - 1], -prices[i])    (买卖股票的最佳时机1)
            have[i] = max(have[i-1], no[i-1] - prices[i]) 
            no[i] = max(no[i - 1], prices[i] + have[i - 1])
        return no[-1]


if __name__ == '__main__':
    solu = Solution()
    prices = [7,1,5,3,6,4]
    print(solu.maxProfit(prices))

3、买卖股票的最佳时机 3

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

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。
示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:

输入:prices = [7,6,4,3,1] 
输出:0 
解释:在这个情况下, 没有交易完成, 所以最大利润为 0。
示例 4:

输入:prices = [1]
输出:0

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if len(prices) < 2 :
            return 0       
        m = len(prices)
        buy1 = [0] * m
        sell1 = [0] * m
        buy2 = [0] * m 
        sell2 = [0] * m
        buy1[0]=buy2[0]= -prices[0]
        sell1[0]=sell2[0] = 0

        for i in range(1,m):
            buy1[i] = max(buy1[i-1],-prices[i])
            sell1[i] = max(sell1[i-1],buy1[i-1] + prices[i])
            buy2[i] = max(buy2[i-1],sell1[i-1]-prices[i])
            sell2[i] = max(buy2[i-1] + prices[i] , sell2[i-1])
        return sell2[-1]

4、整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。
 

示例 1:

输入:x = 123
输出:321
示例 2:

输入:x = -123
输出:-321
示例 3:

输入:x = 120
输出:21
示例 4:

输入:x = 0
输出:0

class Solution:
    def myAtoi(self, s: str) -> int:
        s = s.lstrip()
        res = ""
        flag = False  # 标记答案的正负
        mark = False  # 标记有没有数字被选取过了
        tag = False  # 标记有没有“+”、“-”被选取过了

        for i in s:
            if i.isdigit():
                res += i
                mark = True
            elif i == "+":
                if mark:
                    break
                if tag:
                    return 0
                tag = True
            elif i == "-":
                if mark:
                    break
                if tag:
                    return 0
                flag = True
                tag = True
            else:
                break

        if len(res) == 0:
            return 0
        else:
            res = int(res)
            if flag:
                res = -res
            if res > 2 ** 31 - 1:
                return 2 ** 31 - 1
            elif res < -2 ** 31:
                return -2 ** 31
            else:
                return res


if __name__ == '__main__':
    s = '+-12'
    solu = Solution()
    try:
        print(solu.myAtoi(s))
    except Exception as e:
        print(e.args)

5、实现 Str()函数

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回  -1 。

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。

示例 1:

输入:haystack = "hello", needle = "ll"
输出:2
示例 2:

输入:haystack = "aaaaa", needle = "bba"
输出:-1
示例 3:

输入:haystack = "", needle = ""
输出:0

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        def strStr(self, haystack, needle):
            a, b = len(needle), len(haystack)
            if a == 0: return 0
            # 1、求next数组
            nxt = self.getnext(needle)
            # 2、模式匹配
            p = -1
            for j in range(b):
                while p >= 0 and needle[p + 1] != haystack[j]:
                    p = nxt[p]
                if needle[p + 1] == haystack[j]:
                    p += 1
                if p == a - 1:
                    return j - a + 1
            return -1
            # 求next数组

        def getnext(self, needle):
            nxt = [-1] * len(needle)
            j = -1
            for i in range(1, len(needle)):
                while (j >= 0 and needle[j + 1] != needle[i]):
                    j = nxt[j]
                if needle[j + 1] == needle[i]:
                    j += 1
                nxt[i] = j
            return nxt


if __name__ == '__main__':
    s = "mississippi"
    n = "issip"
    solu = Solution()
    try:
        print(solu.strStr(s, n))
    except Exception as e:
        print(e.args)

6、外观数列

给定一个正整数 n ,输出外观数列的第 n 项。

「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。

你可以将其视作是由递归公式定义的数字字符串序列:

countAndSay(1) = "1"
countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。
前五项如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221
第一项是数字 1 
描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"
要 描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。要将描述转换为数字字符串,先将每组中的字符数量用数字替换,再将所有描述组连接起来。

例如,数字字符串 "3322251" 的描述如下图:

示例 1:

输入:n = 1
输出:"1"
解释:这是一个基本样例。
示例 2:

输入:n = 4
输出:"1211"
解释:
countAndSay(1) = "1"
countAndSay(2) = 读 "1" = 一 个 1 = "11"
countAndSay(3) = 读 "11" = 二 个 1 = "21"
countAndSay(4) = 读 "21" = 一 个 2 + 一 个 1 = "12" + "11" = "1211"

class Solution:
    def countAndSay(self, n: int) -> str:
        pre = ''
        cur = '1'

        # 从第 2 项开始
        for _ in range(1, n):
            # 这里注意要将 cur 赋值给 pre
            # 因为当前项,就是下一项的前一项。有点绕,尝试理解下
            pre = cur
            # 这里 cur 初始化为空,重新拼接
            cur = ''
            # 定义双指针 start,end
            start = 0
            end = 0
            # 开始遍历前一项,开始描述
            while end < len(pre):
                # 统计重复元素的次数,出现不同元素时,停止
                # 记录出现的次数,
                while end < len(pre) and pre[start] == pre[end]:
                    end += 1
                # 元素出现次数与元素进行拼接
                cur += str(end - start) + pre[start]
                # 这里更新 start,开始记录下一个元素
                start = end

        return cur


if __name__ == '__main__':
    n = 4
    solu = Solution()
    try:
        print(solu.countAndSay(n))
    except Exception as e:
        print(e.args)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值