LeetCode 每周算法 2(子串、普通数组)

LeetCode 每周算法 2(子串、普通数组)

子串算法:

在这里插入图片描述

class Solution(object):
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        # 初始化哈希表,用于存储前缀和及其出现的次数  
        # 初始时,前缀和为0的情况出现1次,因为空子数组的和视为0  
        prefix_sum_count = {0: 1}  
        count = 0  # 用于记录满足条件的子数组个数  
        current_sum = 0  # 当前位置之前的元素和  
    
        for num in nums:  
            # 更新当前位置之前的元素和  
            current_sum += num  
            
            # 检查当前前缀和与之前的某个前缀和之差是否为k  
            # 如果存在这样的前缀和差值,那么说明这两个前缀和之间的子数组和就是k  
            if current_sum - k in prefix_sum_count:  
                # 如果存在,则将满足条件的子数组个数增加  
                # 注意,这里可能会多次计算到同一个满足条件的子数组(比如数组中有重复元素)  
                # 但由于题目只要求个数,所以这样是允许的  
                count += prefix_sum_count[current_sum - k]  
            
            # 将当前前缀和加入哈希表,并更新其出现的次数  
            # 注意,如果当前前缀和已经存在于哈希表中,则更新其计数,而不是替换  
            if current_sum in prefix_sum_count:  
                prefix_sum_count[current_sum] += 1  
            else:  
                prefix_sum_count[current_sum] = 1  
    
        # 返回满足条件的子数组个数  
        return count

在这里插入图片描述

class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        # 初始化一个列表作为窗口,用于存储窗口内的元素索引  
        # 这里使用索引而不是元素值,以便在O(1)时间内移除窗口最左侧的元素  
        window = []  
        # 初始化结果列表  
        result = []  
    
        # 遍历数组nums  
        for i in range(len(nums)):  
            # 如果窗口不为空,并且当前元素比窗口最左侧的元素大  
            # 那么窗口最左侧的元素在后续窗口滑动中不会再是最大值  
            # 因此需要移除它(通过移除其索引)  
            while window and nums[i] >= nums[window[-1]]:  
                window.pop()  # 移除窗口最右侧的索引(即当前窗口中最小的元素索引)  
            # 将当前元素的索引添加到窗口的末尾  
            window.append(i)  
            # 当窗口大小达到k时,开始记录窗口的最大值  
            if i >= k - 1:  
                # 窗口最左侧的元素索引对应的值即为当前窗口的最大值  
                result.append(nums[window[0]])  
                # 如果窗口最左侧的元素索引已经不在当前窗口内(即已经滑出窗口)  
                # 则将其从窗口中移除  
                if window[0] <= i - k:  
                    window.pop(0)  # 移除窗口最左侧的索引  
    
        # 返回记录的结果列表  
        return result 

在这里插入图片描述

class Solution(object):
    def minWindow(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        # 初始化需求哈希表,记录 t 中每个字符的需求次数  
        need = {}  
        for char in t:  
            need[char] = need.get(char, 0) + 1  
    
        # 初始化窗口哈希表,记录当前窗口中每个字符的计数  
        window = {}  
        # formed 用于记录当前窗口中已满足 t 中字符需求的种类数  
        formed = 0  
    
        # 初始化左右指针、最小长度和结果字符串  
        left, right = 0, 0  
        min_length = float('inf')  
        result = ""  
    
        # 滑动窗口逻辑  
        while right < len(s):  
            # 将右指针指向的字符加入窗口  
            char = s[right]  
            if char in need:  
                # 如果字符在 need 中,增加窗口哈希表中该字符的计数  
                window[char] = window.get(char, 0) + 1  
                # 如果该字符的计数达到了需求,则 formed 加一  
                if window[char] == need[char]:  
                    formed += 1  
    
            # 尝试缩小窗口  
            while formed == len(need):  
                # 更新最小长度和结果字符串(如果当前窗口更小)  
                if right - left + 1 < min_length:  
                    min_length = right - left + 1  
                    result = s[left:right+1]  
    
                # 尝试移动左指针来缩小窗口  
                char_to_remove = s[left]  
                # 如果左指针指向的字符在窗口哈希表中  
                if char_to_remove in window:  
                    # 减少窗口哈希表中该字符的计数  
                    window[char_to_remove] -= 1  
                    # 如果该字符的计数不再满足需求,则 formed 减一  
                    if window[char_to_remove] < need[char_to_remove]:  
                        formed -= 1  
                # 移动左指针  
                left += 1  
    
            # 移动右指针以继续探索  
            right += 1  
    
        # 返回结果字符串  
        return result

普通数组算法:

在这里插入图片描述

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        # 初始化当前子数组的最大和(current_max)为数组的第一个元素  
        # 初始化全局子数组的最大和(global_max)也为数组的第一个元素  
        if not nums:  # 如果数组为空,则直接返回0  
            return 0  
        current_max = nums[0]  
        global_max = nums[0]  
    
        # 从数组的第二个元素开始遍历  
        for num in nums[1:]:  
            # 如果当前子数组的和加上当前元素的值比当前元素的值还小  
            # 那么就重新以当前元素为新的子数组的起点  
            current_max = max(num, current_max + num)  
            # 更新全局最大和  
            global_max = max(global_max, current_max)  
    
        # 遍历结束后,global_max即为所求的最大和的连续子数组的和  
        return global_max

在这里插入图片描述

class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[List[int]]
        """
        # 如果输入的区间列表为空,则直接返回空列表  
        if not intervals:  
            return []  
        
        # 根据区间的起始位置对区间列表进行排序  
        # 使用lambda函数作为sort方法的key参数,指定按照区间的第一个元素(即起始位置)进行排序  
        intervals.sort(key=lambda x: x[0])  
        
        # 初始化一个空列表merged,用于存储合并后的区间  
        # 同时,将排序后的第一个区间添加到merged列表中,作为合并的起点  
        merged = [intervals[0]]  
        
        # 从排序后的区间列表的第二个区间开始遍历  
        for i in range(1, len(intervals)):  
            # 取出当前遍历到的区间  
            current_interval = intervals[i]  
            
            # 取出merged列表中的最后一个区间(即当前已经合并好的最后一个区间)  
            last_merged_interval = merged[-1]  
            
            # 检查当前区间是否与最后一个合并区间重叠  
            # 重叠的条件是:当前区间的起始位置小于或等于最后一个合并区间的结束位置  
            if current_interval[0] <= last_merged_interval[1]:  
                # 如果重叠,则更新最后一个合并区间的结束位置为两个区间结束位置的最大值  
                # 这样做是为了合并两个重叠的区间  
                last_merged_interval[1] = max(last_merged_interval[1], current_interval[1])  
            else:  
                # 如果不重叠,则将当前区间直接添加到merged列表中  
                # 因为当前区间与之前的区间都不重叠,所以它可以作为一个新的合并区间的起点  
                merged.append(current_interval)  
        
        # 遍历结束后,merged列表中就包含了所有合并后的区间  
        # 返回这个列表作为函数的结果  
        return merged

在这里插入图片描述

class Solution(object):
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        n = len(nums)  # 获取数组nums的长度  
        k = k % n  # 如果k大于数组长度,则取模,保证k在有效范围内  
        
        # 定义一个辅助函数reverse,用于反转数组nums中从start到end(不包含end)的部分  
        def reverse(start, end):  
            while start < end:  
                # 交换start和end位置的元素  
                nums[start], nums[end] = nums[end], nums[start]  
                start += 1  # 向前移动start指针  
                end -= 1    # 向后移动end指针  
        
        # 反转整个数组  
        reverse(0, n-1)  
        
        # 反转前k-1%n个元素,即反转轮转后应该位于数组前面的部分  
        reverse(0, k-1)  
        
        # 反转剩余的n-k-1个元素,即反转轮转后应该位于数组后面的部分  
        reverse(k, n-1) 

在这里插入图片描述

class Solution(object):
    def productExceptSelf(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        n = len(nums)  
        # 初始化结果数组,全部填充为1,因为乘积的初始值是1  
        answer = [1] * n  
        
        # 左侧乘积  
        left_product = 1  
        for i in range(n):  
            # 当前位置的答案数组中的值是左侧乘积  
            answer[i] *= left_product  
            # 更新左侧乘积为当前左侧乘积乘以当前元素的值  
            left_product *= nums[i]  
        
        # 右侧乘积,初始化为1  
        right_product = 1  
        # 从右向左遍历,更新答案数组  
        for i in range(n - 1, -1, -1):  
            # 当前位置的答案数组中的值还需要乘以右侧乘积  
            answer[i] *= right_product  
            # 更新右侧乘积为当前右侧乘积乘以当前元素的值
            #(注意这里是nums[i],因为我们是从右向左遍历的)  
            right_product *= nums[i]  
        
        return answer

在这里插入图片描述

class Solution(object):
    def firstMissingPositive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)  

        # 第一步:将所有非正整数和大于n的整数替换为n+1(或其他大于n的值,目的是排除它们对后续步骤的干扰)  
        for i in range(n):  
            if nums[i] <= 0 or nums[i] > n:  
                nums[i] = n + 1  
        
        # 第二步:根据数组中的值,将其放到正确的位置上(索引为值减1)  
        # 注意,这里可能产生循环依赖,例如nums[i] = j 和 nums[j] = i,此时我们需要用一个临时变量来避免覆盖  
        for i in range(n):  
            while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:  
                # 交换nums[i]和nums[nums[i]-1],直到nums[i]处于正确的位置或nums[i]已经处于循环中  
                nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]  
        
        # 第三步:遍历数组,找到第一个不在正确位置上的正整数索引+1,即为所求  
        for i in range(n):  
            if nums[i] != i + 1:  
                return i + 1  
        
        # 如果所有正整数都出现了,则返回n+1(因为题目要求的是未出现的最小正整数)  
        return n + 1  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值