Leetcode题解 0021期

话说养成习惯是21天,这个应该是调查取的平均数吧,也就是说有些人可能会超过21天,有些人会少于21天……

0075题 分类颜色【Sort Colors】

题目:
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

进阶要求:

  • 一个直观的解决方案是使用计数排序的两趟扫描算法。
  • 首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
  • 你能想出一个仅使用常数空间的一趟扫描算法吗?

示例:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

题目相对严谨

除Robust以外无需注意太多

解题思路:
这题最tricky的地方就是在于这个一趟扫描算法,两趟谁都会做,常数空间也谁都会。
突然想到这道题只有3个数字,我能不能用快排的思路大概以1(这里需要注意如果没有1的情况)pivot,然后这样左右扫描到中间,完成排序这样子的,应该可行。而且打开题目的tag,也有写道双指针的形式,让我们看看能不能实现……然后,很遗憾想的太简单了,自己很轻易就能找见反例,有点不对,然后看着范例就想着再多一些指针会不会好用,但是就越来越冗杂了,三个指针四个区间应该能过但是就太难操作,然后就想着如果仍然是三个指针,顺序扫描放0,1,2的位置是否可以……因为这题不让排序的突破口就是在于数字只有三种,所以这样一想应该说的通。放上代码:

class Solution:
    def sortColors(self, nums):
        n = len(nums)
        if n == 0: return
        zero = one = two = -1
        for i in range(n):
            if nums[i] == 0:
                two += 1
                nums[two] = 2
                one += 1
                nums[one] = 1
                zero += 1
                nums[zero] = 0
            elif nums[i] == 1:
                two += 1
                nums[two] = 2
                one += 1
                nums[one] = 1
            else:
                two += 1
                nums[two] = 2

我挺想打死那个最速解法的……这个enumerate在python里怎么这么快……


0076题 最小覆盖子串【Minimum Window Substring】

题目:
给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。
说明:

  • 如果 S 中不存这样的子串,则返回空字符串 “”。
  • 如果 S 中存在这样的子串,我们保证它是唯一的答案。

示例:

输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"

题目相对严谨

除Robust以外无需注意太多

解题思路:
第一反应暴力肯定是 O ( m n ) 的,那肯定不行……想到之前解一道题时看到的滑动窗口。
解法参考了:https://github.com/zhuli19901106/leetcode-2/blob/master/minimum-window-substring_1_AC.cpp

class Solution:
    def minWindow(self, s, t):
        ls = len(s)
        lt = len(t)
        if lt == 0 or ls < lt: return ""
        cnt = 0
        vs = [0] * 256
        vt = [0] * 256
        for i in range(lt):
            vt[ord(t[i])] += 1
            cnt += 1

        min_len = ls + 1
        res = ""
        j = 0
        for i in range(ls):
            if vs[ord(s[i])] < vt[ord(s[i])]: cnt -= 1
            vs[ord(s[i])] += 1
            if cnt > 0: continue

            ch = s[j]
            vs[ord(ch)] -= 1
            j += 1

            while vs[ord(ch)] >= vt[ord(ch)]:
                ch = s[j]
                vs[ord(ch)] -= 1
                j += 1

            cnt += 1

            if i-j+2 < min_len:
                min_len = i - j + 2
                res = s[j-1: j + min_len - 1]

        return res

0077题 组合【Combinations】

题目:
给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。

示例:

输入: n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

题目相对严谨

除Robust以外无需注意太多

解题思路:
无需注意太多,直接上就行,range是个好东西,iterable。


0078题 子集【Subsets】

题目:

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。

示例:

输入: nums = [1,2,3]
输出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

题目相对严谨

需要注意:
1. 空集合的子集
2. Robust

解题思路:
因为没有重复的元素,子集有多少个,就得循环多少遍,没得说

class Solution:
    def subsets(self, nums):
        n = len(nums)
        if n == 0: return [[]]
        res = []
        for i in range(1<<n):
            tmp = []
            for j in range(n):
                if i & (1<<j):
                    tmp.append(nums[j])
            res.append(tmp)
        return res

本来以为二进制生成子集已经是非常巧妙的解法了,没想到python竟然有更为方便的解法,见如下:

class Solution:
    def subsets(self, nums):
        results=[[]]
        for i in nums:
            results=results+[[i]+num for num in results]
        return results

猜你喜欢

转载自blog.csdn.net/bright_silmarillion/article/details/80759018