leetcode 31-40
31.下一个排列
给出一组由正整数构成的序列,要求重排得到字典序中下一个更大的排列,如不存在则排成最小排列,要求原地修改。
class Solution:
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
def reverse(nums, L, R):
while L < R:
nums[L], nums[R] = nums[R], nums[L]
L += 1
R -= 1
x = len(nums)-2
while x >= 0 and nums[x] >= nums[x+1]:
x -= 1
if x < 0:
reverse(nums, 0, len(nums)-1)
else:
y = len(nums)-1
while nums[y] <= nums[x]:
y -= 1
nums[x], nums[y] = nums[y], nums[x]
reverse(nums, x+1, len(nums)-1)
32.最长有效括号
给定一个只包含'('和')'的字符串,找出最长的包含有效括号的子串的长度。
class Solution:
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
stk = []
dp = [0] * (len(s)+1)
for i, j in enumerate(s):
if j == '(':
stk.append(i)
else:
if stk:
t = stk.pop()
dp[i] = i-t+1
if t: dp[i] += dp[t-1]
return max(dp)
33.搜索旋转数组
假设按照升序排序的数组在预先未知的某个点上进行了旋转,现要在数组中搜索一个给定的目标值,如果存在则返回索引,不存在返回-1。
class Solution:
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
def find1(L, R, nums, target):
if L > R: return -1
if nums[L] <= nums[R]:
return find2(L, R, nums, target)
M = L + (R-L) // 2
if nums[L] <= nums[M]:
if nums[L] <= target <= nums[M]:
return find2(L, M, nums, target)
return find1(M+1, R, nums, target)
else:
if nums[M] <= target <= nums[R]:
return find2(M, R, nums, target)
return find1(L, M-1, nums, target)
def find2(L, R, nums, target):
lo, hi = L, R
while lo <= hi:
mid = lo + (hi-lo) // 2
if nums[mid] < target:
lo = mid+1
elif nums[mid] > target:
hi = mid-1
else:
return mid
return -1
return find1(0, len(nums)-1, nums, target)
34.搜索范围
给定一个按照升序排列的整数数组和一个目标值,找出给定目标值在数组中的开始位置和结束位置,如不存在,则返回[-1,-1]。
class Solution:
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
def find1(nums, target):
if not nums: return -1
lo, hi = 0, len(nums)-1
while lo < hi:
mid = lo + (hi-lo) // 2
if nums[mid] < target:
lo = mid+1
elif nums[mid] > target:
hi = mid-1
else:
hi = mid
if lo < len(nums) and nums[lo] == target:
return lo
return -1
def find2(nums, target):
if not nums: return -1
lo, hi = 0, len(nums)-1
while lo < hi:
mid = lo + (hi-lo+1) // 2
if nums[mid] < target:
lo = mid+1
elif nums[mid] > target:
hi = mid-1
else:
lo = mid
if lo < len(nums) and nums[lo] == target:
return lo
return -1
L = find1(nums, target)
R = find2(nums, target)
return [L, R]
35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果不存在,则返回它将会被按顺序插入的位置。
class Solution:
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if not nums: return 0
lo, hi = 0, len(nums)-1
while lo < hi:
mid = lo + (hi - lo) // 2
if nums[mid] < target:
lo = mid+1
else:
hi = mid
if lo < len(nums) and nums[lo] >= target:
return lo
return lo+1
36.有效的数独
判断一个9x9的数独是否有效,注意给定的数独序列只包含数字1-9和字符'.',一个有效的数独不一定是可解的。
class Solution:
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
def ok(T):
s = set()
for i in T:
if i == '.': continue
if i in s: return False
s.add(i)
return True
for i in range(9):
t = []
for j in range(9):
t.append(board[i][j])
if not ok(t):
return False
for j in range(9):
t = []
for i in range(9):
t.append(board[i][j])
if not ok(t):
return False
for i in range(0,9,3):
for j in range(0,9,3):
t = []
for x in range(3):
for y in range(3):
t.append(board[i+x][j+y])
if not ok(t):
return False
return True
37.解数独
给定一个只包含数字1-9和字符'.'的数独序列,其中'.'代表未确定的数字,解出该数独。输入保证有唯一解。
class Solution:
def solveSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: void Do not return anything, modify board in-place instead.
"""
def ok(T):
s = set()
for i in T:
if i == '.': continue
if i in s: return False
s.add(i)
return True
def checkH(x):
t = []
for i in range(9):
t.append(board[x][i])
return ok(t)
def checkV(y):
t = []
for i in range(9):
t.append(board[i][y])
return ok(t)
def checkB(x, y):
t = []
for i in range(3):
for j in range(3):
t.append(board[x+i][y+j])
return ok(t)
def check(x, y):
return checkH(x) and checkV(y) and checkB(x//3*3, y//3*3)
def dfs(n):
if n == 81: return True
x, y = n//9, n%9
if board[x][y] != '.':
return dfs(n+1)
for i in range(1,10):
board[x][y] = str(i)
if check(x, y):
if dfs(n+1):
return True
board[x][y] = '.'
return False
dfs(0)
38.报数
报数序列是指一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。给定一个正整数n,输出报数序列的第n项。
class Solution:
def countAndSay(self, n):
"""
:type n: int
:rtype: str
"""
ans = '1'
for i in range(1, n):
tmp = ''
idx = 0
while idx < len(ans):
tag = ans[idx]
cnt = 0
while idx < len(ans) and ans[idx] == tag:
idx += 1
cnt += 1
tmp += str(cnt) + tag
ans = tmp
return ans
39.组合求和
给定一个无重复元素的数组candidates和一个目标数target,找出candidates中所有可以使数字和为target的组合,注意candidates中的数字可以无限制重复被选取,保证candidates中的数以及target都是正整数。输出结果要求不能包含重复的组合。
class Solution:
def combinationSum(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
def dfs(idx, cur, tmp, ans, candidates, target):
if cur > target: return
if cur == target:
ans.append(tmp.copy())
return
if idx == len(candidates):
return
dfs(idx+1, cur, tmp+[candidates[idx]], ans, candidates, target)
dfs(idx, cur+candidates[idx], tmp, ans, candidates, target)
ans = []
dfs(0, 0, [], ans, candidates, target)
return ans
40.组合总和II
给定一个数组candidates和一个目标数target,找出candidates中所有可以使数字和为target的组合,注意candidates中的数字在每个组合中最多只能使用一次,保证candidates中的数以及target都是正整数,要求解集不能包含重复的组合。
class Solution:
def combinationSum2(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
def dfs(idx, cur, tmp, ans, candidates, target):
if cur > target: return
if cur == target:
ans.add(tuple(tmp))
return
if idx == len(candidates):
return
dfs(idx+1, cur, tmp, ans, candidates, target)
dfs(idx+1, cur+candidates[idx], tmp+[candidates[idx]], ans, candidates, target)
ans = set()
candidates.sort()
dfs(0, 0, [], ans, candidates, target)
return sorted(list(ans))