Leetcode【227、468、848、1081】

问题描述:【Stack】227. Basic Calculator II
解题思路:

这道题是实现一个基本计算器,即给一个只包括 +、-、*、/、数字和空格的字符串,计算结果。

这道题很容易想到用栈来记录结果。根据“先乘除,后加减”的原则,没有遇到乘除法之前,数字和 +、- 都入栈。遇到乘除号,在栈中找第一个因子,并在字符串中往后找第二个因子,将两者相乘除的结果压入栈中。最后,栈中就只剩下加减法了。然后对栈从头遍历,从左到右计算加减法即可得到最终答案。

这道题代码虽然比较长,但写起来不难,注意字符串和数字之间的转化即可。

Python3 实现:
class Solution:
    def calculate(self, s: str) -> int:
        stack = []
        i = 0
        while i < len(s):
            if s[i] != ' ':
                stack.append(s[i])
                # 先做乘除法,并将结果压入栈
                if s[i] == '*' or s[i] == '/':
                    num1, num2, op = 0, 0, stack.pop()
                    # 从栈中计算第一个乘法或除法因子
                    cnt = 0
                    while stack and stack[-1].isdigit():
                        num1 += int(stack.pop()) * (10 ** cnt)
                        cnt += 1
                    # 计算第二个乘法或除法因子,往后遍历
                    j = i + 1
                    while j < len(s):
                        if s[j] != ' ':
                            if s[j].isdigit():
                                num2 = num2 * 10 + int(s[j])
                            else:
                                break
                        j += 1
                    # 将结果压入栈中
                    if op == '*':
                        stack.append(str(num1 * num2))
                    else:
                        stack.append(str(num1 // num2))
                    i = j
                    continue
            i += 1
        # 栈中只有加减法
        i, ans, op = 0, 0, ''
        while i < len(stack):
            if stack[i] == '+' or stack[i] == '-':
                op = stack[i]
            else:
                if op == '':
                    ans = ans * 10 + int(stack[i])
                else:
                    # 从栈中得到第二个加数或减数
                    j, num2 = i, 0
                    while j < len(stack):
                        if stack[j].isdigit():
                            num2 = num2 * 10 + int(stack[j])
                        else:
                            break
                        j += 1
                    # 结果累加或累减
                    if op == '+':
                        ans += num2
                    else:
                        ans -= num2
                    i = j
                    continue
            i += 1
        return ans  # 最终的结果

问题描述:【String】468. Validate IP Address
解题思路:

这道题给一个字符串,判断其是否是有效的 IPv4 地址或者是 IPv6 地址。

这题只要认真读题,没有任何难度。可以根据字符串中是否含有 "." 或者 ":" 来分为可疑 IPv4 和可疑 IPv6,然后写两个函数分别判断即可。对于每个函数,遇到非法的情况就返回 "Neither",那么剩下的就是合法的 IPv4 和 IPv6 地址了。

Python3 实现:
class Solution:
    def validIPAddress(self, IP: str) -> str:
        def validIPV4(IP):
            groups = IP.split(".")
            if len(groups) != 4:
                return "Neither"
            for group in groups:
                if len(group) > 1 and group[0] == '0':  # 不能包含前导0
                    return "Neither"
                if group.isdigit() == False:  # 空串和负数也包括在这种情况
                    return "Neither"
                if int(group) > 255:
                    return "Neither"
            return "IPv4"
                
        def validIPV6(IP):
            groups = IP.split(":")
            if len(groups) != 8:
                return "Neither"
            for group in groups:
                if len(group) == 0:
                    return "Neither"  # 防止::情况出现 
                if len(group) > 4:
                    return "Neither"
                for g in group:  # 含有其他字符
                    if g not in "0123456789abcdefABCDEF":
                        return "Neither"
            return "IPv6"
            
        if IP.find('.') != -1:
            return validIPV4(IP)
        elif IP.find(':') != -1:
            return validIPV6(IP)
        else:
            return "Neither"

问题描述:【String】848. Shifting Letters
解题思路:

这道题是给一个字符串 S 和数组 shifts,将 S 中前 i+1 个字母移位 shifts[i] 次,返回移位后的字符串。

观察所给的例子,shifts = [3,5,9],"abc" -> "rpl",其中 "a" 移动了 3+5+9 次,"b" 移动了 5+9 次,"c" 移动了 9 次。

因此,我们只需要重新构造 shifts,将其每一项 shift[i] 变成 shifts[i] 与后面项的累加值之和。然后,对于 S 中的每个字符,移动 shifts[i] 就是答案。时间复杂度为 O(n),空间复杂度为 O(1)。

注意:循环移动,写代码时要对总移动数进行 %26 操作,防止字符越界。

Python3 实现:
class Solution:
    def shiftingLetters(self, S: str, shifts: List[int]) -> str:
        for i in range(len(shifts)-2, -1, -1):
            shifts[i] += shifts[i+1]
        ans = ""
        for s, shift in zip(S, shifts):
            ans += chr(ord('a') + (ord(s) - ord('a') + shift) % 26)
        return ans

问题描述:【Stack】1081. Smallest Subsequence of Distinct Characters
解题思路:

这道题是返回字符串 text 中按字典序排列最小的子序列,该子序列包含 text 中所有不同字符一次。

此题可以使用栈来保存结果。如果字符单调递增,就依次入栈;否则就要看已经在栈中的字符将来还有没有可能再次出现,如果还会出现,就把栈中字符依次删去

以 text = cdadabcc 为例,算法过程如下:

这是一种贪心的思想,栈中总是维持最小的字典序,局部最优则全局最优。时间复杂度为 O(n),空间复杂度为 O(26) (最多保存26个小写字母)。

Python3 实现:
class Solution:
    def smallestSubsequence(self, text: str) -> str:
        dic = dict()  # 记录每个字符最后的位置
        for i in range(len(text)):
            dic[text[i]] = i
        stack = []
        for i in range(len(text)):
            if text[i] in stack:  # 已经在栈中出现过,跳过
                continue
            # 对于栈中每个大于text[i]的字符,如果之后还会出现,就弹出
            while stack and stack[-1] > text[i] and dic[stack[-1]] > i:
                stack.pop()
            stack.append(text[i])  # 判断完成后,将当前字符入栈
        return "".join(stack)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容