2. 两数相加
// 思路:巧用进位变量
#if 1
#include <iostream>
#include <list>
using namespace std;
list<int> GetReValue(list<int> ll, list<int> lr)
{
list<int> lres;
lres.clear();
int carry = 0;
list<int>::iterator iterll = ll.begin();
list<int>::iterator iterlr = lr.begin();
while (iterll != ll.end() || iterlr != lr.end())
{
// 优化前 时间:O(m > n ? m : n + k) 空间:O((m > n ? m : n + k) 说明:k为size差值
/*if (iterll == ll.end())
{
ll.emplace_back(0);
iterll--;
continue;
}
if (iterlr == lr.end())
{
lr.emplace_back(0);
iterlr--;
continue;
}
int sum = (*iterll + *iterlr + carry) % 10;
lres.emplace_back(sum);*/
// 优化后 时间:O((m > n ? m : n) 空间:O((m > n ? m : n)
int sum = 0;
int all = 0;
if (iterll == ll.end())
{
all = (0 + *iterlr + carry);
}
else if (iterlr == lr.end())
{
all = (*iterll + 0 + carry) % 10;
}
else
{
all = (*iterll + *iterlr + carry) % 10;
}
sum = all % 10;
lres.emplace_back(sum);
carry = all / 10;
if (iterll != ll.end())
{
iterll++;
}
if (iterlr != lr.end())
{
iterlr++;
}
}
if (carry > 0)
{
lres.emplace_back(carry);
}
return lres;
}
int main()
{
list<int> ll = { 1,2,3,4,6,7,8,9,0 };
list<int> lr = { 7,8,9,1,2,3,4,5,6,7,7,8,8,8,8,8 };
list<int> lres = GetReValue(ll, lr);
list<int>::iterator iter = lres.begin();
for (; iter != lres.end(); ++iter)
{
cout << *iter << " ";
}
cout << endl;
return 0;
}
#endif
5. 最长回文子串
#if 0
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 暴力查找
// 思路:保证顺序的前提下 时间:O(n3) 空间:O(1)
string longestPalindrome(string s) {
int len = s.length();
if (len < 2) {
return s;
}
int maxn = 1;
int idx = 0;
for (int i = 0; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
string tmp = s.substr(i, j - i + 1);
string tmp2 = tmp;
reverse(tmp.begin(), tmp.end());
if (tmp == tmp2 && j - i + 1 > maxn) {
maxn = j - i + 1;
idx = i;
}
}
}
return s.substr(idx, maxn);
}
// 动态规划 只遍历二维数组一半的区域
// 思路:找出状态转移方程
string longestPalindrome_dp(string s) {
int size = s.size();
if (size <= 1) return s; // 边界条件处理
int len = 1; // 记录回文子串的长度,回文子串的最小长度为1
int start = 0; // 回文子串的开始位置
/*
这里有个有趣的现象就是如果我把下面的代码中的二维数组由 int 改为 vector<vector<int>> 后,就会超时,
这说明 int 型的二维数组访问执行速度完爆 std 的 vector 啊,所以以后尽可能的还是用最原始的数据类型吧。
*/
vector<vector<int>>dp(size, vector<int>(size, 0));
for (int i = 0; i < size; i++) dp[i][i] = 1; // 设置表格中对角线位置的值
for (int j = 1; j < size; j++) // i是开始位置,j是结束位置
{
for (int i = 0; i < j; i++)
{
if (s[i] == s[j])
{
if (j - i < 3)
dp[i][j] = 1; // 特殊情况处理:保证遍历范围在矩形的对角线之下(j>i) 反之亦然
else
dp[i][j] = dp[i + 1][j - 1]; // 状态转移方程的确定是核心:i+1到j-1是回文, 说明i到j一定是回文
}
if (dp[i][j]) // 更新长度
{
if (j - i + 1 > len)
{
len = j - i + 1;
start = i;
}
}
}
}
return s.substr(start, len);
}
// 相同思路拓展:最长上升子序列
string longestRiseSub_dp(string s) {
int size = s.size();
if (size <= 1) return s; // 边界条件处理
int len = 1; // 记录长度,最小长度为1
int start = 0; // 子串开始位置
vector<vector<int>>dp(size, vector<int>(size, 0));
for (int i = 0; i < size; i++) dp[i][i] = 1; // 设置表格中对角线位置的值
for (int j = 1; j < size; j++) // i是开始位置,j是结束位置
{
for (int i = 0; i < j; i++)
{
if (s[j] > s[j - 1]) // 升序
{
if (j - i < 2)
dp[i][j] = 1; // 特殊情况处理:保证遍历范围在矩形的对角线之下(j>i) 反之亦然
else
dp[i][j] = dp[i][j - 1]; // 状态转移方程
}
if (dp[i][j]) // 更新长度
{
if (j - i + 1 > len)
{
len = j - i + 1;
start = i;
}
}
}
}
return s.substr(start, len);
}
// 中心扩展 时间O(n^2) 空间O(1)
//int computeLen(string s, int l, int r) {
// int len = s.length();
// int i = l, j = r;
// while (i >= 0 && j < len) {
// if (s[i] == s[j]) {
// i--; j++;
// }
// else
// {
// break;
// }
// }
// return j - i - 1;
//}
//
//string longestPalindrome_center(string s) {
// int len = s.length();
// if (len < 2) {
// return s;
// }
// int maxn = 1;
// int idx = 0;
//
// for (int i = 0; i < len - 1; i++) {
// int oddLen = computeLen(s, i, i);
// int evenLen = computeLen(s, i, i + 1);
// int tempLen = max(oddLen, evenLen);
// if (tempLen > maxn) {
// maxn = tempLen;
// idx = i - (tempLen - 1) / 2;
// }
// }
// return s.substr(idx, maxn);
//}
//
// 马拉车算法: 时间:O(n)
//string longestPalindrome_mlc(string s) {
// string t = "$#";
// for (int i = 0; i < s.size(); ++i) {
// t += s[i];
// t += '#';
// }
// int p[t.size()] = { 0 }, id = 0, mx = 0, resId = 0, resMx = 0;
// for (int i = 1; i < t.size(); ++i) {
// p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
// while (t[i + p[i]] == t[i - p[i]]) ++p[i];
// if (mx < i + p[i]) {
// mx = i + p[i];
// id = i;
// }
// if (resMx < p[i]) {
// resMx = p[i];
// resId = i;
// }
// }
// return s.substr((resId - resMx) / 2, resMx - 1);
//}
int main()
{
// cout << longestPalindrome_dp("abcbaaaabcddd") << endl;
cout << longestRiseSub_dp("abcbaaaabcddd") << endl;
return 0;
}
#endif
8. 字符串转整数: 时间:O(n) 空间:O(1)
// 字符串转整数: 时间:O(n) 空间:O(1)
#if 0
#include <iostream>
#include <unordered_map>
#include <algorithm>
using namespace std;
class Automaton {
string state = "start";
// 枚举了一下所有的类型(数字(in_number)、符号(signed)、空白(start)、其他(end)前后出现是否可行的情况)
unordered_map<string, vector<string>> table = {
{"start", {"start", "signed", "in_number", "end"}},
{"signed", {"end", "end", "in_number", "end"}},
{"in_number", {"end", "end", "in_number", "end"}},
{"end", {"end", "end", "end", "end"}}
};
int get_col(char c) {
if (isspace(c)) return 0; // 空白字符只包括空格
if (c == '+' or c == '-') return 1;
if (isdigit(c)) return 2;
return 3;
}
public:
int sign = 1; // 正负符号
long long ans = 0;
void get(char c) {
state = table[state][get_col(c)];
if (state == "in_number") {
ans = ans * 10 + c - '0';
ans = sign == 1 ? min(ans, (long long)INT_MAX) : min(ans, -(long long)INT_MIN);
}
else if (state == "signed")
sign = c == '+' ? 1 : -1;
}
};
class Solution {
public:
int myAtoi(string str) {
Automaton automaton;
for (char c : str)
automaton.get(c);
return automaton.sign * automaton.ans;
}
};
int main()
{
Solution s;
cout << s.myAtoi("-2 2324 234 1\n3 2sfwe13213213213213") << endl;
return 0;
}
#endif
11. 盛水最多的容器 时间:O(n) 空间:O(1)
// 盛水最多的容器 时间:O(n) 空间:O(1)
// 思路:每次移动较小的边, 并更新最大容量
#if 0
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
uint32_t GetMaxCapacity(const vector<uint32_t> v)
{
if (v.empty())
{
return -1;
}
uint32_t l = 0, r = v.size() - 1;
uint32_t maxC = 0;
uint32_t tmp = 0;
while (l < r)
{
tmp = min(v[l], v[r]) * (r - l);
if (tmp > maxC)
{
maxC = tmp;
}
if (v[l] <= v[r])
{
l++;
}
else
{
r--;
}
}
return maxC;
}
int main()
{
vector<uint32_t> v = { 5, 10, 12, 3, 1, 2, 5, 10 };
cout << GetMaxCapacity(v) << endl;
return 0;
}
#endif