Zhuanli&Blog


  • 首页

  • 标签

  • 分类

  • 归档

leetcode 301. 删除无效的括号

发表于 2018-07-30 | 分类于 leetcode

Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.

Note: The input string may contain letters other than the parentheses ( and ).

Example 1:

Input: "()())()"
Output: ["()()()", "(())()"]

Example 2:

Input: "(a)())()"
Output: ["(a)()()", "(a())()"]

Example 3:

Input: ")("
Output: [""]
  • bfs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from collections import deque
class Solution(object):
def removeInvalidParentheses(self, s):
self.solution_found = False
self.visited_potential_solutions = set()
self.results = set()
self.bfs(s,0)
return list(self.results)

def bfs(self, s, characters_removed):
if s is "" or s is None:
return
queue = deque()
queue.append(s)
while queue:
current = queue.popleft()
if self.is_valid(current):
self.solution_found = True
self.results.add(current)
continue
if self.solution_found:
continue
for i,c in enumerate(current):
if not self.is_parenthesis(c):
continue
potential_solution = current[:i]+current[i+1:]
if potential_solution not in self.visited_potential_solutions:
self.visited_potential_solutions.add(potential_solution)
queue.append(potential_solution)

def is_valid(self, s):
summatory = 0
for c in s:
if c == '(':
summatory += 1
if c == ')':
summatory -= 1
if summatory < 0:
return False
return summatory == 0

def is_parenthesis(self, c):
return c in ['(', ')']
  • dfs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution(object):
def removeInvalidParentheses(self, s):
self.ans = []
self.dfs(s, 0, 0, ['(',')'])
if len(self.ans) == 0:
return [""]
return self.ans

def dfs(self, s, last_i, last_j, par):
count = 0
for i in range(last_i, len(s)):
if s[i] == par[0]: count +=1
if s[i] == par[1]: count -=1
if count >=0:
continue
for j in range ( last_j, i+1):
if s[j] == par[1] and (j == last_j or s[j-1] != par[1]):
self.dfs(s[:j] + s[j+1:], i, j, par )
return

s_reversed = s[::-1]
if par[0] == '(':
self.dfs(s_reversed, 0, 0, [')','('])
else:
self.ans.append(s_reversed)

leetcode 306. 累加数

发表于 2018-07-26 | 分类于 leetcode

累加数是一个字符串,组成它的数字可以形成累加序列。

一个有效的累加序列必须至少包含 3 个数。除了最开始的两个数以外,字符串中的其他数都等于它之前两个数相加的和。

给定一个只包含数字 '0'-'9'的字符串,编写一个算法来判断给定输入是否是累加数。

说明: 累加序列里的数不会以 0 开头,所以不会出现 1, 2, 03 或者 1, 02, 3 的情况。

示例 1:

输入: "112358"
输出: true 
解释: 累加序列为: 1, 1, 2, 3, 5, 8 。1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, 3 + 5 = 8

示例 2:

输入: "199100199"
输出: true 
解释: 累加序列为: 1, 99, 100, 199。1 + 99 = 100, 99 + 100 = 199

进阶:

  • 你如何处理一个溢出的过大的整数输入?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution(object):
def isAdditiveNumber(self, num):
"""
:type num: str
:rtype: bool
"""
def dfs(numstr,res):
if len(res) >= 3 and res[-2] + res[-3] != res[-1]:return False
if not numstr and len(res) >= 3:return True
for i in range(len(numstr)):
curr = numstr[:i+1]
if curr[0] == '0' and len(curr) != 1:continue
if dfs(numstr[i+1:],res+[int(curr)]):return True
return False
return dfs(num,[])

leetcode 188. 买卖股票的最佳时机 IV

发表于 2018-07-25 | 分类于 leetcode

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。

注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: [2,4,1], k = 2
输出: 2
解释: 在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。

示例 2:

输入: [3,2,6,5,0,3], k = 2
输出: 7
解释: 在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
     随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution(object):
def maxProfit(self, k, prices):
"""
:type k: int
:type prices: List[int]
:rtype: int
"""
n = len(prices)
if n < 2:return 0
if n <= 2*k:
return sum(i-j for i,j in zip(prices[1:],prices[:-1]) if i-j > 0)
dp = [[0]*n for _ in range(k+1)]
for i in range(1,k+1):
tmp = [0]*n
for j in range(1,n):
profit = prices[j] - prices[j-1]
tmp[j] = max(tmp[j-1]+profit,dp[i-1][j-1]+profit,dp[i-1][j-1])
dp[i][j] = max(tmp[j],dp[i][j-1])
return dp[k][-1]

leetcode 307. 区域和检索 - 数组可修改

发表于 2018-07-25 | 分类于 leetcode

给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点。

update(i, val) 函数可以通过将下标为 i 的数值更新为 val,从而对数列进行修改。

示例:

Given nums = [1, 3, 5]

sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8

说明:

  • 数组仅可以在 update 函数下进行修改。
  • 你可以假设 update 函数与 sumRange 函数的调用次数是均匀分布的。

正常的思路容易想到每次求和的时间复杂度为O(n), 更新数组元素的时间复杂度为O(1), 因此总体的时间复杂度为 O(n)。但是通过使用segment tree可以将求和以及更新数组元素操作的时间复杂度均变为 O(log2n)。

Segment Tree是一棵二叉树,其特点为叶子节点个数与数组的长度相同 从左到右依次为数组中下标从小到大的元素的值,父节点的值为其左右的叶子节点的值的和。如下图是一个简单的例子

因此可以看到每个非叶子节点的值均是代表了数组某个区间的和。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class NumArray(object):
def __init__(self, nums):
"""
initialize your data structure here.
:type nums: List[int]
"""
n = len(nums)
if n == 0: return
max_size = 2 * pow(2, int(math.ceil(math.log(n, 2)))) - 1
self.seg_tree = [0 for i in xrange(max_size)]
self.nums = nums[:]
self.build_tree(0, n-1, 0)

def build_tree(self, start, end, curr):#构造segment tree
if start > end: return # empty list
if start == end:
self.seg_tree[curr] = self.nums[start]
else:
mid = start + (end - start)/2
self.seg_tree[curr] = self.build_tree(start, mid, curr*2+1) + self.build_tree(mid+1, end, curr*2+2)
return self.seg_tree[curr]

def update(self, i, val):
"""
:type i: int
:type val: int
:rtype: int
"""
diff = val - self.nums[i]
self.nums[i] = val
self.update_sum(0, len(self.nums)-1, i, 0, diff)

def update_sum(self, start, end, idx, curr, diff):#更新segment tree某个元素的值
self.seg_tree[curr] += diff
if start == end: return
mid = start + (end - start)/2
if start <= idx <= mid:
self.update_sum(start, mid, idx, curr*2+1, diff)
else:
self.update_sum(mid+1, end, idx, curr*2+2, diff)

def sumRange(self, i, j):
"""
sum of elements nums[i..j], inclusive.
:type i: int
:type j: int
:rtype: int
"""
return self.get_sum(0, len(self.nums)-1, i, j, 0)

def get_sum(self, start, end, qstart, qend, curr):#segment tree特定区间求和
mid = start + (end - start)/2
if qstart > end or qend < start:
return 0
elif start >= qstart and end <= qend:
return self.seg_tree[curr]
else:
return self.get_sum(start, mid, qstart, qend, curr*2+1) + self.get_sum(mid+1, end, qstart, qend, curr*2+2)

leetcode 304. 二维区域和检索 - 矩阵不可变

发表于 2018-07-25 | 分类于 leetcode

给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2)。
sd
Range Sum Query 2D
上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = (4, 3),该子矩形内元素的总和为 8。

示例:

给定 matrix = [
  [3, 0, 1, 4, 2],
  [5, 6, 3, 2, 1],
  [1, 2, 0, 1, 5],
  [4, 1, 0, 1, 7],
  [1, 0, 3, 0, 5]
]

sumRegion(2, 1, 4, 3) -> 8
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2, 2, 4) -> 12

说明:

  • 你可以假设矩阵不可变。
  • 会多次调用 sumRegion 方法。
  • 你可以假设 row1 ≤ row2 且 col1 ≤ col2。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class NumMatrix(object):

def __init__(self, matrix):
"""
:type matrix: List[List[int]]
"""
if not matrix or not matrix[0]:
self.matrix = None
return
self.rows = len(matrix)
self.cols = len(matrix[0])
self.matrix = matrix
self.SM = [[0]*self.cols for _ in range(self.rows)]
self.update()

def update(self):
if self.rows > 0 and self.cols > 0:self.SM[0][0] = self.matrix[0][0]
for i in range(1,self.rows):
self.SM[i][0] = self.SM[i-1][0] + self.matrix[i][0]
for j in range(1,self.cols):
self.SM[0][j] = self.SM[0][j-1] + self.matrix[0][j]
for i in range(1,self.rows):
for j in range(1,self.cols):
self.SM[i][j] = self.SM[i-1][j] + self.SM[i][j-1] - self.SM[i-1][j-1] + self.matrix[i][j]

def sumRegion(self, row1, col1, row2, col2):
if self.matrix == None or (self.rows == self.cols and self.rows == 0) or row1<0 or row1>=self.rows or row2<0 or row2>=self.rows or col1<0 or col1>=self.cols or col2<0 or col2>=self.cols:return 0
up = self.SM[row1-1][col2] if row1 >= 1 else 0
diag = self.SM[row1-1][col1-1] if row1 >= 1 and col1 >= 1 else 0
left = self.SM[row2][col1-1] if col1 >= 1 else 0
return self.SM[row2][col2]- up - left + diag


# Your NumMatrix object will be instantiated and called as such:
# obj = NumMatrix(matrix)
# param_1 = obj.sumRegion(row1,col1,row2,col2)

c语言实现解析转义字符串

发表于 2018-07-24 | 分类于 c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(const char *str)
{
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!='\"') {return 0;} /* not a string! */

while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */

out=(char*)malloc(len+1); /* This is how long we need for the string, roughly. */
if (!out) return 0;

ptr=str+1;ptr2=out;
while (*ptr!='\"' && *ptr)
{
if (*ptr!='\\') *ptr2++=*ptr++;
else
{
ptr++;
switch (*ptr)
{
case 'b': *ptr2++='\b'; break;
case 'f': *ptr2++='\f'; break;
case 'n': *ptr2++='\n'; break;
case 'r': *ptr2++='\r'; break;
case 't': *ptr2++='\t'; break;
case 'u': /* transcode utf16 to utf8. */
sscanf(ptr+1,"%4x",&uc);ptr+=4; /* get the unicode char. */

if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */

if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
{
if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */
sscanf(ptr+3,"%4x",&uc2);ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */
uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
}

len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;

switch (len) {
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=len;
break;
default: *ptr2++=*ptr; break;
}
ptr++;
}
}
*ptr2=0;
if (*ptr=='\"') ptr++;
return out;
}
int main(void) {
printf("%s\r\n","hh\r\nh");
return 0;
}

leetcode 309. 最佳买卖股票时机含冷冻期

发表于 2018-07-24 | 分类于 leetcode

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

示例:

输入: [1,2,3,0,2]
输出: 3 
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution(object):
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
n = len(prices)
if n == 0:return 0
buy = [0]*n
sell = [0]*n
cool = [0]*n
buy[0] = -prices[0]
for i in range(1,n):
buy[i] = max(buy[i-1],cool[i-1]-prices[i])
sell[i] = max(sell[i-1],buy[i-1]+prices[i])
cool[i] = max(cool[i-1],sell[i-1])
return sell[-1]

leetcode 310. 最小高度树

发表于 2018-07-23 | 分类于 leetcode

对于一个具有树特征的无向图,我们可选择任何一个节点作为根。图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树。给出这样的一个图,写出一个函数找到所有的最小高度树并返回他们的根节点。

格式

该图包含 n 个节点,标记为 0 到 n - 1。给定数字 n 和一个无向边 edges 列表(每一个边都是一对标签)。

你可以假设没有重复的边会出现在 edges 中。由于所有的边都是无向边, [0, 1]和 [1, 0] 是相同的,因此不会同时出现在 edges 里。

示例 1:

输入: n = 4, edges = [[1, 0], [1, 2], [1, 3]]

        0
        |
        1
       / \
      2   3 

输出: [1]

示例 2:

输入: n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]

     0  1  2
      \ | /
        3
        |
        4
        |
        5 

输出: [3, 4]

说明:

  • 根据树的定义,树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。
  • 树的高度是指根节点和叶子节点之间最长向下路径上边的数量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution:
def findMinHeightTrees(self, n, edges):
if n == 1: return [0]
adj = [set() for _ in xrange(n)]
for i, j in edges:
adj[i].add(j)
adj[j].add(i)

leaves = [i for i in xrange(n) if len(adj[i]) == 1]

while n > 2:
n -= len(leaves)
newLeaves = []
for i in leaves:
j = adj[i].pop()
adj[j].remove(i)
if len(adj[j]) == 1: newLeaves.append(j)
leaves = newLeaves
return leaves

leetcode 312. 戳气球

发表于 2018-07-20 | 分类于 leetcode

有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。

现在要求你戳破所有的气球。每当你戳破一个气球 i 时,你可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。

求所能获得硬币的最大数量。

说明:

  • 你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。
  • 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100

示例:

输入: [3,1,5,8]
输出: 167 
解释: nums = [3,1,5,8] --> [3,5,8] -->   [3,8]   -->  [8]  --> []
     coins =  3*1*5      +  3*5*8    +  1*3*8      + 1*8*1   = 167
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
def maxCoins(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
#dp[i][j] = max(dp[i][j], nums[i] * nums[k] * nums[j] + dp[i][k] + dp[k][j]) # i < k < j
nums = [1] + nums + [1]
n = len(nums)
dp = [[0]*n for _ in range(n)]
for gap in range(2,n):
for i in range(n-gap):
j = gap+i
for k in range(i+1,j):
dp[i][j] = max(dp[i][j], nums[i] * nums[k] * nums[j] + dp[i][k] + dp[k][j])
return dp[0][n-1]

recursion solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution:
def maxCoins(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
#dp[i][j] = max(dp[i][j], nums[i] * nums[k] * nums[j] + dp[i][k] + dp[k][j]) # i < k < j
nums = [1] + nums + [1]
n = len(nums)
dp = [[0]*n for _ in range(n)]
def cal(i,j):
if dp[i][j] or j == i+1:
return dp[i][j]
coins = 0
for k in range(i+1,j):
coins = max(coins,nums[i]*nums[k]*nums[j] + cal(i,k)+cal(k,j))
dp[i][j] = coins
return coins
return cal(0,n-1)

leetcode 313. 超级丑数

发表于 2018-07-19 | 分类于 leetcode

编写一段程序来查找第 n 个超级丑数。

超级丑数是指其所有质因数都是长度为 k 的质数列表 primes 中的正整数。

示例:

输入: n = 12, primes = [2,7,13,19]
输出: 32 
解释: 给定长度为 4 的质数列表 primes = [2,7,13,19],前 12 个超级丑数序列为:[1,2,4,7,8,13,14,16,19,26,28,32] 。

说明:

  • 1 是任何给定 primes 的超级丑数。
  • 给定 primes 中的数字以升序排列。
  • 0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000 。
  • 第 n 个超级丑数确保在 32 位有符整数范围内。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution(object):
def nthSuperUglyNumber(self, n, primes):
"""
:type n: int
:type primes: List[int]
:rtype: int
"""
res = [1]
idx = [0]*len(primes)
for i in range(n-1):
minv = min([res[idx[k]]*primes[k] for k in range(len(primes))])
for j in range(len(primes)):
if minv == res[idx[j]]*primes[j]:
idx[j] += 1
res.append(minv)
return res[-1]

a faster solution use heap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from heapq import heappush, heappop

class Solution:
def nthSuperUglyNumber(self, n, primes):
"""
:type n: int
:type primes: List[int]
:rtype: int
"""
res, idx, ugly_by_last_prime = [1] * n, [0] * len(primes), [0] * n

heap = [(p, k) for k, p in enumerate(primes)]
print(heap)
for i in range(1, n):
res[i], k = heappop(heap)
print(res[i],k)
ugly_by_last_prime[i] = k
idx[k] += 1
while ugly_by_last_prime[idx[k]] > k:
idx[k] += 1
heappush(heap, (primes[k] * res[idx[k]], k))

return res[-1]
1…8910…20

zhuanli

194 日志
9 分类
41 标签
GitHub
© 2018 — 2019 zhuanli
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4