【leetcode刷题之路】面试经典150题(2)——双指针+滑动窗口+矩阵

这篇具有很好参考价值的文章主要介绍了【leetcode刷题之路】面试经典150题(2)——双指针+滑动窗口+矩阵。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

2 双指针

2.1 【双指针】验证回文串

题目地址:https://leetcode.cn/problems/valid-palindrome/description/?envType=study-plan-v2&envId=top-interview-150

  详见代码。

class Solution:
    def isPalindrome(self, s: str) -> bool:
        newStr = ""
        s = s.lower()
        for c in s:
            if (c >= "a" and c <= "z") or (c >= "0" and c <= "9"):
                newStr += c
        left, right = 0, len(newStr)-1
        while(left<=right):
            if newStr[left] != newStr[right]:
                return False
            left += 1
            right -= 1
        return True
2.2 【双指针】判断子序列

题目地址:https://leetcode.cn/problems/is-subsequence/description/?envType=study-plan-v2&envId=top-interview-150

  双指针挨个遍历 s s s t t t中的字符,看能否找到相对位置一致的字串。

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        s_len = len(s)
        t_len = len(t)
        s_index = 0
        if s_len == 0:
            return True
        if t_len == 0:
            return False

        for i in range(t_len):
            if s_index == s_len:
                break
            if s[s_index] == t[i]:
                s_index += 1
        if s_index == s_len:
            return True
        else:
            return False
2.3 【双指针】两数之和 II - 输入有序数组

题目地址:https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/description/?envType=study-plan-v2&envId=top-interview-150

  双指针前后遍历元素,找到合适的值。

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        left, right = 0, len(numbers)-1
        while(left < right):
            if numbers[left] + numbers[right] > target:
                right -= 1
            elif numbers[left] + numbers[right] < target:
                left += 1
            else:
                break
        return [left+1,right+1]
2.4 【双指针】盛最多水的容器

题目地址:https://leetcode.cn/problems/container-with-most-water/description/?envType=study-plan-v2&envId=top-interview-150

  木桶原理,水最多取决于左右边界更短的那个边界,所以希望最短边界尽可能长。

class Solution:
    def maxArea(self, height: List[int]) -> int:
        left, right = 0, len(height)-1
        max_water = 0
        while left < right:
            tmp_water = min(height[left],height[right])*(right-left)
            max_water = max(max_water,tmp_water)
            if height[left] <= height[right]:
                left += 1
            else:
                right -= 1
        return max_water
2.5 【双指针】三数之和

题目地址:https://leetcode.cn/problems/3sum/description/?envType=study-plan-v2&envId=top-interview-150

  先排序,然后去重,每次固定一个数,在剩下的范围中用双指针找合为0的三元组。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        length = len(nums)
        ans = []

        if length < 3:
            return ans
        
        nums.sort()
        for i in range(length):
            if nums[i] > 0:
                return ans
            if i > 0 and nums[i] == nums[i-1]:
                continue
            left = i + 1
            right = length - 1
            while left < right:
                if nums[i] + nums[left] + nums[right] == 0:
                    ans.append([nums[i],nums[left],nums[right]])
                    while left<right and nums[left] == nums[left+1]:
                        left += 1
                    while left<right and nums[right] == nums[right-1]:
                        right -= 1
                    left += 1
                    right -= 1
                elif nums[i] + nums[left] + nums[right] < 0:
                    left += 1
                else:
                    right -= 1
        return ans

3 滑动窗口

3.1 【双指针】长度最小的子数组

题目地址:https://leetcode.cn/problems/minimum-size-subarray-sum/description/?envType=study-plan-v2&envId=top-interview-150

  设置滑动窗口比较窗口内的数字之和与 t a r g e t target target,当满足条件时去掉窗口内首元素,将窗口右移,再次比较。

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        length = len(nums)
        slow, fast = 0, 0
        sum, ans = 0, length+1
        while fast < length:
            sum += nums[fast]
            while sum >= target:
                ans = min(ans,fast-slow+1)
                sum -= nums[slow]
                slow += 1
            fast += 1
        return 0 if ans==length+1 else ans
3.2 【滑动窗口】无重复字符的最长子串

题目地址:https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/?envType=study-plan-v2&envId=top-interview-150

  详见代码。

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        max_len = 0
        tmp_str = ""
        length = len(s)
        i = 0

        while i < length:
            if s[i] not in tmp_str:
                tmp_str += s[i]
                max_len = max(max_len,len(tmp_str))
                i += 1
            else:
                while s[i] in tmp_str:
                    tmp_str = tmp_str[1:]
        return max_len
3.3 【哈希表】串联所有单词的子串

题目地址:https://leetcode.cn/problems/substring-with-concatenation-of-all-words/description/?envType=study-plan-v2&envId=top-interview-150

  依次比较每个滑动窗口中单词的出现次数与 w o r d s words words是否一致即可。

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        word_len = len(words[0])
        word_num = len(words)
        window = word_len * word_num
        ans = []

        cnt = {word:0 for word in words}
        word_cnt = cnt.copy()
        for word in words:
            word_cnt[word] += 1
        
        start = 0
        while start < len(s) - window + 1:
            tmp_cnt = cnt.copy()
            for i in range(start, start+window, word_len):
                tmp_word = s[i:i+word_len]
                if tmp_word in tmp_cnt:
                    tmp_cnt[tmp_word] += 1
                else:
                    break
            if tmp_cnt == word_cnt:
                ans.append(start)
            start += 1
        return ans
3.4 【哈希表】最小覆盖子串

题目地址:https://leetcode.cn/problems/minimum-window-substring/description/?envType=study-plan-v2&envId=top-interview-150

  • 不断增加使滑动窗口增大,直到窗口包含了t的所有元素;
  • 不断增加使滑动窗口缩小,将不必要的元素排除在外,直到碰到一个必须包含的元记录此时滑动窗口的长度,并保存最小值;
  • 再增加一个位置,这个时候滑动窗口肯定不满足条件了,继续从步骤一开始执行,寻找新的满足条件的滑动窗口。
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        s_len, t_len, needCnt = len(s), len(t), len(t)
        need = collections.defaultdict(int)
        for c in t:
            need[c] += 1
        ans = (0,float('inf'))

        # 增加右边界使滑窗包含t
        i = 0
        for j,c in enumerate(s):
            if need[c] > 0:
                needCnt -= 1
            need[c] -= 1
            # 收缩左边界直到无法再去掉元素
            if needCnt == 0:
                while True:
                    ch = s[i]
                    if need[ch] == 0:
                        break
                    else:
                        need[ch] += 1
                        i += 1
                if j-i < ans[1]-ans[0]:
                    ans = (i,j+1)
                # i多增加一个位置,准备开始下一次循环
                need[s[i]] += 1
                needCnt += 1
                i += 1
        return ""if ans[1]>s_len else s[ans[0]:ans[1]]

4 矩阵

4.1 【哈希表】有效的数独

题目地址:https://leetcode.cn/problems/valid-sudoku/description/?envType=study-plan-v2&envId=top-interview-150

  将数组分别按照行、列、块构造哈希表,判断是否有重复元素。

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:

        row = [[0] * 9 for _ in range(9)]
        col = [[0] * 9 for _ in range(9)]
        block = [[0] * 9 for _ in range(9)]

        for i in range(9):
            for j in range(9):
                if board[i][j] != '.':
                    num = int(board[i][j]) - 1
                    b = (i // 3) * 3 + j // 3
                    if row[i][num] or col[j][num] or block[b][num]:
                        return False
                    row[i][num] = col[j][num] = block[b][num] = 1
        return True
4.2 【模拟】螺旋矩阵

题目地址:https://leetcode.cn/problems/spiral-matrix/description/?envType=study-plan-v2&envId=top-interview-150

  设置上下左右边界,按照从左到右、从上到下、从右到左、从下到上的顺序挨个遍历即可。

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        l,r,t,b,res = 0,len(matrix[0])-1,0,len(matrix)-1,[]
        while True:
            # left to right
            for i in range(l,r+1):
                res.append(matrix[t][i])
            t += 1
            if t > b:
                break
            # top to bottom
            for i in range(t,b+1):
                res.append(matrix[i][r])
            r -= 1
            if r < l:
                break
            # right to left
            for i in range(r,l-1,-1):
                res.append(matrix[b][i])
            b -= 1
            if b < t:
                break
            # bottom to top
            for i in range(b,t-1,-1):
                res.append(matrix[i][l])
            l += 1
            if l > r:
                break
        return res
4.3 【数学】旋转图像

题目地址:https://leetcode.cn/problems/rotate-image/description/?envType=study-plan-v2&envId=top-interview-150

  主对角线翻转+左右翻转。

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        length = len(matrix)
        # 主对角线
        for i in range(length):
            for j in range(i+1,length):
                matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j]
        # 左右
        for i in range(length):
            for j in range(length//2):
                matrix[i][j],matrix[i][length-j-1] = matrix[i][length-j-1],matrix[i][j]
4.4 【哈希】矩阵置零

题目地址:https://leetcode.cn/problems/set-matrix-zeroes/description/?envType=study-plan-v2&envId=top-interview-150

  首先判断第一行和第一列是否存在零,然后分别用第一行和第一列的空间表示该行或者该列是否存在零,最后统一置零即可。

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        row = len(matrix)
        col = len(matrix[0])
        zero_first = [False,False]
        # 第一行是否有零
        for i in range(col):
            if matrix[0][i] == 0:
                zero_first[0] = True
                break
        # 第一列是否有零
        for i in range(row):
            if matrix[i][0] == 0:
                zero_first[1] = True
                break
        # 记录其他行和列的零
        for i in range(1,row):
            for j in range(1,col):
                if matrix[i][j] == 0:
                    matrix[i][0] = matrix[0][j] = 0
        # 矩阵置零
        for i in range(1,row):
            for j in range(1,col):
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0
        if zero_first[0] == True:
            for i in range(col):
                matrix[0][i] = 0
        if zero_first[1] == True:
            for i in range(row):
                matrix[i][0] = 0
4.5 【模拟】生命游戏

题目地址:https://leetcode.cn/problems/game-of-life/description/?envType=study-plan-v2&envId=top-interview-150

  卷积运算,计算每个细胞的得分。文章来源地址https://www.toymoban.com/news/detail-827585.html

import numpy as np

class Solution:
    def gameOfLife(self, board: List[List[int]]) -> None:
        row,col = len(board),len(board[0])
        # zero padding
        board_tmp = np.array([[0 for _ in range(col+2)] for _ in range(row+2)])
        board_tmp[1:row+1,1:col+1] = np.array(board)
        # kernel
        kernel = np.array([[1,1,1],[1,0,1],[1,1,1]])
        # conv
        for i in range(1,row+1):
            for j in range(1,col+1):
                tmp = np.sum(kernel * board_tmp[i-1:i+2,j-1:j+2])
                if board_tmp[i][j] == 1:
                    if tmp < 2 or tmp > 3:
                        board[i-1][j-1] = 0
                else:
                    if tmp == 3:
                        board[i-1][j-1] = 1

到了这里,关于【leetcode刷题之路】面试经典150题(2)——双指针+滑动窗口+矩阵的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法刷题记录-双指针/滑动窗口(LeetCode)

    思路 根据题目描述,我们可以知道,如果要将某个单词定义为可扩张(stretchy),需要满足如下两个条件: 所以,我们在实现的时候,可以通过两个指针p1和p2,分别指向s和word,分别统计连续的相同字符数量c1和c2,然后再通过上述的两个条件进行判断,即:如果 则表示该单

    2024年02月09日
    浏览(28)
  • Leetcode面试经典150题刷题记录 —— 二叉搜索树篇

    Leetcod面试经典150题刷题记录-系列 Leetcod面试经典150题刷题记录——数组 / 字符串篇 Leetcod面试经典150题刷题记录 —— 双指针篇 Leetcod面试经典150题刷题记录 —— 矩阵篇 Leetcod面试经典150题刷题记录 —— 滑动窗口篇 Leetcod面试经典150题刷题记录 —— 哈希表篇 Leetcod面试经典

    2024年01月23日
    浏览(35)
  • 【双指针】滑动窗口经典例题 力扣

    无重复的最长子串LC3 中等 题目链接 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 代码: 找到字符串中所有子母异位词LC438 中等 题目链接 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序

    2024年02月07日
    浏览(31)
  • 【面试经典150 | 双指针】验证回文串

    本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下: Tag:介绍本题牵涉到的知识点、数据结构; 题目来源:贴上题目的链接,方

    2024年02月09日
    浏览(23)
  • 【面试经典150 | 双指针】两数之和

    本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删: Tag:介绍本题牵涉到的知识点、数据结构; 题目来源:

    2024年02月09日
    浏览(25)
  • 刷题(双指针思想/滑动窗口思想/l螺旋矩阵)

    刚开始自己做就是无脑ac的,sort: 但是时间复杂度有问题, 是O(nlogn)的时间复杂度 提升:用双指针的思想:时间复杂度为O(n) 使用 双指针 的思想解决本题的思路: 以数组 为例: 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 因为输入的数组是递增的,因此,平方后的最大值,只

    2023年04月08日
    浏览(38)
  • 【剑指offer刷题记录 java版】数组双指针 之 滑动窗口

    本系列文章记录labuladong的算法小抄中剑指offer题目 题目链接:https://leetcode.cn/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/ 题目链接:https://leetcode.cn/problems/MPnaiL/ 题目链接:https://leetcode.cn/problems/VabMRr/ 题目链接:https://leetcode.cn/problems/wtcaE1/ 题目链接:https://leetcode.cn/pr

    2024年02月09日
    浏览(39)
  • 【LeetCode-经典面试150题-day12】

    20.有效的括号 题意: 给定一个只包括  \\\'(\\\' , \\\')\\\' , \\\'{\\\' , \\\'}\\\' , \\\'[\\\' , \\\']\\\'  的字符串  s  ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有一个对应的相同类型的左括号。 【输入样例】s=\\\"

    2024年02月11日
    浏览(27)
  • LeetCode面试经典150题(day 1)

    LeetCode是一个免费刷题的一个网站,想要通过笔试的小伙伴可以每天坚持刷两道算法题。 接下来,每天我将更新LeetCode面试经典150题的其中两道算法题,一边巩固自己,一遍希望能帮助到有需要的小伙伴。 88.合并两个有序数组 给你两个按  非递减顺序  排列的整数数组  nu

    2024年02月11日
    浏览(26)
  • LeetCode面试经典150题(day 2)

    26. 删除有序数组中的重复项 难度: 简单    给你一个  升序排列  的数组  nums  ,请你  原地  删除重复出现的元素,使每个元素  只出现一次  ,返回删除后数组的新长度。元素的  相对顺序  应该保持  一致  。然后返回  nums  中唯一元素的个数。 考虑  nums  的唯一

    2024年02月11日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包