最近在用python刷Leetcode,个人把刷题过程中遇到的一些难题记录在博客上,以做复习之用。
github刷题链接
在线阅读地址
参考资料:LeetCode 题解(c++)灵魂机器著
class Solution:
def longestPalindrome(self, s: str) -> str:
r = ''
for i, j in [(i, j) for i in range(len(s)) for j in (0, 1)]:
while i > -1 and i + j < len(s) and s[i] == s[i + j]:
i, j = i - 1, j + 2
r = max(r, s[i + 1:i + j], key=len)
return '' if not s else r
60 Permutation Sequence
给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。
说明:给定 n 的范围是 [1, 9]。给定 k 的范围是[1, n!]。
示例:
输入: n = 3, k = 3
输出: "213"
输入: n = 4, k = 9
输出: "2314"
class Solution:
def getPermutation(self, n: int, k: int) -> str:
# 0-9的阶乘
self.fac = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
self.nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 康托编码
res = ''
k -= 1
for i in reversed(range(n)):
cur = self.nums[k // self.fac[i]]
res += str(cur)
self.nums.remove(cur)
if i != 0:
k %= self.fac[i]
self.fac[i] //= i
return res
68 Text Justification
给定一个单词数组和一个长度 maxWidth,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。
你应该使用“贪心算法”来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ’ ’ 填充,使得每行恰好有 maxWidth 个字符。
要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。
文本的最后一行应为左对齐,且单词之间不插入额外的
空格。
示例:
输入:
words = ["This", "is", "an", "example", "of", "text", "justification."]
maxWidth = 16
输出:
[
"This is an",
"example of text",
"justification. "
]
输入:
words = ["What","must","be","acknowledgment","shall","be"]
maxWidth = 16
输出:
[
"What must be",
"acknowledgment ",
"shall be "
]
解释: 注意最后一行的格式应为 "shall be " 而不是 "shall be",
因为最后一行应为左对齐,而不是左右两端对齐。
第二行同样为左对齐,这是因为这行只包含一个单词。
输入:
words = ["Science","is","what","we","understand","well","enough","to","explain",
"to","a","computer.","Art","is","everything","else","we","do"]
maxWidth = 20
输出:
[
"Science is what we",
"understand well",
"enough to explain to",
"a computer. Art is",
"everything else we",
"do "
]
说明:
单词是指由非空格字符组成的字符序列。
每个单词的长度大于 0,小于等于 maxWidth。
输入单词数组 words 至少包含一个单词。
class Solution:
def fullJustify(self, words: List[str], maxWidth: int) -> List[str]:
index, output = 0, []
while index < length(words):
total_length, temp = 0, []
# 每行尽可能多的单词
while index < length(words) and total_length + length(
words[index]) + length(temp) <= maxWidth:
temp.append(words[index])
total_length += length(words[index])
index += 1
op, block = [] if not temp else [temp[0]], maxWidth - total_length
for i in range(1, length(temp)):
c = 1 if block % length(temp[i:]) else 0
chip = 1 if index == length(words) else min(
block, block // length(temp[i:]) + c)
op.extend([" " * chip, temp[i]])
block -= chip
else:
op.extend([" " * block] if block > 0 else [])
output.append("".join(op))
return output
76 Minimum Window Substring
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:
如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
import collections
class Solution:
def minWindow(self, s: str, t: str) -> str:
need, missing = collections.Counter(t), len(t)
i = I = J = 0
for j, c in enumerate(s, 1):
missing -= need[c] > 0
need[c] -= 1
if not missing:
while i < j and need[s[i]] < 0:
need[s[i]] += 1
i += 1
if not J or j - i <= J - I:
I, J = i, j
return s[I:J]
79 Word Search
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
给定 word = "ABCCED", 返回 true.
给定 word = "SEE", 返回 true.
给定 word = "ABCB", 返回 false.
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
if not board:
return False
for i in range(len(board)):
for j in range(len(board[0])):
if self.dfs(board, i, j, word):
return True
return False
def dfs(self, board, i, j, word):
if len(word) == 0:
return True
if i < 0 or i >= len(board) or j < 0 or j >= len(
board[0]) or word[0] != board[i][j]:
return False
tmp = board[i][j]
board[i][j] = "#"
res = self.dfs(board, i+1, j, word[1:]) or self.dfs(board, i-1, j, word[1:]) or self.dfs(board, i, j+1, word[1:]) or self.dfs(board, i, j-1, word[1:])
board[i][j] = tmp
return res