leetcode update

This commit is contained in:
gameloader 2024-09-21 21:39:53 +08:00
parent d7029da6b9
commit 8bedd7a0ac

View File

@ -13618,16 +13618,19 @@ private:
``` ```
## day206 2024-09-20 ## day206 2024-09-20
### 214. Shortest Palindrome
You are given a string s. You can convert s to a ### 214. Shortest Palindrome
You are given a string s. You can convert s to a
palindrome palindrome
by adding characters in front of it. by adding characters in front of it.
Return the shortest palindrome you can find by performing this transformation. Return the shortest palindrome you can find by performing this transformation.
![092021GmdHWmTgR4](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/092021GmdHWmTgR4.png) ![092021GmdHWmTgR4](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/092021GmdHWmTgR4.png)
### 题解 ### 题解
本题是一道难题但整体思路是比较简洁的我们只能在字符串的前面添加字符来构造回文串则以字符串开头作为起始的回文子字符串是不需要构造的需要添加的只是回文子字符串后面的部分。如aabaac则aabaa是不需要做任何变动的只需添加c如果在字符串中间位置有一个回文串对于构造整个回文串影响不大如acbcd显然要构造回文串必须将cbcd反转一遍。则解题思路为先找到以字符串开头为起始的原始字符串中的最长回文子串再将该子串后面的字符串反转添加到字符串前面即得到目标字符串。 本题是一道难题但整体思路是比较简洁的我们只能在字符串的前面添加字符来构造回文串则以字符串开头作为起始的回文子字符串是不需要构造的需要添加的只是回文子字符串后面的部分。如aabaac则aabaa是不需要做任何变动的只需添加c如果在字符串中间位置有一个回文串对于构造整个回文串影响不大如acbcd显然要构造回文串必须将cbcd反转一遍。则解题思路为先找到以字符串开头为起始的原始字符串中的最长回文子串再将该子串后面的字符串反转添加到字符串前面即得到目标字符串。
接下来要解决的问题是,如何得到以开头作为起始的最长回文子串有多长。如果我们将字符串逆序, 问题就变成了能找到的包含原始字符串开头和包含逆转后的字符串末尾的两个字符串中相同的子字符串最长有多长如aabaac逆转后为caabaa则前一个字符串开头的aa和后一个字符串结尾的aa完全相同则最长为2。这是一个模式匹配的问题如果熟悉kmp算法的话就会发现这和kmp算法中next数组的含义非常相似如果把原始字符串和逆转后的字符串连接在一起就变成了求这个连接后的字符串的最长公共前后缀的长度问题若字符串长度为n则此问题即为求next\[n-1\]。 接下来要解决的问题是,如何得到以开头作为起始的最长回文子串有多长。如果我们将字符串逆序, 问题就变成了能找到的包含原始字符串开头和包含逆转后的字符串末尾的两个字符串中相同的子字符串最长有多长如aabaac逆转后为caabaa则前一个字符串开头的aa和后一个字符串结尾的aa完全相同则最长为2。这是一个模式匹配的问题如果熟悉kmp算法的话就会发现这和kmp算法中next数组的含义非常相似如果把原始字符串和逆转后的字符串连接在一起就变成了求这个连接后的字符串的最长公共前后缀的长度问题若字符串长度为n则此问题即为求next\[n-1\]。
@ -13640,20 +13643,21 @@ kmp算法的next的求法网上已经有很多讲解以下面的情况为例
本题还可以使用滚动哈希来解决。即Rabin-Karp算法这里不再讲解该算法可参考下面的资料 本题还可以使用滚动哈希来解决。即Rabin-Karp算法这里不再讲解该算法可参考下面的资料
[Rabin-Karp算法](https://algo.itcharge.cn/06.String/02.String-Single-Pattern-Matching/02.String-Rabin-Karp/#_2-2-%E6%BB%9A%E5%8A%A8%E5%93%88%E5%B8%8C%E7%AE%97%E6%B3%95) [Rabin-Karp算法](https://algo.itcharge.cn/06.String/02.String-Single-Pattern-Matching/02.String-Rabin-Karp/#_2-2-%E6%BB%9A%E5%8A%A8%E5%93%88%E5%B8%8C%E7%AE%97%E6%B3%95)
### 代码 ### 代码
```cpp
```cpp
class Solution { class Solution {
public: public:
string shortestPalindrome(string s) { string shortestPalindrome(string s) {
string rev_s = s; string rev_s = s;
reverse(rev_s.begin(), rev_s.end()); reverse(rev_s.begin(), rev_s.end());
string temp = s + "#" + rev_s; string temp = s + "#" + rev_s;
int n = temp.length(); int n = temp.length();
vector<int> lps(n, 0); vector<int> lps(n, 0);
for (int i = 1, len = 0; i < n;) { for (int i = 1, len = 0; i < n;) {
if (temp[i] == temp[len]) { if (temp[i] == temp[len]) {
lps[i++] = ++len; lps[i++] = ++len;
@ -13665,14 +13669,58 @@ public:
} }
// 最长回文前缀的长度 // 最长回文前缀的长度
int longest_palindrome_prefix = lps[n - 1]; int longest_palindrome_prefix = lps[n - 1];
// 需要反转并添加到前面的子串 // 需要反转并添加到前面的子串
string to_reverse = s.substr(longest_palindrome_prefix); string to_reverse = s.substr(longest_palindrome_prefix);
reverse(to_reverse.begin(), to_reverse.end()); reverse(to_reverse.begin(), to_reverse.end());
// 拼接并返回结果 // 拼接并返回结果
return to_reverse + s; return to_reverse + s;
} }
}; };
``` ```
## day207 2024-09-21
### 386. Lexicographical Numbers
Given an integer n, return all the numbers in the range [1, n] sorted in lexicographical order.
You must write an algorithm that runs in O(n) time and uses O(1) extra space.
![09219ROMuzHfztdy](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/09219ROMuzHfztdy.png)
### 题解
本题要求将从1-n的数字按照字典序排列要明确字典序的含义即将数字视为字符串从头开始遍历字符串对每一位的字符字符小ascii码小或者理解为一般意义上的字符顺序如a-z0-9的即在前面短字符串和长字符串的前缀相同则短字符串在前面。
在遍历这样的数字过程中相当于构造了一棵树树的每一层都是0-9如果还可以继续产生下一层则先产生下一层并遍历。对每一层的操作都是相同的因此可以使用递归解决。这里的层就是将原来的数字乘10后对个位进行遍历看当前产生的新数字乘10是否小于n小于n则可以产生新的一层。在每一层的操作为遍历0-9遍历每个数字时与原始数字相加构成新数字判断新数字是否小于n小于n则将新数字乘10判断是否小于n小于n则递归调用层处理函数将新数字乘10作为参数传递当作下一层的原始数字。
相当于固定0-9的顺序产生一棵生成树对这棵多叉树进行后序遍历。
### 代码
```cpp
class Solution {
public:
vector<int> lexicalOrder(int n) {
vector<int> result;
for(int i=1;i<=9 && i<=n;i++){
result.push_back(i);
if (i*10 <= n){
layer(i*10, result, n);
}
}
return result;
}
void layer(int raw, vector<int>& result, int target){
for (int i=0; i<=9 && raw+i<=target; i++){
result.push_back(raw+i);
if ((raw+i)*10 <= target){
layer((raw+i)*10, result, target);
}
}
}
};
```