Day 2 数组拓展:904. 水果成篮, 76. 最小覆盖子串, 54. 螺旋矩阵, 48. 旋转图像; 数组总结

904. 水果成篮

  • 思路
    • example
    • 两个篮子,返回你可以收集的水果的 最大 数目
    • 等价于“最长的含两个不同数字的连续子序列长度”
    • Two Pointer, Sliding Window, -->-->
      • left, right = 0, 0
      • use hash, i.e., dict to record the fruits
      • dict[num] = freq
      • len(dict) is always <= 2
      • [left, right] is feasible if len(dict) <= 2,左闭右闭,可行窗口
  • 注意最大最小的处理逻辑不同。

本题

遍历 right:
    处理right
    循环收缩left找到可行窗口
    处理可行窗口
  • 复杂度. 时间:O(n), 空间: O(1)
class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        n = len(fruits)
        left, right = 0, 0
        basket = collections.defaultdict(int)
        res = 0
        while right < n:
            # "add"/test current fruit into the basket
            basket[fruits[right]] += 1
            # then check the feasibility
            while len(basket) > 2: # more than 2 types of fruits, [left, right] is not feasible
                # move left
                basket[fruits[left]] -= 1
                if basket[fruits[left]] == 0:
                    del basket[fruits[left]] # need to del this otherwise we could not use len(basket)
                left += 1
            # [left, right] is feasible, update res
            res = max(res, right - left + 1)
            # move right
            right += 1
        return res
  • try this
import collections
dict1 = collections.defaultdict(int)
print(dict1)
print(dict1[2])
print(len(dict1))
print(dict1[3])
print(len(dict1))
print(dict1)

76. 最小覆盖子串

  • 思路
    • example
    • 等价于“最短的连续子串(包含t)"
    • sliding window, -->-->
      • left, right = 0, 0
      • two hashes, cnt_s, cnt_t, "cnt[ch] = freq"
      • feasible window [left, right]
        • valid == len(t) (valid always <= len(t))
        • it's possible that cnt_s[ch] > cnt_t[ch] for some ch in s[left: right+1]
      • once find a feasible window, keep moving left to update the result (needs smallest substring)
      • Key: for a feasible window, cnt_s[s[right]] is exactly equal to cnt_t[s[right]]
hash: cnt_s (变化),cnt_t (不变)
valid记录当前窗口含有t元素的个数。(valid 最大值n)
遍历right:
    处理right (更新cnt_s, valid)
    如果窗口可行(size=n), 循环收缩left找到满足要求的最小窗口 (更新cnt_s, valid, 答案)
  • 复杂度. 时间:O(n), 空间: O(1)
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        m, n = len(s), len(t)
        if m < n:
            return ''
        # fix cnt_t
        cnt_t = collections.defaultdict(int) 
        for ch in t:
            cnt_t[ch] += 1
        #
        cnt_s = collections.defaultdict(int) 
        left, right = 0, 0
        valid = 0
        start, end = 0, -1
        min_len = float('inf') # smallest length of feasible window
        while right < m:
            ch = s[right]
            cnt_s[ch] += 1
            if cnt_s[ch] <= cnt_t[ch]: # add one valid char
                valid += 1
            while valid == n: # [left, right] is a feasible, keep moving left to find the smallest window
                cur_len = right - left + 1
                if cur_len < min_len:
                    min_len = cur_len
                    start, end = left, right # record
                cnt_s[s[left]] -= 1
                if cnt_s[s[left]] < cnt_t[s[left]]: # cnt_t[s[left]] is at least 0 (defaultdict)
                    valid -= 1
                left += 1
            # move right
            right += 1
        return s[start:end+1]
  • version 2: 每一步都把left指针移动到“最佳“位置。
    • Key: for a feasible window, cnt_s[s[left]] is exactly equal to cnt_t[s[left]]
hash: cnt_s (变化),cnt_t (不变)
valid记录当前窗口含有t元素的个数。(valid 最大值n)
遍历right:
    处理right (更新cnt_s, valid)
    循环收缩left直到左边界处在最佳位置 (cnt_s[s[left]] == cnt_t[s[left]]),结束后得到“预可行”窗口(valid < n)
    如果窗口可行,更新最小值
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        m, n = len(s), len(t)
        if m < n:
            return ''
        # fix cnt_t
        cnt_t = collections.defaultdict(int) 
        for ch in t:
            cnt_t[ch] += 1
        #
        cnt_s = collections.defaultdict(int) 
        left, right = 0, 0
        valid = 0
        start, end = 0, -1
        min_len = float('inf') # smallest length of feasible window
        while right < m:
            ch = s[right]
            cnt_s[ch] += 1
            if cnt_s[ch] <= cnt_t[ch]: # add one valid char
                valid += 1
            # keep moving left to remove the unnecessary char, until cnt_s[s[left]] == cnt_t[s[left]] 
            while left <= right and cnt_s[s[left]] > cnt_t[s[left]]:
                cnt_s[s[left]] -= 1
                left += 1
            # check feasibility
            if valid == n: # now [left, right] will be the shortest feasible substring 
                cur_len = right - left + 1
                if cur_len < min_len:
                    min_len = cur_len 
                    start, end = left, right 
            # move right
            right += 1
        return s[start:end+1]

54. 螺旋矩阵

  • 思路
    • example
    • size of matrix: m \times n
    • slightly change the update style inside the loop
      • 贪心策略:右,下,左,上。每个方向都尽可能搜索,这样可以方便处理单行单列的情况。
    • deal with the boundary case (eg., one row, one column)
    • should work for m==n case
  • 复杂度. 时间:O(n^2), 空间: O(1)
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        m, n = len(matrix), len(matrix[0])
        top, bottom = 0, m-1
        left, right = 0, n-1
        res = []
        while top <= bottom and left <= right:
            #-->
            for j in range(left, right+1):
                res.append(matrix[top][j])
            # downward (right column)
            for i in range(top+1, bottom+1):
                res.append(matrix[i][right])
            #<--
            if top < bottom and left < right: # extra row or column updates
                for j in range(right-1, left-1, -1):
                    res.append(matrix[bottom][j])
                for i in range(bottom-1, top, -1):
                    res.append(matrix[i][left])
            # update indices
            top += 1
            bottom -= 1
            left += 1
            right -= 1
        return res

48. 旋转图像

  • 思路
    • example
    • size of matrix: n \times n

先按主对角线翻转
再每一行进行翻转



class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        def reverse(nums):
            n = len(nums)
            left, right = 0, n-1
            while left < right:
                nums[left], nums[right] = nums[right], nums[left]
                left += 1
                right -= 1
        # step 1
        n = len(matrix)
        for i in range(n):
            for j in range(i+1, n):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
        # step 2
        for i in range(n):
            reverse(matrix[i])

数组总结

  1. 二分搜索
  • 左闭右闭
  • 左闭右开
  1. 双指针
  • 快慢,前后, 。。。
  • 滑动窗口
    • 同向移动 -->-->
    • left, right 初始化
    • 外层循环:right
    • 内层:left
    • 判断当前窗口可行性,移动left
      • 计数
      • hash技术
    • 滑动窗口:本质是满足了单调性,即左右指针只会往一个方向走且不会回头。收缩的本质即去掉不再需要的元素。也就是做题我们可以先固定移动右指针,判断条件是否可以收缩左指针算范围。大家可以好好理解一下。From 芒果冰
    • <--*-->
    • -->*<--
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容