【CODE】字符串 && DP

目录

712. Minimum ASCII Delete Sum for Two Strings

583. Delete Operation for Two Strings

72. Edit Distance

300. Longest Increasing Subsequence

334. Increasing Triplet Subsequence

1305. All Elements in Two Binary Search Trees

152. Maximum Product Subarray


712. Minimum ASCII Delete Sum for Two Strings

Medium

72241Add to ListShare

Given two strings s1, s2, find the lowest ASCII sum of deleted characters to make two strings equal.

Example 1:

Input: s1 = "sea", s2 = "eat"
Output: 231
Explanation: Deleting "s" from "sea" adds the ASCII value of "s" (115) to the sum.
Deleting "t" from "eat" adds 116 to the sum.
At the end, both strings are equal, and 115 + 116 = 231 is the minimum sum possible to achieve this.

Example 2:

Input: s1 = "delete", s2 = "leet"
Output: 403
Explanation: Deleting "dee" from "delete" to turn the string into "let",
adds 100[d]+101[e]+101[e] to the sum.  Deleting "e" from "leet" adds 101[e] to the sum.
At the end, both strings are equal to "let", and the answer is 100+101+101+101 = 403.
If instead we turned both strings into "lee" or "eet", we would get answers of 433 or 417, which are higher.

Note:

  • 0 < s1.length, s2.length <= 1000.
  • All elements of each string will have an ASCII value in [97, 122].
#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
/*712. Minimum ASCII Delete Sum for Two Strings
1.dp[i][j]表示s1的前i个与s2的前j个相等,要动多少次
dp[i][0]=s1的前i个字符累加,dp[0][j]=s2的前j个字符累加,注意第j个字符是s2[j-1]
若s1[i-1]==s2[j-1],表明s1的第i个=s2的第j个,说明dp[i][j]=dp[i-1][[j-1]
若s1[i-1]!=s2[j-1],表明从s1的前i个到s2的前j个,需要删除s1[i-1]或者s2[j-1],
若删除s1[i-1],dp[i][j]=dp[i-1][j]+s1[i-1],否则dp[i][j]=dp[i][j-1]+s2[j-1].
Runtime: 24 ms, faster than 80.39% of C++ online submissions for Minimum ASCII Delete Sum for Two Strings.
Memory Usage: 16.7 MB, less than 77.78% of C++ online submissions for Minimum ASCII Delete Sum for Two Strings.*/
int minimumDeleteSum1(string s1, string s2) {
	int n1 = s1.size(), n2 = s2.size();
	vector<vector<int> > dp(n1 + 1, vector<int>(n2 + 1));
	for (int i = 1; i <= n1; i++) {
		dp[i][0] = dp[i - 1][0] + s1[i - 1];
	}for (int j = 1; j <= n2; j++) {
		dp[0][j] = dp[0][j - 1] + s2[j - 1];
	}for (int i = 1; i <= n1; i++) {
		for (int j = 1; j <= n2; j++) {
			if (s1[i - 1] == s2[j - 1]) dp[i][j] = dp[i - 1][j - 1];
			else {
				dp[i][j] = min(dp[i - 1][j] + s1[i - 1], dp[i][j - 1] + s2[j - 1]);
			}
		}
	}
	return dp[n1][n2];
}
/*2.最大相同子序列的ascii值
dp[i][j]表示s1前i个与s2前j个相同字符的ascii和值
dp[i][0]=0,dp[0][j]=0
s1[i-1]==s2[j-1]:dp[i][j]=dp[i-1][j-1]+s1[i-1]
s1[i-1]!=s2[j-1]:dp[i][j]=max(dp[i-1][j],dp[i][j-1])
需要删除的字符=s1和s2总的字符-相同字符*2
Runtime: 24 ms, faster than 80.39% of C++ online submissions for Minimum ASCII Delete Sum for Two Strings.
Memory Usage: 16.7 MB, less than 77.78% of C++ online submissions for Minimum ASCII Delete Sum for Two Strings.*/
int minimumDeleteSum(string s1, string s2) {
	int n1 = s1.size(), n2 = s2.size();
	vector<vector<int> > dp(n1+1, vector<int>(n2+1));
	int sum=0;
	for (int i = 1; i <= n1; i++) {
		sum += s1[i - 1];
		for (int j = 1; j <= n2; j++) {
			if (i == 1) sum += s2[j - 1];
			if (s1[i - 1] == s2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + s1[i - 1];
			else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
		}
	}
	return sum-2*dp[n1][n2];
}
int main() {
	string s1 = "delete", s2 = "leet";
	cout << minimumDeleteSum(s1, s2);
	return 0;
} 

583. Delete Operation for Two Strings

Medium

88124Add to ListShare

Given two words word1 and word2, find the minimum number of steps required to make word1 and word2 the same, where in each step you can delete one character in either string.

Example 1:

Input: "sea", "eat"
Output: 2
Explanation: You need one step to make "sea" to "ea" and another step to make "eat" to "ea".

Note:

  1. The length of given words won't exceed 500.
  2. Characters in given words can only be lower-case letters.
class Solution {
public:
    /*Runtime: 16 ms, faster than 81.17% of C++ online submissions for Delete Operation for Two Strings.
    Memory Usage: 13.4 MB, less than 55.56% of C++ online submissions for Delete Operation for Two Strings.*/
    int minDistance(string word1, string word2) {
        int n1=word1.size(),n2=word2.size();
        vector<vector<int> > dp(n1+1,vector<int>(n2+1));
        int res=0;
        for(int i=1;i<=n1;i++) dp[i][0]=i;
        for(int j=1;j<=n2;j++) dp[0][j]=j;
        for(int i=1;i<=n1;i++){
            for(int j=1;j<=n2;j++){
                if(word1[i-1]!=word2[j-1]) dp[i][j]=min(dp[i-1][j],dp[i][j-1])+1;
                else dp[i][j]=dp[i-1][j-1];
            }
        }
        return dp[n1][n2];
    }
};

72. Edit Distance

Hard

302244Add to ListShare

Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.

You have the following 3 operations permitted on a word:

  1. Insert a character
  2. Delete a character
  3. Replace a character

Example 1:

Input: word1 = "horse", word2 = "ros"
Output: 3
Explanation: 
horse -> rorse (replace 'h' with 'r')
rorse -> rose (remove 'r')
rose -> ros (remove 'e')

Example 2:

Input: word1 = "intention", word2 = "execution"
Output: 5
Explanation: 
intention -> inention (remove 't')
inention -> enention (replace 'i' with 'e')
enention -> exention (replace 'n' with 'x')
exention -> exection (replace 'n' with 'c')
exection -> execution (insert 'u')
#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
/*72. Edit Distance
dp[i][j]表示word1前i个变为word2前j个需要的步骤数量
dp[i][0]=i,dp[0][j]=j
word1[i-1]==word2[j-1],dp[i][j]=dp[i-1][j-1]
word1[i-1]!=word2[j-1],有三种情况:
删除word1[i-1]:接下来比较word1[i]和word2[j-1],dp[i][j-1]+1
插入word2[j-1]:接下来比较word2[j]和word1[i-1],dp[i-1][j]+1
替换:接下来比较word1[i]和word2[j],dp[i-1][j-1]+1
Runtime: 0 ms, faster than 100.00% of C++ online submissions for Edit Distance.
Memory Usage: 10.5 MB, less than 71.88% of C++ online submissions for Edit Distance.*/
int minDistance(string word1, string word2) {
	int n1 = word1.size(), n2 = word2.size();
	vector<vector<int> > dp(n1 + 1, vector<int>(n2 + 1));
	for (int i = 1; i <= n1; i++) dp[i][0] = i;
	for (int j = 1; j <= n2; j++) dp[0][j] = j;
	for (int i = 1; i <= n1; i++) {
		for (int j = 1; j <= n2; j++) {
			if (word1[i - 1] == word2[j - 1]) dp[i][j] = dp[i - 1][j - 1];
			else dp[i][j] = min(dp[i - 1][j - 1], min(dp[i][j - 1], dp[i - 1][j])) + 1;
		}
	}
	return dp[n1][n2];
}
int main() {
	string s1 = "horse", s2 = "ros";
	cout << minDistance(s1, s2);
	return 0;
} 

300. Longest Increasing Subsequence

Medium

374185Add to ListShare

Given an unsorted array of integers, find the length of longest increasing subsequence.

Example:

Input: [10,9,2,5,3,7,101,18]
Output: 4 
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4. 

Note:

  • There may be more than one LIS combination, it is only necessary for you to return the length.
  • Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
/*300. Longest Increasing Subsequence
1.最长递增子序列,dp[i]表示以nums[i]为结尾的最长递增子串长度
对于每个nums[i],从0搜索到i,如果发现某个数nums[j],小于nums[i],更新dp[i]
dp[i]=max(dp[i],dp[j]+1)
Runtime: 40 ms, faster than 49.19% of C++ online submissions for Longest Increasing Subsequence.
Memory Usage: 8 MB, less than 100.00% of C++ online submissions for Longest Increasing Subsequence.*/
int lengthOfLIS1(vector<int>& nums) {
	if (nums.size() == 0) return 0;
	vector<int> dp(nums.size(),1);
	int res = 1;
	for (int i = 0; i < nums.size(); i++) {
		for (int j = 0; j <= i; j++) {
			if (nums[j] < nums[i]) dp[i] = max(dp[i], dp[j]+1);
		}
		res = max(res, dp[i]);
	}
	return res;
}
/*2.使用二分查找加快运行速度,建立空的dp数组,开始遍历原数组
对于每一个遍历到的数字,用二分查找在dp数组找 第一个≥它 的数字,
如果这个数字不存在,那么直接在dp后加上遍历到的这个数字,
如果存在,将这个数字更新为刚刚遍历到的数字,就是对于长度可能相等的子序列,部分最大值要更小一些
dp数组中的值可能不是一个真实的LIS
Runtime: 4 ms, faster than 91.34% of C++ online submissions for Longest Increasing Subsequence.
Memory Usage: 8.1 MB, less than 100.00% of C++ online submissions for Longest Increasing Subsequence.*/
int lengthOfLIS(vector<int>& nums) {
	vector<int> dp;
	for (int i = 0; i < nums.size(); i++) {
		if (dp.size()==0 || dp.size()>0 && dp.back()<nums[i]) dp.push_back(nums[i]);
		else {
			//找 第一个≥nums[i] 的
			int left = 0, right = dp.size();
			while (left < right) {
				int mid = left + (right - left) / 2;
				if (dp[mid] < nums[i]) left = mid + 1;
				else right = mid ;
			}
			dp[right] = nums[i];
		}
	}
	return dp.size();
}
int main() {
	vector<int> nums = {3,5,6,2,5,4,19,5,6,7,12};
	cout << lengthOfLIS(nums);
	return 0;
} 

334. Increasing Triplet Subsequence

Medium

1265115Add to ListShare

Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array.

Formally the function should:

Return true if there exists  i, j, k
such that  arr[i] <  arr[j] <  arr[k] given 0 ≤  i <  j <  k ≤  n-1 else return false.

Note: Your algorithm should run in O(n) time complexity and O(1) space complexity.

Example 1:

Input: [1,2,3,4,5]
Output: true

Example 2:

Input: [5,4,3,2,1]
Output: false
#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
/*334. Increasing Triplet Subsequence
是否有三个数递增,递增子序列长度是否大于等于3
Runtime: 300 ms, faster than 5.27% of C++ online submissions for Increasing Triplet Subsequence.
Memory Usage: 8.2 MB, less than 100.00% of C++ online submissions for Increasing Triplet Subsequence.*/
bool increasingTriplet(vector<int>& nums) {
	vector<int> dp(nums.size(),1);
	for (int i = 1; i < nums.size(); i++) {
		for (int j = i; j >= 0; j--) {
			if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
			if (dp[i] >= 3) return true;
		}
	}
	return false;
}
int main() {
	vector<int> nums = {5,4,3,2,1};
	cout << increasingTriplet(nums);
	return 0;
} 

1305. All Elements in Two Binary Search Trees

Medium

1826Add to ListShare

Given two binary search trees root1 and root2.

Return a list containing all the integers from both trees sorted in ascending order.

 

Example 1:

Input: root1 = [2,1,4], root2 = [1,0,3]
Output: [0,1,1,2,3,4]

Example 2:

Input: root1 = [0,-10,10], root2 = [5,1,7,0,2]
Output: [-10,0,0,1,2,5,7,10]

Example 3:

Input: root1 = [], root2 = [5,1,7,0,2]
Output: [0,1,2,5,7]

Example 4:

Input: root1 = [0,-10,10], root2 = []
Output: [-10,0,10]

Example 5:

Input: root1 = [1,null,8], root2 = [8,1]
Output: [1,1,8,8]

Constraints:

  • Each tree has at most 5000 nodes.
  • Each node's value is between [-10^5, 10^5].
/**
 * 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:
    /*返回二叉搜索树中的所有值,升序,中序遍历
    Runtime: 436 ms, faster than 7.78% of C++ online submissions for All Elements in Two Binary Search Trees.   
    Memory Usage: 56.3 MB, less than 100.00% of C++ online submissions for All Elements in Two Binary Search Trees.*/
    vector<int> getAllElements(TreeNode* root1, TreeNode* root2) {
        vector<int> res;
	    stack<TreeNode *> s;
        while(root1 || !s.empty()){
            while(root1){
                s.push(root1);
                root1=root1->left;
            }
            TreeNode *tmp=s.top();
            s.pop();
            res.push_back(tmp->val);
            root1=tmp->right;
        }
        int left=0,flag=0;
        if(res.size()==0) flag=1;
	    while(root2 || !s.empty()){
            while(root2){
                s.push(root2);
                root2=root2->left;
            }
            TreeNode *tmp=s.top();
            s.pop();
            root2=tmp->right;
            if(flag==1) res.push_back(tmp->val);
            else{
                while(left<res.size() && res[left]<tmp->val) left++;
                if(left==res.size()){ flag=1; res.push_back(tmp->val);}
                else res.insert(res.begin()+left,tmp->val);
            }
        }
        return res;
    }
};

152. Maximum Product Subarray

Medium

3208135Add to ListShare

Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.

Example 1:

Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.

Example 2:

Input: [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.
#include"pch.h"
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<unordered_map>
using namespace std;
/*152. Maximum Product Subarray
1.动态规划,计算j->i的乘积,超时*/
int maxProduct1(vector<int>& nums) {
	int n = nums.size();
	int res = nums[0];
	vector<vector<int> > dp(n, vector<int>(n));
	for (int i = 0; i < n; i++) {
		for (int j = i; j >= 0; j--) {
			if (j == i) dp[j][i] = nums[i];
			else {
				dp[j][i] = dp[j + 1][i] * nums[j];
			}
			res = max(res, dp[j][i]);
		}
	}
	return res;
}
/*2.用两个变量表示当前最大值和最小值,对于当前的nums[i]做了正负讨论
(1)遍历到正数,此时最大值=max(该正数,之前最大值*该正数),最小值=min(该正数,之前最小值*该正数)
(2)遍历到负数,先保存之前的最大值max1,此时最大值=max(该负数,之前最小值*该负数),最小值=min(该负数,max1*该负数)
(3)每遍历完一个数,都要更新最终最大值,如果是求最小值,一样的
Runtime: 4 ms, faster than 88.25% of C++ online submissions for Maximum Product Subarray.
Memory Usage: 8.5 MB, less than 100.00% of C++ online submissions for Maximum Product Subarray.*/
int maxProduct(vector<int>& nums) {
	int maxnow = nums[0], minnow = nums[0];
	int res = nums[0];
	for (int i = 1; i < nums.size(); i++) {
		if (nums[i] > 0) {
			maxnow = max(nums[i], nums[i] * maxnow);
			minnow = min(nums[i], nums[i] * minnow);
		}
		else {
			int maxx = maxnow;
			maxnow = max(nums[i], nums[i] * minnow);
			minnow = min(nums[i], nums[i] * maxx);
		}
		res = max(res, maxnow);
	}
	return res;
}
int main() {
	vector<int> num = { 2,3,-2,4 };
	int res = maxProduct(num);
	cout << res << endl;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值