给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点。
示例:
给定 nums = [-2, 0, 3, -5, 2, -1],求和函数为 sumRange()
sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3
说明:
你可以假设数组不可变。
会多次调用 sumRange 方法。
此题简单,直接看代码。
class NumArray {
private int[] sums;
public NumArray(int[] nums) {
int n = nums.length;
this.sums = new int[n + 1];
for (int i = 1; i <= n; ++i) {
sums[i] = sums[i - 1] + nums[i - 1];
}
}
public int sumRange(int i, int j) {
return sums[j + 1] - sums[i];
}
}
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* int param_1 = obj.sumRange(i,j);
*/
如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,以下数列为等差数列:
1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
以下数列不是等差数列。
1, 1, 2, 5, 7
数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P 如果满足以下条件,则称子数组(P, Q)为等差数组: 元素 A[P], A[p + 1], …, A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。 函数要返回数组 A 中所有为等差数组的子数组个数。 示例: A = [1, 2, 3, 4] 返回: 3, A 中有三个子等差数组: [1, 2, 3], [2, 3, 4] 以及自身 [1, 2, 3, 4]。 dp[i] 表示以 A[i] 为结尾的等差递增子区间的个数。 当 A[i] - A[i-1] == A[i-1] - A[i-2],那么 [A[i-2], A[i-1], A[i]] 构成一个等差递增子区间。而且在以 A[i-1] 为结尾的递增子区间的后面再加上一个 A[i],一样可以构成新的递增子区间。 综上,在 A[i] - A[i-1] == A[i-1] - A[i-2] 时,dp[i] = dp[i-1] + 1。 因为递增子区间不一定以最后一个元素为结尾,可以是任意一个元素结尾,因此需要返回 dp 数组累加的结果。 给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 示例 1: 输入: 2 输入: 10 状态数组dp[i]表示:数字 i 拆分为至少两个正整数之和的最大乘积。为了方便计算,dp 的长度是 n + 1,值初始化为 1。 显然dp[2]等于 1,外层循环从 3 开始遍历,一直到 n 停止。内层循环 j 从 1 开始遍历,一直到 i 之前停止,它代表着数字 i 可以拆分成 j + (i - j)。但 j * (i - j)不一定是最大乘积,因为i-j不一定大于dp[i - j](数字i-j拆分成整数之和的最大乘积),这里要选择最大的值作为 dp[i] 的结果。 空间复杂度是 O(N)O(N),时间复杂度是 O(N^2)O(N 给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。 标签:动态规划 一条包含字母 A-Z 的消息通过以下方式进行了编码:
常数内存的动态规划
dp[2] = 1
[0, 1, 2]
dp[3] = dp[2] + 1 = 2
[0, 1, 2, 3], // [0, 1, 2] 之后加一个 3
[1, 2, 3] // 新的递增子区间
dp[4] = dp[3] + 1 = 3
[0, 1, 2, 3, 4], // [0, 1, 2, 3] 之后加一个 4
[1, 2, 3, 4], // [1, 2, 3] 之后加一个 4
[2, 3, 4] // 新的递增子区间
以前动态规划的标准解法,此题只用记录上次的dp值即可,所以空间复杂度可以将为O(1)
class Solution {
public int numberOfArithmeticSlices(int[] A) {
if (A == null && A.length == 0) {
return 0;
}
int n = A.length;
int temp = 0; //temp保留上次dp值
int total = 0;
for (int i = 2; i < n; ++i) {
if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) {
temp = temp + 1;
total += temp;
} else { // 中断了,下次置为0
temp = 0;
}
}
return total;
}
}
343. 整数拆分
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。
示例 2:
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
说明: 你可以假设 n 不小于 2 且不大于 58。动态规划
2
)。代码实现如下:class Solution {
public int integerBreak(int n) {
int[] dp = new int[n + 1];
dp[1] = dp[2] = 1;
for (int i = 3; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
dp[i] = Math.max(dp[i], Math.max(dp[i - j] * j, j * (i - j)));
}
}
return dp[n];
}
}
279. 完全平方数
示例 1:
输入: n = 12
输出: 3
解释: 12 = 4 + 4 + 4.
示例 2:
输入: n = 13
输出: 2
解释: 13 = 4 + 9.
BFS
import javafx.util.Pair;
class Solution {
public int numSquares(int n) {
if(n == 0)
return 0;
LinkedList<Pair<Integer, Integer> > queue = new LinkedList<>();
queue.addLast(new Pair<>(n, 0));
boolean[] visited = new boolean[n + 1];
visited[n] = true;
while(!queue.isEmpty()){
Pair<Integer, Integer> front = queue.removeFirst();
int num = front.getKey();
int step = front.getValue();
if(num == 0){
return step;
}
for(int i = 1; num - i * i >= 0; ++i){
int a = num - i * i;
if(!visited[a]){
if(a == 0)
return step + 1;
queue.addLast(new Pair(a, step + 1));
visited[a] = true;
}
}
}
return -1;
}
}
动态规划
首先初始化长度为n+1的数组dp,每个位置都为0
如果n为0,则结果为0
对数组进行遍历,下标为i,每次都将当前数字先更新为最大的结果,即dp[i]=i,比如i=4,最坏结果为4=1+1+1+1即为4个数字
动态转移方程为:dp[i] = MIN(dp[i], dp[i - j * j] + 1)
,i表示当前数字,jj表示平方数
时间复杂度:O(nsqrt(n)),sqrt为平方根class Solution {
public int numSquares(int n) {
int[] dp = new int[n + 1];
for (int i = 1; i <= n; ++i) {
dp[i] = i;
for (int j = 1; i - j * j>= 0; ++j) {
dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
}
}
return dp[n];
}
}
91. 解码方法
'A' -> 1
'B' -> 2
...
'Z' -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。
示例 1:
输入: "12"
输出: 2
解释: 它可以解码为 "AB"(1 2)或者 "L"(12)。
示例 2:
输入: "226"
输出: 3
解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
动态规划
class Solution {
public int numDecodings(String s) {
if (s == null && s.length() == 0) {
return 0;
}
int n = s.length();
int[] dp = new int[n + 1];
dp[0] = 1;
dp[1] = s.charAt(0) == '0' ? 0 : 1;
for (int i = 2; i <= n; ++i) {
int index1 = Integer.valueOf(s.substring(i - 1, i));
if (index1 != 0) {
dp[i] += dp[i - 1];
}
if (s.charAt(i - 2) == '0') {
continue;
}
int index2 = Integer.valueOf(s.substring(i - 2, i));
if (index2 <= 26) {
dp[i] += dp[i - 2];
}
}
return dp[n];
}
}
推荐阅读