字符串
1、string数组的最长公共前缀
https://leetcode-cn.com/problems/longest-common-prefix/comments/
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
string res = strs[0];
for(int i=1; i<strs.size(); i++)
{
for(int j=0; j<res.size();j++)
{
if(res[j] != strs[i][j])
{
res = res.substr(0,j);
break;
}
}
}
return res;
}
};2、求字符串中不含重复字符的最长字串
https://leetcode-cn.com/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.length()<=1) return s.length();
int res = -1, right = 0;
unordered_set<char> store;
for(int left=0; left<s.length();left++)
{
while(right < s.length() && !store.count(s[right]))
{
store.insert(s[right]);
right++;
}
res = max(res,right - left);
store.erase(s[left]);
if(right>=s.length()) break;
}
return res;
}
};3、完美子串的个数
参考:https://blog.csdn.net/qq_44745063/article/details/114627854
vector<string> GetPerfectStr(string& s)
{
int len = s.size();//记录字符串长度
vector<string> res;//用来储存结果
vector<vector<string>> dp(len + 1, vector<string>(len + 1));//实现动归的数组
map<char,int> mp;//用map的去重来统计包含字符
for (auto str : s)
{
mp[str]++;
}
string countstr = "";
for (auto c : mp)
{
countstr+=c.first;
}//到此,统计字符结束
//初始化
for (int i = 0; i < len + 1; i++)
{
for (int j = 0; j <= i; j++)
{
dp[i][j] = countstr;
}
}
for (int i = 0; i < len + 1; i++)
{
for (int j = 1; j < len + 1; j++)
{
int pos = dp[i][j - 1].find(s[i]);
if (pos != string::npos)
{
dp[i][j] = dp[i][j - 1].erase(pos, 1);
}
else
dp[i][j] = dp[i][j - 1];
if (dp[i][j] == "")
{
res.push_back(s.substr(i, j));
}
}
}
return res;
}
4、删除s1中所有S2中的字符
#include<iostream>
#include<set>
#include<string.h>
using namespace std;
void re_str_delete(string& a, string& b)
{
set<char> temp;
for (auto s : b)
{
temp.insert(s);
}
int i = 0;
while (a[i]!= '\0')
{
while(temp.find(a[i]) != temp.end())
{
a.erase(a.begin()+i);
}
i++;
}
}
int main()
{
string a = "abcdefghdijabklcmn";
string b = "abcdef";
re_str_delete(a, b);
for (int i = 0; i < a.size(); ++i)
{
cout << a[i];
}
cout << endl;
system("pause");
return 0;
}5、最长回文子串
动态规划
class Solution {
public:
int getLongestPalindrome(string A, int n) {
// write code here
if(n < 2 ) return n;
vector<vector<bool>> dp(n,vector<bool>(n));
int maxLen = 0;
for(int i=0; i<n; i++)
{
dp[i][i] = 1;
}
for(int L=2; L<=n; L++)
{
for(int i=0; i<n; i++)
{
int j = L + i - 1;
if(j >=n) break;
if(A[i] != A[j]) dp[i][j] = false;
else{
if(j - i < 3) dp[i][j] =true;
else{
dp[i][j] = dp[i+1][j-1];
}
}
if(dp[i][j] == true && j - i + 1 > maxLen)
{
maxLen = j - i + 1;
}
}
}
return maxLen;
}
};6、最长递增子序列
动态规划+二分
上面的动态规划算法需要向前遍历找到前一个k,导致算法复杂度为O(nn),一个牛逼的想法是使用二分查找优化,使复杂度降低为O(nlogn)。
基本点在于维护一个数组maxEnd,其元素maxEnd[k]表示长度为k+1的递增长子序列的最后一个元素,并且是字典序最小的那个。显然maxEnd是一个递增数组。
1 如果arr[i] > maxEnd.back()时,显然直接..., maxEnd.back(), arr[i]依然是一个递增子序列。
2 问题是arr[i] <= maxEnd.back()时怎么处理?
我们找到maxEnd中大于等于arr[i]的元素位置k,将maxEnd[k]替换为arr[i],这表示将长度为k+1的子序列的最后一个元素更新为更小的值。显然更合理。然后再同步更新dp[k]值的为i。
class Solution {
public:
/**
* retrun the longest increasing subsequence
* @param arr int整型vector the array
* @return int整型vector
*/
vector<int> LIS(vector<int>& nums) {
// write code here
if (nums.size() <= 1)
return nums;
vector<int> dp(nums.size(), 0);
vector<int> pos(nums.size(), 0);//pos[i]=j用来记录nums[i]在dp中的第j个位置
int len = 0;
dp[len] = nums[0];
for (int i = 1; i < nums.size(); ++i) {
if (nums[i] > dp[len]) {
dp[++len] = nums[i];
pos[i] = len;
}
else {
int low = 0, high = len;
while (low <= high) {
int mid = (low + high) >> 1;
if (dp[mid] < nums[i])
low = mid + 1;
else
high = mid - 1;
}
if (low != -1) {
dp[low] = nums[i];
pos[i] = low;
}
else {
dp[0] = nums[i];
pos[i] = 0;
}
}
}
vector<int> res(len + 1, INT_MAX);
for (int i = nums.size() - 1; i >= 0; i--) {
if (pos[i] == len) {
res[len] = min(res[len], nums[i]);
len--;
}
}
return res;
}
};
京公网安备 11010502036488号