5 Longest Palindromic Substring
网址:https://leetcode.com/problems/longest-palindromic-substring/submissions/
思路一:暴力破解
O(n^3)
思路二:动态规划
时间复杂度:O(n^2), 空间复杂度:O( n ^ 2)
动态转移方程:
if i == j,dp[i, j] = 1
if i = j + 1,dp[i, j] = s[i] == s[j]
if i > j + 1,dp[i, j] = s[i] == s[j] && dp[i + 1][j - 1]
string longestPalindrome(string s) {
if(s.size()==0) //考虑字符串为0的情况
return s;
int max=0,start=0;
bool dp[1001][1001]={false};
for (int i=0;i<s.size();i++) {
dp[i][i] = true;
}
for (int i=1;i<s.size();i++){
for (int j=0;j<i;j++){
if(i==j+1 && s[i]==s[j])
dp[j][i]= true;
if(s[i]==s[j] && dp[j+1][i-1] && i>j+1)
dp[j][i]= true;
if(dp[j][i] && i-j+1>max){
max=i-j+1;
start=j;
}
}
}
if(max==0) //考虑没有找到大于等于2的回文串
return s.substr(0,1);
return s.substr(start,max);
}
53 maximum subarray
网址:https://leetcode.com/problems/maximum-subarray/
状态转移方程:f=max(f+A[i],A[i])
int maxSubArray(vector<int>& nums) {
vector<int> sum(nums.size(),0);
sum[0]=nums[0];
int max=nums[0];
for (int i=1;i<nums.size();i++){
sum[i]=nums[i]+(sum[i-1]>0?sum[i-1]:0);
max=(max<sum[i]?sum[i]:max);
}
cout<<max;
}
62 Unique Paths
思路:动态规划
状态转移方程:dp[i][j]=dp[i-1][j]+dp[i][j-1]
1.使用普通递归:超时……
int getSteps(int m,int n){
if(m==0 || n==0)
return 1;
return getSteps(m,n-1)+getSteps(m-1,n);
}
int uniquePaths(int m, int n) {
int s=getSteps(m-1,n-1);
cout<<s;
}
2.换用自底向上方法:击败100%……
int s[101][101];
int uniquePaths(int m, int n) {
for (int i=0;i<m;i++){
for (int j=0;j<n;j++){
if(i==0 || j==0) {
s[i][j] = 1;
}
else s[i][j]=s[i-1][j]+s[i][j-1];
}
}
return s[m-1][n-1];
}
322. Coin Change
网址:https://leetcode.com/problems/coin-change/
状态转移方程:dp[i]=min(dp[i],dp[i-coins[j]]+1);
int INF=0x7ffffffe;
int min(int a,int b){
if(a<=b)
return a;
else return b;
}
int coinChange(vector<int>& coins, int amount) {
if(amount==0)
return 0;
if(coins.size()==0)
return 0;
vector<int> dp(amount+1,INF);
dp[0]=0;
for (int i=1;i<=amount;i++){
for (int j=0;j<coins.size();j++){
if(coins[j]<=i) //开始的时候忘了比较,使数据越界
dp[i]=min(dp[i],dp[i-coins[j]]+1);
}
}
if(dp[amount]==INF)
return -1;
else return dp[amount];
}
时间复杂度:O(amount*coins.size)
空间复杂度:O(amount)
416. Partition Equal Subset Sum
网址:https://leetcode.com/problems/partition-equal-subset-sum/
思路:
1)求出所有数字的和,若为奇数则一定不能分成两个相等的组;
2)若为偶数,求出和的1/2数target,看能否在数组中找到和为target的数。即转换为恰能装满的01背包问题
状态转移方程:dp[i] = dp[i] || dp[i - num],dp[i]的类型为布尔型,代表数组中是否存在数字使和为i。
bool canPartition(vector<int>& nums) {
int sum = accumulate(nums.begin(), nums.end(), 0), target = sum >> 1;
cout<<"target:"<<target<<endl;
if (sum & 1) return false;
vector<bool> dp(target + 1, false);
dp[0] = true;
for (int num : nums) {
for (int i = target; i >= num; --i) {
dp[i] = dp[i] || dp[i - num];
}
}
return dp[target];
}
注意:
在动态规划问题中要注意循环的顺序,例如背包问题:
1)背包容量在内层循环;
2)内层循环采用顺序还是逆序(01背包逆序,完全背包顺序)