303. Range Sum Query - Immutable
解题思路:给定一个数组,计算给定区间的数字的和。利用DP算出从开始处到i的和,dp[i]=sum[i],代码如下:
class NumArray {
public:
NumArray(vector nums)
{
sum.push_back(0);
for(int i=0;i sum;
};
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* int param_1 = obj.sumRange(i,j);
*/
53. Maximum Subarray
题目描述:求给定数组的和最大的连续子数组。
思路一:DP,表示到该元素的时候的和最大的连续子数组,代码如下:
class Solution {
public:
int maxSubArray(vector& nums)
{
int ret=nums[0];
vector dp(nums.size()+1);
dp[0]=ret;
for(int i=1;iret)
{
ret=dp[i];
}
}
return ret;
}
};
思路2:不用DP,不需要额外这么多内存,只用两个变量表示即可,代码如下:
class Solution {
public:
int maxSubArray(vector& nums)
{
int ret=INT_MIN;
int f=0;
for(int i=0;i
198. House Robber
解题思路:DP。递推公式,我们维护一个一位数组dp,其中dp[i]表示到i位置时不相邻数能形成的最大和,dp[i] = max(num[i] + dp[i - 2], dp[i - 1]),代码如下:
class Solution {
public:
int rob(vector& nums)
{
int n=nums.size();
if(n==0)
{
return 0;
}
vector dp(n,0);
dp[0]=nums[0];
dp[1]=max(nums[0],nums[1]);
for(int i=2;i
213. House Robber II
题目描述:跟上一个题目相比,这里的房子成一个圈,不能同时包含第一个和最后一个。代码如下:
// DP
class Solution {
public:
int rob(vector& nums)
{
if (nums.size() <= 1)
{
return nums.empty() ? 0 : nums[0];
}
return max(rob(nums, 0, nums.size() - 1), rob(nums, 1, nums.size()));
}
int rob(vector &nums, int left, int right)
{
if (right - left <= 1)
return nums[left];
vector dp(right, 0);
dp[left] = nums[left];
dp[left + 1] = max(nums[left], nums[left + 1]);
for (int i = left + 2; i < right; ++i)
{
dp[i] = max(nums[i] + dp[i - 2], dp[i - 1]);
}
return dp.back();
}
};
题目描述:这个题目扩展为二叉树,即不能同时偷直接相邻的节点。
Solution1:二叉树的题目:递归,深度优先遍历,宽度优先遍历,第一种,递归算法
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int rob(TreeNode* root)
{
if(root==NULL)
{
return 0;
}
int val=0;
if(root->left)
{
val=val+rob(root->left->left)+rob(root->left->right);
}
if(root->right)
{
val=val+rob(root->right->left)+rob(root->right->right);
}
return max(root->val+val,rob(root->left)+rob(root->right));
}
};
Solution 2:用hash来存储每一个节点对应的最大值。代码如下:
class Solution {
public:
int rob(TreeNode* root)
{
unordered_map m;
return dfs(root, m);
}
int dfs(TreeNode *root, unordered_map &m)
{
if (!root) return 0;
if (m.count(root)) return m[root];
int val = 0;
if (root->left)
{
val += dfs(root->left->left, m) + dfs(root->left->right, m);
}
if (root->right)
{
val += dfs(root->right->left, m) + dfs(root->right->right, m);
}
val = max(val + root->val, dfs(root->left, m) + dfs(root->right, m));
m[root] = val;
return val;
}
};
338. Counting Bits
解题思路:如果一个数为偶数,那么它包含的1的个数与其除2后的1的个数相同,比如8,4,2,1,如果一个数为奇数,它包含的1的个数等于除2后的数加1,找到相互关系后,代码如下:
代码:
class Solution {
public:
vector countBits(int num)
{
vector dp(num+1,0);
dp[1]=1;
for(int i=2;i
647. Palindromic Substrings
题目描述:给定一个字符串,求该字符串的所有对称的子串。
解题思路:二维DP问题,DP[j][i]表示子串sub(j,i)是否是对称的子串,如果dp[j][i]=dp[j+1][i-1]+s[i]==s[j].然后统计所有的对称的子串的个数,代码如下:
class Solution {
public:
int countSubstrings(string s)
{
if(s.size()<=1)
{
return s.size();
}
int n=s.size();
vector> dp(n,vector(n,false));
for(int i=0;i
5. Longest Palindromic Substring
解题思路:同上
代码如下:
// DP
class Solution {
public:
string longestPalindrome(string s)
{
int dp[s.size()][s.size()] = {0}, left = 0, right = 0, len = 0;
for (int i = 0; i < s.size(); ++i) {
for (int j = 0; j < i; ++j)
{
dp[j][i] = (s[i] == s[j] && (i - j < 2 || dp[j + 1][i - 1]));
if (dp[j][i] && len < i - j + 1)
{
len = i - j + 1;
left = j;
right = i;
}
}
dp[i][i] = 1;
}
return s.substr(left, right - left + 1);
}
};
题目描述:求最长的对称的子序列。
解题思路:动态规划
代码如下:
class Solution {
public:
int longestPalindromeSubseq(string s)
{
int n=s.size();
if(n<=1)
{
return n;
}
vector> dp(n,vector(n,0));
for(int i=0;i=0;j--)
{
if(s[i]==s[j])
{
dp[j][i]=dp[j+1][i-1]+2;
}
else
{
dp[j][i]=max(dp[j+1][i],dp[j][i-1]);
}
}
}
return dp[0][n-1];
}
};
413. Arithmetic Slices
解题思路:DP
class Solution {
public:
int numberOfArithmeticSlices(vector& A)
{
int res = 0, n = A.size();
vector dp(n, 0);
for (int i = 2; i < n; ++i)
{
if (A[i] - A[i - 1] == A[i - 1] - A[i - 2])
{
dp[i] = dp[i - 1] + 1;
}
res += dp[i];
}
return res;
}
};
343. Integer Break
题目描述:给定一个数字,将该数字至少分成两个,求分开后乘积最大的结果。
解题思路:dp,试着写前几个,发现规律。
class Solution {
public:
int integerBreak(int n)
{
vectordp(7);
dp[0]=0;
dp[1]=0;
dp[2]=1;
dp[3]=2;
dp[4]=4;
dp[5]=6;
dp[6]=9;
for (int i = 7; i <= n; ++i)
{
dp.push_back(dp[i-3]*3);
}
return dp[n];
}
};
题目描述:给定一个区间数组,求满足要求的最长长度。
Input: [[1,2], [2,3], [3,4]] Output: 2 Explanation: The longest chain is [1,2] -> [3,4]
解题思路:按照结束值进行排序,即可。
代码:
class Solution {
public:
int findLongestChain(vector>& pairs)
{
sort(pairs.begin(),pairs.end(),cmp);
vector pair;
int ret=0;
for(int i=0;ipair[1])
{
pair=pairs[i];
ret++;
}
}
return ret;
}
static bool cmp(vector a,vector b)
{
return a[1]
392. Is Subsequence
题目描述:给定两个字符串s和t,判断s是不是t的子串。
解题思路:依次遍历即可;
代码:
class Solution {
public:
bool isSubsequence(string s, string t)
{
int m=s.size();
int n=t.size();
if(m>n)
{
return false;
}
if(m==n)
{
return s==t;
}
int i=0;
int j=0;
while(i
494. Target Sum
Input: nums is [1, 1, 1, 1, 1], S is 3. Output: 5 Explanation: -1+1+1+1+1 = 3 +1-1+1+1+1 = 3 +1+1-1+1+1 = 3 +1+1+1-1+1 = 3 +1+1+1+1-1 = 3 There are 5 ways to assign symbols to make the sum of nums be target 3.解题思路:深度优先遍历,求每一种组合的结果,然后统计满足要求的结果的个数。
代码如下:
class Solution {
public:
int findTargetSumWays(vector& nums, int S)
{
return help(nums,0,S);
}
int help(vector&nums,int start,int S)
{
if(start>=nums.size())
{
if(S==0)
{
return 1;
}
return 0;
}
return help(nums,start+1,S-nums[start])+help(nums,start+1,S+nums[start]);
}
};