1、答:
定义:
m
a
x
S
u
m
i
为
A
[
1
,
.
.
.
i
]
连
续
子
数
组
的
最
大
和
;
s
u
m
i
为
当
前
连
续
子
数
组
的
和
maxSum_i为A[1,...i]连续子数组的最大和;sum_i为当前连续子数组的和
maxSumi为A[1,...i]连续子数组的最大和;sumi为当前连续子数组的和,则有
递推方程:
s u m i = A [ i ] i f i = 1 或 s u m i − 1 < 0 s u m i = s u m i − 1 + A [ i ] i f s u m i − 1 > = 0 m a x S u m i = A [ i ] i f i = 1 m a x S u m i = M a x ( m a x S u m i − 1 , s u m i ) sum_i = A[i] \qquad if \;i = 1\;或 \;sum_{i-1} < 0\\ sum_i = sum_{i-1} + A[i] \qquad if\; sum_{i-1} >=0\\ maxSum_i = A[i] \qquad if \; i = 1 \\ maxSum_i = Max(maxSum_{i-1}, sum_i) sumi=A[i]ifi=1或sumi−1<0sumi=sumi−1+A[i]ifsumi−1>=0maxSumi=A[i]ifi=1maxSumi=Max(maxSumi−1,sumi)
算法伪代码:
- 输入: 数 组 A [ 1 , 2.... n ] 数组A[1,2....n] 数组A[1,2....n]
- 输出:连续子数组的最大和
maxSubArray(A)
maxSum <- A[1];
sum <- A[1];
for i <- 2 to n
if sum < 0 Then
sum <- A[i];
else
sum <- sum + A[i];
maxSum = Max(maxSum, sum);
return maxSum;
时间复杂度分析:
- 输入规模: n n n
- 复杂度: O ( n ) O(n) O(n)
2、答:
定义:
d
p
i
为
爬
到
第
i
阶
台
阶
的
方
法
数
dp_i 为爬到第i阶台阶的方法数
dpi为爬到第i阶台阶的方法数,则有
递推方程:
d p 1 = 1 d p 2 = 2 d p i = d p i − 1 + d p i − 2 dp_1 = 1 \quad dp_2 = 2\\ dp_i = dp_{i-1} + dp_{i-2} dp1=1dp2=2dpi=dpi−1+dpi−2
算法伪代码:
- 输入:台阶阶数 n n n
- 输出:爬到 n n n阶的方法数
climbStairs(n)
if n == 1 Then return 1;
if n == 2 Then return 2;
dp_i_1 <- 2;
dp_i_2 <- 1;
for i <- 3 to n
dp_i <- dp_i_1 + dp_i_2;
dp_i_2 = dp_i_1;
dp_i_1 = dp_i;
return dp_i;
时间复杂度分析:
- 输入规模: log n \log{n} logn
- 复杂度: O ( 2 log n ) O(2^{\log{n}}) O(2logn)
3、答:
定义:
d
p
[
i
]
[
j
]
记
录
字
符
串
S
中
s
i
s
i
+
1
.
.
.
s
j
子
串
是
否
为
回
文
的
dp[i][j]记录字符串S中s_is_{i+1}...s_j子串是否为回文的
dp[i][j]记录字符串S中sisi+1...sj子串是否为回文的,则有
递推方程:
d p [ i ] [ i ] = T r u e d p [ i ] [ i + 1 ] = T r u e i f s i = s i + 1 d p [ i ] [ j ] = T r u e i f d p [ i + 1 ] [ j − 1 ] = T r u e 且 s i = s j dp[i][i] = True \\ dp[i][i + 1] = True \quad if \; s_i = s_{i+1} \\ dp[i][j] = True \quad if \; dp[i + 1][j - 1] = True 且 s_i = s_j dp[i][i]=Truedp[i][i+1]=Trueifsi=si+1dp[i][j]=Trueifdp[i+1][j−1]=True且si=sj
算法伪代码:
- 输入:字符串 S S S
- 输出:最长回文子串 S ′ S' S′
longestPalindrome(S)
n <- S.length;
dp <- new boolean[n][n]
start <- 1;
maxL <- 1;
if n <= 1 Then return S;
for i <-1 to n
dp[i][i] <- True;
for i <-1 to n - 1
if S[i] = S[i + 1] Then
dp[i][i + 1] <- True;
start <- i;
maxL <- 2;
for gap <- 2 to n - 1
for i <- 1 to n - gap - i
j <- i + gap;
if dp[i + 1][j - 1] && S[i] = S[j] Then
dp[i][j] <- True;
start <- i;
maxL <- gap + 1;
return S.subString(start, start + gap);
时间复杂度分析:
- 输入规模: n n n
- 复杂度: O ( n 2 ) O(n^2) O(n2)
4、答:
定义:
d
p
[
i
]
[
j
]
记
录
到
达
网
格
A
第
i
行
第
j
列
,
最
短
路
径
dp[i][j] 记录到达网格A第i行第j列,最短路径
dp[i][j]记录到达网格A第i行第j列,最短路径,则有
递推方程:
d p [ i ] [ j ] = A [ i ] [ j ] i f i = 1 且 j = 1 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + A [ i ] [ j ] i f j = 1 且 i > = 2 d p [ i ] [ j ] = d p [ i ] [ j − 1 ] + A [ i ] [ j ] i f i = 1 且 j > = 2 d p [ i ] [ j ] = M i n ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) + A [ i ] [ j ] dp[i][j] = A[i][j] \quad if \; i = 1 且 j = 1\\ dp[i][j] = dp[i - 1][j] + A[i][j] \quad if \; j = 1 且 i >=2\\ dp[i][j] = dp[i][j - 1] + A[i][j] \quad if \; i = 1 且 j >= 2\\ dp[i][j] = Min(dp[i - 1][j], dp[i][j - 1]) + A[i][j] dp[i][j]=A[i][j]ifi=1且j=1dp[i][j]=dp[i−1][j]+A[i][j]ifj=1且i>=2dp[i][j]=dp[i][j−1]+A[i][j]ifi=1且j>=2dp[i][j]=Min(dp[i−1][j],dp[i][j−1])+A[i][j]
算法伪代码:
- 输入:网格 A [ 1... m ] [ 1... n ] A[1...m][1...n] A[1...m][1...n]
- 输出:到达网格第m行第n列的最短路径
findPath(A, m, n)
dp <- new int[m][n];
dp[1][1] <- A[1][1];
path <- new Stack()
for i <- 2 to m
dp[i][1] <- dp[i - 1][1] + A[i][1];
for j <- 2 to n
dp[1][j] <- dp[1][j - 1] + A[1][j];
for i <- 2 to m
for j <- 2 to n
dp[i][j] <- Min(dp[i - 1][j],dp[i][j - 1]) + A[i][j];
i <- m; j <- n;
while i >= 1 && j >= 1
d <- dp[i][j] - A[i][j]
if i > 1 && dp[i - 1][j] == d Then
path.push(DOWN);
else
path.push(RIGHT);
return path;
时间复杂度分析:
- 输入规模: m n mn mn
- 复杂度: O ( m n ) O(mn) O(mn)
5、答:
定义:
d
p
[
i
]
[
j
]
为
i
时
刻
j
位
置
可
以
收
到
得
最
多
馅
饼
数
dp[i][j]为i时刻j位置可以收到得最多馅饼数
dp[i][j]为i时刻j位置可以收到得最多馅饼数
递推方程:
d
p
[
i
]
[
j
]
=
P
[
i
]
[
j
]
i
f
i
=
1
且
j
=
4
,
5
,
6
d
p
[
i
]
[
j
]
=
M
a
x
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
−
1
]
[
j
−
1
]
,
d
p
[
i
−
1
]
[
j
+
1
]
)
+
P
[
i
]
[
j
]
dp[i][j] = P[i][j] \quad if \; i = 1 且 j = 4, 5, 6\\ dp[i][j] = Max(dp[i - 1][j], dp[i - 1][j - 1], dp[i - 1][j + 1]) + P[i][j]
dp[i][j]=P[i][j]ifi=1且j=4,5,6dp[i][j]=Max(dp[i−1][j],dp[i−1][j−1],dp[i−1][j+1])+P[i][j]
算法伪代码:
- 输入: 数 组 P , P [ i ] [ j ] 表 示 i 时 刻 j 位 置 落 下 得 馅 饼 数 数组P,P[i][j]表示i时刻j位置落下得馅饼数 数组P,P[i][j]表示i时刻j位置落下得馅饼数
- 输出:可以获得最多得馅饼数
getPie(P)
t <- P.length;
dp <- new int[13];
dp[-1] <- 0; dp[11] <- 0;
dp[4] <- P[1][4];dp[5] <- P[1][5];dp[6] <- P[1][6];
start <- 3;
end <- 7;
for i <- 2 to t
start <- Max(--start, 0);
end <- Min(++end, 10);
for j <- start to end
dp[j] <- Max(dp[j],dp[j - 1], dp[j + 1]) + P[i][j];
return Max(dp);
时间复杂度分析:
- 输入规模: 11 n 11n 11n
- 复杂度: O ( n ) O(n) O(n)