LeetCode HOT100刷题笔记(二):滑动窗口,数组

【如果笔记对你有帮助,欢迎关注&点赞&收藏,收到正反馈会加快更新!谢谢支持!】

ps:笔记和代码按本人理解整理,重思路

目录

上期笔记

一、滑动窗口

题目8:无重复字符的最长子串

 题目9:找到字符串中所有字母异位词

二、数组

题目10:最大子数组和

题目11:合并区间

题目12:轮转数组

题目13:除自身以外数组的乘积

题目14:缺失的第一个正数


上期笔记

LeetCode HOT100刷题笔记(一):哈希表, 双指针_leetcode刷题笔记模板-CSDN博客

一、滑动窗口

题目8:无重复字符的最长子串

3. 无重复字符的最长子串 - 力扣(LeetCode)

  • 题意:找到字符串s中无重复字符的最长子串
  • 拆解:
    「滑动窗口」一左一右两个指针组成
    
    「代码逻辑」
    - 初始化滑动窗口的左右指针在最左端
    while 右指针右移【扩大窗口】:
    	while 新字符已在窗口中(重复情况):
    		- 左指针右移【缩小窗口】至无重复
    	更新最长子串
    		
  • 代码:
    class Solution:
        def lengthOfLongestSubstring(self, s: str) -> int:
            left = 0
            right = 0
            result = 0
            while right < len(s):
                
                while left < right and s[right] in s[left: right]:
                    left += 1
    
                result = max(result, right - left + 1)
                right += 1
    
            return result
    
     

 题目9:找到字符串中所有字母异位词

438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

  • 题意:所有 p 的 异位词 的子串,记录子串起始index
  • 关键:用Counter()统计 p 和窗口的字符和个数,如果两个Counter相等,则记录结果
  • 代码:
    class Solution:
        def findAnagrams(self, s: str, p: str) -> List[int]:
            n = len(s)
            m = len(p)
            Counterp = Counter(p)
            Counters = Counter()
            ans = []
            if n >= m:
                for i in range(m-1):
                    Counters[s[i]] += 1
                for i in range(m-1, n):      
                    Counters[s[i]] += 1
                    if Counters == Counterp:
                        ans.append(i-m+1)
                    Counters[s[i-m+1]] -= 1
            return ans
                

二、数组

题目10:最大子数组和

53. 最大子数组和 - 力扣(LeetCode)

  • 题意:找到和最大的连续子数组
  • 关键:及时丢掉和为负数的连续子数组
  • 拆解:
    「代码逻辑」
    - temp_sum:记录当前子数组的和
    for nums中的每个num:
    	- 加到temp_sum中
    	- 更新最大子数组和
    	if temp_sum < 0:
    		- 丢掉(即temp_sum置0,不让他拖累后面的结果)
  • 代码:
    class Solution:
        def maxSubArray(self, nums: List[int]) -> int:
            sum_ = -inf
            temp_sum = 0
            for i in nums:
                temp_sum += i
                sum_ = max(sum_, temp_sum)
                if temp_sum <= 0:
                    temp_sum = 0
            return sum_
    

题目11:合并区间

56. 合并区间 - 力扣(LeetCode)

  • 题意:一个数组里面有多个可能有重叠部分的区间,合并重叠部分,返回合并后的所有区间
  • 关键:先通过排序确定一端(如左端),再找可以合并的区间们,确认另一端
  • 拆解:
    「代码逻辑」
    
    - 根据区间们的左端排序 
    - ans:记录合并后的区间
    for 每个区间:
    	if 当前区间和ans[-1]区间相交【可合并】:
    		- 更新ans[-1]区间右端
    	else【不可合并】:
    		- ans加入当前区间
    
  • 代码:
    class Solution:
        def merge(self, intervals: List[List[int]]) -> List[List[int]]:
            intervals.sort(key=lambda p: p[0])  # 按照左端点从小到大排序
            ans = []
            for p in intervals:
                if ans and p[0] <= ans[-1][1]:  # 可以合并
                    ans[-1][1] = max(ans[-1][1], p[1])  # 更新右端点最大值
                else:  # 不相交,无法合并
                    ans.append(p)  # 新的合并区间
            return ans
    

题目12:轮转数组

189. 轮转数组 - 力扣(LeetCode)

  • 题意:将数组中的元素向右轮转k个位置,要求空间复杂度O(1)
  • 关键:用反转数组解决
  • 拆解:
    「代码逻辑」
    
    - 反转整个数组
    - 反转数组前k个[:k]
    - 反转剩余后面数组[k:]
    【得到轮转数组】
  • 代码:
    class Solution:
        def rotate(self, nums: List[int], k: int) -> None:
            """
            Do not return anything, modify nums in-place instead.
            """
            k = k % len(nums)
            def reverse(arr):
                l = 0
                r = len(arr)-1
                while l <= r:
                    arr[l], arr[r] = arr[r], arr[l]
                    l += 1
                    r -= 1 
                return arr
            
            nums = reverse(nums)
            nums[:k] = reverse(nums[:k])
            nums[k:] = reverse(nums[k:])
    

题目13:除自身以外数组的乘积

238. 除自身以外数组的乘积 - 力扣(LeetCode)

  • 题意:返回answer,其中answer[i] = nums 中除nums[i]之外其余各元素的乘积
  • 关键:\前缀和\ 和 \后缀和\ 记录乘积
  • 拆解:

    「代码逻辑」
    
    - pre 前缀和 nums[:i]的乘积
    - suff 后缀和 nums[i+1:]的乘积
    - answer[i] = nums[:i]的乘积*nums[i+1:]的乘积 = pre[i]*suff[i]
    
    「例子」
    nums = [1,2,3,4]
    pre = [1,1,2,6]
    suff =[24,12,4,1]
    answer[1] = pre[1]*suff[1] = 12
  • 代码:

    「代码逻辑」
    
    - pre 前缀和 nums[:i]的乘积
    - suff 后缀和 nums[i+1:]的乘积
    - answer[i] = nums[:i]的乘积*nums[i+1:]的乘积 = pre[i]*suff[i]
    
    「例子」
    nums = [1,2,3,4]
    pre = [1,1,2,6]
    suff =[24,12,4,1]
    answer[1] = pre[1]*suff[1] = 12


     

题目14:缺失的第一个正数

41. 缺失的第一个正数 - 力扣(LeetCode)

  • 题意:找到数组中没有出现的最小正整数,要求时间复杂度O(n),只使用O(1)额外空间
  • 关键:两遍遍历数组,第一遍让所有所有数组长度范围内的数归位,第二遍找出没出现的最小正整数
  • 拆解:
    「代码逻辑」
    
    - 第一遍遍历
    	- 通过【交换】,把数num放到数组中第num个位置
    	 (跳过 <1 或者 >n 的数)
    
    - 第二遍遍历
    	- 看 nums[i] == i+1 是否成立(数num是否在第num个位置)
    		如果不在就返回结果(说明找到没出现的最小正整数)
  • 代码:
    class Solution:
        def firstMissingPositive(self, nums: List[int]) -> int:
            n = len(nums)
            for i in range(n):
                while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:
                    j = nums[i] - 1 
                    nums[i], nums[j] = nums[j], nums[i]
            
            for i, num in enumerate(nums):
                if num != i+1:
                    return i+1
            return n+1          

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值