Leetcode hot100 刷题记录 (python)

冲冲冲!!! 开始时间:2.20

双指针

1 盛最多水的容器

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        # 暴力解法 12ms超时
        # res = 0
        # for i in range(len(height)):
        #     for j in range(i+1, len(height)):
        #         l = j -i
        #         h = min(height[i], height[j])
        #         vol = l * h
        #         res = max(vol, res)
        # return res

        # 双指针 !
        l = 0 #left pointer
        r = len(height) - 1 #right pointer
        res = 0
        while l < r :
            vol = (r - l) * min(height[l], height[r])
            res = max(res, vol)
            if height[l] <= height[r]:
                l += 1
            else:
                r -= 1
        return res

2 三数之和

我的解法: 写了一个世纪┭┮﹏┭┮,虽然通过,但太长,运行时间也长

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        nums = sorted(nums)
        res = []
        j = 1
        for i in nums[:len(nums)-2]:
            if len(self.twoSum(nums[j:], -i))>0:
                
                for num in self.twoSum(nums[j:], -i):
                    tmp = []
                    tmp.append(i)
                    tmp.extend(num)
                    res.append(tmp)
                    
            j += 1

        # 去除res中重复的元素
        # print(res)
        res_tuples = [tuple(sorted(r)) for r in res] #对每个list元素排序且转为tuple
        res_unique = set(res_tuples) #去重,set()函数的操作对象是list、tuple和字符串
        res = [list(u) for u in res_unique] #还原为list
        return res
        

    @staticmethod
    def twoSum(array, addvalue):
        res =[]
        if len(array) >= 2:
            lp = 0
            rp = len(array)-1        
            while lp < rp:
                if array[lp] + array[rp] < addvalue:
                    lp += 1
                elif array[lp] + array[rp] > addvalue:
                    rp -= 1
                else:
                    tmp = []
                    tmp.append(array[lp])
                    tmp.append(array[rp])
                    res.append(tmp)
                    lp += 1
                    rp -= 1
                    continue

        return res

leetcode官方题解:很简洁(┭┮﹏┭┮)

class Solution:
    def threeSum(self, nums):
        n = len(nums)
        nums.sort()
        ans = list()
        
        # 枚举 a
        for first in range(n):
            # 需要和上一次枚举的数不相同
            if first > 0 and nums[first] == nums[first - 1]:
                continue
            # c 对应的指针初始指向数组的最右端
            third = n - 1
            target = -nums[first]
            # 枚举 b
            for second in range(first + 1, n):
                # 需要和上一次枚举的数不相同
                if second > first + 1 and nums[second] == nums[second - 1]:
                    continue
                # 需要保证 b 的指针在 c 的指针的左侧
                while second < third and nums[second] + nums[third] > target:
                    third -= 1
                # 如果指针重合,随着 b 后续的增加
                # 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
                if second == third:
                    break
                if nums[second] + nums[third] == target:
                    ans.append([nums[first], nums[second], nums[third]])
        
        return ans

3 接雨水

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        n = len(height)
        # 每个区域S = min(前缀max,后缀max)-height[i]
        pre_max = [0] * n
        pre_max[0] = height[0]
        for i in range(1, n):
            pre_max[i] = max(height[i], pre_max[i-1])
        post_max = [0] * n
        post_max[-1] = height[-1]
        for j in range(n-2, -1 ,-1):
            post_max[j] = max(post_max[j+1], height[j])
        ans = 0
        for pre, post, h in zip(pre_max, post_max, height):
            ans += min(pre, post) - h
        return ans
        # 灵茶山艾府思路

二分查找

一个有序整数数组nums, 查找target在其中的位置,如果nums含有target,则返回其下标,如果不含有targrt,则返回按顺序target应该在哪个位置插入nums。(无论nums中有无重复元素均成立)

def binary_search_insertion(nums: list[int], target: int) -> int:
    i, j = 0, len(nums) - 1
    while i <= j:
        m = (i + j) // 2
        if nums[m] < target:
            i = m + 1
        elif nums[m] > target:
            j = m - 1
        else:
            j = m - 1
    return i

查找左右位置,如

nums = [1, 3, 6, 6, 6, 12, 15]
taget = 6

target 左侧位置即为2, 右侧位置为4, 如果要查找的target不存在,则左右位置均返回-1

利用上述二分算法binary_search_insertion(nums, target)

# 左
def binary_search_left_edge(nums: list[int], target: int) -> int:
    i = binary_search_insertion(nums, target)
    if i == len(nums) or nums[i] != target:
        # 越界 或 值不对应
        return -1
    return i

# 右
def binary_search_right_edge(nums: list[int], target: int) -> int:
    i = binary_search_insertion(nums, target + 1)
    j = i - 1
    if j == -1 or nums[j] != target:
        # 首元素 或 值不对应
        return -1
    return j

(参考10.1   二分查找 - Hello 算法 (hello-algo.com)

4 搜索插入位置

class Solution(object):
    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        i, j = 0, len(nums) - 1
        while i <= j:
            m = (i + j) //2
            if nums[m] < target:
                i = m + 1
            elif nums[m] > target:
                j = m -1
            else:
                j = m - 1
        return i

搜索二维矩阵

class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        nums = []
        for item in matrix:
            nums.extend(item)
        i = self.searchInsert(nums, target)
        if i == len(nums) or nums[i] != target:
            return False
        return True
        
            



    @staticmethod
    def searchInsert(nums, target):
        i, j = 0, len(nums) - 1
        while i <= j:
            m = (i + j) // 2
            if nums[m] < target:
                i = m + 1
            elif nums[m] > target:
                j = m - 1
            else:
                j = m - 1
        return i

在排序数组中查找元素的第一个和最后一个位置

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        left = self.searchInsert(nums, target)
        if left == len(nums) or nums[left] != target:
            left = -1
        right = self.searchInsert(nums, target + 1) - 1
        if right == -1 or nums[right] != target:
            right = -1
        return [left, right]



    @staticmethod
    def searchInsert(nums, target):
        i, j = 0, len(nums) - 1
        while i <= j:
            m = (i + j) // 2
            if nums[m] < target:
                i = m + 1
            elif nums[m] > target:
                j = m - 1
            else:
                j = m - 1
        return i

 搜索旋转排序数组(⭐)

看答案的

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        l, r = 0, len(nums) - 1
        while l <= r:
            m = (l + r) // 2
            if nums[m] == target:
                return m
            # 总有一侧是有序的,如果左侧有序
            if nums[0] <= nums[m]:
                if nums[0] <= target < nums[m]:
                    r = m - 1
                else:
                    l = m + 1
            else:
                if nums[m] < target <= nums[len(nums) - 1]:
                    l = m + 1
                else:
                    r = m - 1
        return -1

寻找旋转排序数组中的最小值(⭐)

看答案的。

class Solution(object):
    def findMin(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        l, r = 0 ,len(nums) - 1
        while l < r:
            m = (l + r) // 2
            if nums[m] < nums[r]:
                r = m
            elif nums[m] > nums[r]:
                l = m + 1
        return nums[l]

滑动窗口

最长不重复子串

思路:左指针left, 右指针right, 在右指针向右移动的过程中,如果nums[right]不在set()里面,则加入,如果在set()里面,则先不右移,将左指针向右移动,并在set()里面删除nums[left], 直到可以右移右指针为止。

无重复字符的最长子串(⭐)

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        left, right, length, max_length = 0, 0, 0, 0
        array = set()
        while right < len(s):
            if s[right] not in array:
                array.add(s[right])
                right += 1
                length += 1
                max_length = max(length, max_length)
            else:
                while s[right] in array:
                    array.remove(s[left])
                    left += 1
                    length -= 1
                array.add(s[right])
                right += 1
                length += 1
        return max_length

10 找到字符串中所有字母异位词(⭐)

维护两个数组,长度为26,每一个位置表示某个字母的出现位置,比较这两个数组,一直则为异位词。

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        n = len(s)
        m = len(p)
        res = []
        if n < m:
            return res
        s_count = [0] * 26
        p_count = [0] * 26
        for i in range(m):
            p_count[ord(p[i]) - ord('a')] += 1
            s_count[ord(s[i]) - ord('a')] += 1
        if p_count == s_count:
            res.append(0)
        for i in range(m, n):
            s_count[ord(s[i-m]) - ord('a')] -= 1
            s_count[ord(s[i]) - ord('a')] += 1
            if s_count == p_count:
                res.append(i-m+1)
        return res

回溯

全排列(参考13.2   全排列问题 - Hello 算法 (hello-algo.com)

无重复元素

[1, 2, 3]
全排列[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
[1, 1, 3]
全排列[[1, 1, 3], [1, 3, 1], [1, 1, 3], [1, 3, 1], [3, 1, 1], [3, 1, 1]]
def backtrack(state, choices, selected, res):
    """回溯算法:全排列 I"""
    # 当状态长度等于元素数量时,记录解
    if len(state) == len(choices):
        res.append(list(state))
        return
    # 遍历所有选择
    for i, choice in enumerate(choices):
        # 剪枝:不允许重复选择元素
        if not selected[i]:
            # 尝试:做出选择,更新状态
            selected[i] = True
            state.append(choice)
            # 进行下一轮选择
            backtrack(state, choices, selected, res)
            # 回退:撤销选择,恢复到之前的状态
            selected[i] = False
            state.pop()

def permutations_i(nums):
    res = []
    backtrack(state=[], choices=nums, selected=[False] * len(nums), res=res)
    return res

有重复元素

[1, 1, 3]全排列[[1, 1, 3], [1, 3, 1], [3, 1, 1]]
def backtrack2(state, choices, selected, res):
    if len(state) == len(choices):
        res.append(list(state))
        return
    duplicated = set[int]() #add
    for i, choice in enumerate(choices):
        if not selected[i] and choice not in duplicated: #add
            duplicated.add(choice) #add
            state.append(choice)
            selected[i] = True
            backtrack2(state, choices, selected, res)
            selected[i] = False
            state.pop()

def permutations_i2(nums):
    res = []
    backtrack2(state=[], choices=nums, selected=[False] * len(nums), res=res)
    return res           
print(permutations_i2([1,1,3]))

11 全排列

class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        
        def backtrack(state, choices, selected, res):
            if len(state) == len(choices):
                res.append(list(state))
                return 
            for i, choice in enumerate(choices):
                if not selected[i]:
                    selected[i] = True
                    state.append(choice)
                    backtrack(state, choices,selected, res)
                    selected[i] = False
                    state.pop()
        res = []
        backtrack([], nums, [False]*len(nums), res)
        return res   

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值