动态规划之二:最长子系列问题(共五题)

题目一:(求最长相同字母)
给定一组字符串,包含大小写字母,求由同一字母组成的最长子串,字母不区分大小写。
例如:aAbbBBcccCC 最长子串:cccCC
例如:ddddDDDDeeeEEEeeeEEEeee 最长子串:eeeEEEeeeEEEeee

状态定义:dp[i]为以i为结尾的相同字母子串的长度

以字符串 "aAbbBBcc" 为例, 看状态变化.
字符串  a  A  b  b  B  B  c  c
状态值  1  2  1  2  3  4  1  2

得出状态转移方程为:
if s[i] == s[i-1]: dp[i] = dp[i-1] + 1
if s[i] != s[i-1]: dp[i] = 1

python代码如下:
def longestSameChars(s):
	if s == None : return None
	w = len(s)
	if w == 0 or w == 1 : return s
	dp = [ 1 for i in range(w) ]
	for i in range(1, w):
		if s[i].upper() == s[i-1].upper() : dp[i] = dp[i-1] + 1
		else : dp[i] = 1
	# 以下求出最大的相同字符子串开始索引和结束索引
	end, maxd = 0, 0
	for i in range( len(dp) ):
		if dp[i] > maxd:
			maxd = dp[i]
			end = i
	sta = end - maxd + 1
	return s[sta : end + 1 ]

题目二:(求最长连续上升子系列长度)
给定一个整数数组, 求数组当中的最长子串长度是多少?
例如: 1, 4, 3, 6 最长子串是 3 6 或者 1 4 长度都是2
例如: 15, 1, 5, 13, 6, 11, 7, 8 最长子串是 1, 5, 13 长度都是 3

状态定义:dp[i]为以i为结尾的最长子串长度.

以数组 [15, 1, 5, 13, 6, 11, 7, 8]为例,  看状态变化.
数组  15  1  5  13  6  11  7  8
状态  1   1  2  3   1  2   1  2  (最长连续上升子系列长度)

得出状态转移方程为:
if nums[i] > nums[i-1] : dp[i] = dp[i-1] + 1
if nums[i] <= nums[i-1]: dp[i] = 1

python 代码如下:
def lengthOfContinueLIS(nums):
	if len(nums) == 0 : return 0
	dp = [ 0 for i in range( len(nums) ) ]
	for i in range( 1, len(nums) ):
		if nums[i] > nums[i-1] : dp[i] = dp[i-1] + 1
		else : dp[i] = 1
	return max(dp)

题目三 :(求最长上升子系列长度)
给定一个整数数组, 求数组当中的最长上升子系列长度是多少?
例如: 1, 4, 3, 6 最长子串是1 3 6 或者 1 4 6 长度都是3
例如: 15, 1, 5, 13, 6, 11, 7, 8 最长上升子系列是 1, 5, 6, 7, 8 长度都是 5

状态定义:dp[i]为以i为结尾的最长上升子系列的长度.

以数组[10, 9, 2, 5, 3, 1, 7, 101, 18]为例,看状态的变化.
数组  10  9  2  5  3  1  7  101  18
状态  1   1  1  2  2  1  3  4    4  (最长上升子系列的长度)

当前索引i,找到一个i之前( 0 ~ i-1 )比i的值要小且dp值最大的值再+1
得出状态转移方程为:
for j in range( i ):
	if nums[j] < nums[i] : dp[i] = max( dp[i], dp[j] + 1 )
	
python代码如下:
def lengthOfLIS(nums):
	if len(nums) == 0 : return 0
	dp = [ 1 for i in range( len(nums) ) ]
	for i in range( 1, len(nums) ):
		for j in range( i ):
			if nums[j] < nums[i] : dp[i] = max( dp[i], dp[j] + 1 )
	return max(dp) 

题目四 : (求最长无重复字符子串的长度 )
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb” 输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb” 输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew” 输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。

状态定义: dp[i]以i为结尾的最长无重复字符子串的长度

以字符串 "abcabcbb" 为例, 看状态变化.
字符  a  b  c  a  b  c  b  b
状态  1  2  3  3  3  3  2  1  (最长无重复字符子串的长度)

状态转移方程:
for j in range( i - 1, -1, -1 ):
	if s[i] != s[j] : dp[i] += 1
	else : break
	
python代码如下:
def lenghtOfLongestSubstring(s):
	if len(s) == 0 or len(s) == 1 : return len(s)
	dp = [ 1 for i in range( len(s) ) ]
	for i in range( 1 , len(s) ):
		endfor = i - 1 - dp[i-1]
		for j in range( i - 1, endfor, -1 ):
			if s[i] != s[j] : dp[i] += 1
			else : break
	return max(dp)

题目五 :(求最长交替子系列长度)
一个系列,它的相邻数字的大小关系就是升序降序轮流交替的(最初可以是升序,也可以是降序),
就称为wiggle sequence.比如[ 1, 7, 4, 9, 2, 5, ]就是一个wiggle sequence.但是[ 1, 4, 7, 2, 5]
和[1, 7, 4, 5, 5]就不是. 给出一个数组,求出它的最长wiggle sequence子系列.

状态定义: dp[i]以i为结尾的最大摆动系列的长度

以数组[10, 9, 2, 5, 5, 1, 7, 11, 8]为例,看状态的变化.
数组   10  9   2   5   5   1   7   11   8
状态st 0  -1  -1   1   1  -1   1   1   -1  (状态st 保存[1:上升,-1:下降,0:相等]信息)
状态dp 1   2   2   3   3   4   5   5    6  (状态dp 最大摆动系列的长度)

状态转移方程(伪代码):
if nums[i] == nums[i-1] : 
	st[i], dp[i] = st[i-1], dp[i-1]
if nums[i] > nums[i-1]:
	st[i] = 1
	if st[i-1] == 1 : dp[i] = dp[i-1]
	if st[i-1] == -1 : dp[i] = dp[i-1] + 1
if nums[i] < nums[i-1]:
	st[i] = -1
	if st[i-1] == -1 : dp[i] = dp[i-1]
	if st[i-1] == 1 : dp[i] = dp[i-1] + 1

python代码如下:
def wiggleMaxLenght(nums):
	if nums == None : return None
	w = len(nums)
	if w == 0 or w == 1 : return w
	dp , st = [ 1 for i in range(w) ], [ 0 for i in range(w) ]
	for i in range( 1, w ):
		if nums[i] == nums[i-1] : 
			st[i], dp[i] = st[i-1], dp[i-1]
		elif nums[i] > nums[i-1]:
			st[i] = 1
			dp[i] = dp[i-1] if st[i-1] == 1 else dp[i-1] + 1
		else:
			st[i] = -1
			dp[i] = dp[i-1] if st[i-1] == -1 else dp[i-1] + 1
	return dp[-1]

你可能感兴趣的:(动态规划,动态规划,算法,leetcode,python)