上药三品,神与气精

曾因酒醉鞭名马 生怕情多累美人


  • 首页

  • 关于

  • 分类

  • 标签

  • 归档

  • 搜索

dp003

发表于 2019-03-21 | 阅读次数:
字数统计: 512 | 阅读时长 ≈ 2
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

#!/usr/bin/python
# -*- coding: UTF-8 -*-

from typing import List


def longest_increasing_subsequence(nums: List[int]) -> int:
"""
最长子上升序列的一种DP解法,从回溯解法转化,思路类似于有限物品的背包问题
每一次决策都算出当前可能的lis的长度,重复子问题合并,合并策略是lis的末尾元素最小
时间复杂度:O(n^2)
空间复杂度:O(n^2),可优化至O(n)
没leetcode上的参考答案高效,提供另一种思路作为参考
https://leetcode.com/problems/longest-increasing-subsequence/solution/
:param nums:
:return:
"""
if not nums:
return 0

n = len(nums)
# memo[i][j] 表示第i次决策,长度为j的lis的 最小的 末尾元素数值
# 每次决策都根据上次决策的所有可能转化,空间上可以类似背包优化为O(n)
memo = [[-1] * (n+1) for _ in range(n)]

# 第一列全赋值为0,表示每次决策都不选任何数
for i in range(n):
memo[i][0] = 0
# 第一次决策选数组中的第一个数
memo[0][1] = nums[0]

for i in range(1, n):
for j in range(1, n+1):
# case 1: 长度为j的lis在上次决策后存在,nums[i]比长度为j-1的lis末尾元素大
if memo[i-1][j] != -1 and nums[i] > memo[i-1][j-1]:
memo[i][j] = min(nums[i], memo[i-1][j])

# case 2: 长度为j的lis在上次决策后存在,nums[i]比长度为j-1的lis末尾元素小/等
if memo[i-1][j] != -1 and nums[i] <= memo[i-1][j-1]:
memo[i][j] = memo[i-1][j]

if memo[i-1][j] == -1:
# case 3: 长度为j的lis不存在,nums[i]比长度为j-1的lis末尾元素大
if nums[i] > memo[i-1][j-1]:
memo[i][j] = nums[i]
# case 4: 长度为j的lis不存在,nums[i]比长度为j-1的lis末尾元素小/等
break

for i in range(n, -1, -1):
if memo[-1][i] != -1:
return i


if __name__ == '__main__':
# 要求输入的都是大于0的正整数(可优化至支持任意整数)
nums = [2, 9, 3, 6, 5, 1, 7]
print(longest_increasing_subsequence(nums))

dp002

发表于 2019-03-21 | 分类于 leetcode | 阅读次数:
字数统计: 318 | 阅读时长 ≈ 1
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
65

#!/usr/bin/python
# -*- coding: UTF-8 -*-

from typing import List

Layer_nums = List[int]


def yh_triangle(nums: List[Layer_nums]) -> int:
"""
从根节点开始向下走,过程中经过的节点,只需存储经过它时最小的路径和
:param nums:
:return:
"""
assert len(nums) > 0
n = len(nums) # 层数
memo = [[0]*n for i in range(n)]
memo[0][0] = nums[0][0]

for i in range(1, n):
for j in range(i+1):
# 每一层首尾两个数字,只有一条路径可以到达
if j == 0:
memo[i][j] = memo[i-1][j] + nums[i][j]
elif j == i:
memo[i][j] = memo[i-1][j-1] + nums[i][j]
else:
memo[i][j] = min(memo[i-1][j-1] + nums[i][j], memo[i-1][j] + nums[i][j])
return min(memo[n-1])


def yh_triangle_space_optimization(nums: List[Layer_nums]) -> int:
assert len(nums) > 0
n = len(nums)
memo = [0] * n
memo[0] = nums[0][0]

for i in range(1, n):
for j in range(i, -1, -1):
if j == i:
memo[j] = memo[j-1] + nums[i][j]
elif j == 0:
memo[j] = memo[j] + nums[i][j]
else:
memo[j] = min(memo[j-1] + nums[i][j], memo[j] + nums[i][j])
return min(memo)


def yh_triangle_bottom_up(nums: List[Layer_nums]) -> int:
assert len(nums) > 0
n = len(nums)
memo = nums[-1].copy()

for i in range(n-1, 0, -1):
for j in range(i):
memo[j] = min(memo[j] + nums[i-1][j], memo[j+1] + nums[i-1][j])
return memo[0]


if __name__ == '__main__':
nums = [[3], [2, 6], [5, 4, 2], [6, 0, 3, 2]]
print(yh_triangle(nums))
print(yh_triangle_space_optimization(nums))
print(yh_triangle_bottom_up(nums))

dp001

发表于 2019-03-21 | 分类于 leetcode | 阅读次数:
字数统计: 358 | 阅读时长 ≈ 1

动态规化

寻求最优解 比如最大值 最小值 降低时间复杂度

0-1背包

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

from typing import List, Tuple


def bag(items_info: List[int], capacity: int) -> int:
"""
固定容量的背包,计算能装进背包的物品组合的最大重量
:param items_info: 每个物品的重量
:param capacity: 背包容量
:return: 最大装载重量
"""
n = len(items_info)
memo = [[-1]*(capacity+1) for i in range(n)]
memo[0][0] = 1
if items_info[0] <= capacity:
memo[0][items_info[0]] = 1

for i in range(1, n):
for cur_weight in range(capacity+1):
if memo[i-1][cur_weight] != -1:
memo[i][cur_weight] = memo[i-1][cur_weight] # 不选
if cur_weight + items_info[i] <= capacity: # 选
memo[i][cur_weight + items_info[i]] = 1

for w in range(capacity, -1, -1):
if memo[-1][w] != -1:
return w


def bag_with_max_value(items_info: List[Tuple[int, int]], capacity: int) -> int:
"""
固定容量的背包,计算能装进背包的物品组合的最大价值
:param items_info: 物品的重量和价值
:param capacity: 背包容量
:return: 最大装载价值
"""
n = len(items_info)
memo = [[-1]*(capacity+1) for i in range(n)]
memo[0][0] = 0
if items_info[0][0] <= capacity:
memo[0][items_info[0][0]] = items_info[0][1]

for i in range(1, n):
for cur_weight in range(capacity+1):
if memo[i-1][cur_weight] != -1:
memo[i][cur_weight] = memo[i-1][cur_weight]
if cur_weight + items_info[i][0] <= capacity:
memo[i][cur_weight + items_info[i][0]] = max(memo[i][cur_weight + items_info[i][0]],
memo[i-1][cur_weight] + items_info[i][1])
return max(memo[-1])


if __name__ == '__main__':
# [weight, ...]
items_info = [2, 2, 4, 6, 3]
capacity = 9
print(bag(items_info, capacity))

# [(weight, value), ...]
items_info = [(3, 5), (2, 2), (1, 4), (1, 2), (4, 10)]
capacity = 8
print(bag_with_max_value(items_info, capacity))

字符串之字典树

发表于 2019-03-21 | 分类于 leetcode | 阅读次数:
字数统计: 152 | 阅读时长 ≈ 1
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


class TrieNode:
def __init__(self, data: str):
self._data = data
self._children = [None] * 26
self._is_ending_char = False


class Trie:
def __init__(self):
self._root = TrieNode("/")

def insert(self, text: str) -> None:
node = self._root
for index, char in map(lambda x: (ord(x) - ord("a"), x), text):
if not node._children[index]:
node._children[index] = TrieNode(char)
node = node._children[index]
node._is_ending_char = True

def find(self, pattern: str) -> bool:
node = self._root
for index in map(lambda x: ord(x) - ord("a"), pattern):
if not node._children[index]: return False
node = node._children[index]
return node._is_ending_char


if __name__ == "__main__":

strs = ["how", "hi", "her", "hello", "so", "see"]
trie = Trie()
for s in strs:
trie.insert(s)

for s in strs:
print(trie.find(s))

print(trie.find("swift"))

字符串匹配-kmp

发表于 2019-03-20 | 分类于 leetcode | 阅读次数:
字数统计: 268 | 阅读时长 ≈ 1
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

from typing import List

def kmp(s: int, pattern: int) -> int:
m = len(pattern)
partial_match_table = _get_partial_match_table(pattern)
j = 0
for i in range(len(s)):
while j >= 0 and s[i] != pattern[j]:
j = partial_match_table[j]
j += 1
if j == m:
return i - m + 1
return -1


def _get_partial_match_table(pattern: int) -> List[int]:
# Denote πᵏ(i) as π applied to i for k times,
# i.e., π²(i) = π(π(i)).
# Then we have the result:
# π(i) = πᵏ(i-1) + 1,
# where k is the smallest integer such that
# pattern[πᵏ(i-1)+1] == pattern[i].

# The value of π means the maximum length
# of proper prefix/suffix.
# The index of π means the length of the prefix
# considered for pattern.
# For example, π[2] means we are considering the first 2 characters
# of the pattern.
# If π[2] == 1, it means for the prefix of the pattern, P[0]P[1],
# it has a maximum length proper prefix of 1, which is also the
# suffix of P[0]P[1].
# We also add a π[0] == -1 for easier handling of boundary
# condition.

m = len(pattern)
π = [0] * (m + 1)
π[0] = k = -1 # We use k here to represent πᵏ(i)
for i in range(1, m + 1):
while k >= 0 and pattern[k] != pattern[i - 1]:
k = π[k]
k += 1
π[i] = k
return π


if __name__ == "__main__":

s = "abc abcdab abcdabcdabde"
pattern = "bcdabd"
print(kmp(s, pattern), s.find(pattern))

s = "hello"
pattern = "ll"
print(kmp(s, pattern), s.find(pattern))
1…262728…109
John Cheung

John Cheung

improve your python skills

543 日志
33 分类
45 标签
RSS
GitHub Email
© 2020 John Cheung
本站访客数:
|
主题 — NexT.Pisces v5.1.4
博客全站共226.3k字