// Created by Administrator on 2022/3/21.
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "Offer.h"
using std::vector;
using std::set;
using std::string;
using std::unordered_map;
using folly::fbstring;
int Offer::divide() {
int a = 15;
int b = 2;
bool negative = true;
if (a < 0 && b < 0) negative = false;
a = std::abs(a);
b = std::abs(b);
int answer = a / b;
return 0;
}
int Offer::addBinary() {
string first = "10";
string second = "101111";
size_t secondSize = second.size();
size_t firstSize = first.size();
std::string result;
if (firstSize >= secondSize) {
std::swap(first, second);
std::swap(firstSize, secondSize);
}
bool isMetric = false;
result.reserve(secondSize + 1);
int firstIndex = firstSize - 1;
int secondIndex = secondSize - 1;
while (firstIndex >= 0) {
int addNum = 0;
if (isMetric) {
addNum = first[firstIndex] + second[secondIndex] - '0' * 2 + 1;
} else {
addNum = first[firstIndex] + second[secondIndex] - '0' * 2;
}
dbg(addNum);
if (addNum >= 2) {
result.push_back(addNum + '0' - 2);
isMetric = true;
} else {
result.push_back('0' + addNum);
isMetric = false;
}
--firstIndex;
--secondIndex;
}
dbg(result);
while (secondIndex >= 0) {
if (isMetric) {
char addNum = 0;
addNum = static_cast(second[secondIndex] - '0' + 1);
if (addNum == 2) {
isMetric = true;
result.push_back('0');
} else {
result.push_back('1');
--secondIndex;
while (secondIndex >= 0) {
result.push_back(second[secondIndex]);
--secondIndex;
}
isMetric = false;
}
} else {
result.push_back(second[secondIndex]);
}
--secondIndex;
}
if (isMetric) {
result.push_back('1');
}
std::reverse(result.begin(), result.end());
dbg(result);
vector resultA;
int newCapacity = 80;
resultA.reserve(newCapacity);
resultA.push_back(0);
for (int i = 1; i < newCapacity; ++i) {
if ((i & 1) == 1) { //奇数则 将当前的 存在的 转换为
resultA.push_back(resultA[i >> 1] + 1);
} else {
resultA.push_back(resultA[i >> 1]);
}
}
return 0;
}
void Offer::singleNum() {
std::vector nums{0, 1, 0, 1, 0, 1, 99};
std::sort(nums.begin(), nums.end());
int count = 1;
int last = nums[0];
for (auto start = nums.begin() + 1; start != nums.end(); ++start) {
if (*start == last) {
count++;
} else {
if (count == 1) {
dbg(last);
break;
}
count = 1;
last = *start;
}
}
// dbg(nums.back());
std::vector words = {"abcw", "baz", "foo", "bar", "xtfn", "abcdef"};
size_t n = words.size();
auto masks = std::vector(n);
for (int i = 0; i < n; ++i) {
dbg(masks[i]);
}
int res = 0;
for (int i = 0; i < n; i++) {
int bitMask = 0;
for (char c: words[i]) {
bitMask |= (1 << (c - 'a'));
}
masks[i] = bitMask;
dbg(masks[i]);
}
}
void Offer::threeSum() {
// std::unordered_map mMap;
// for (int i: data) {
// mMap[i]++;
// }
// size_t size = data.size();
// vector> result;
// for (int i = 0; i + 2 < size; ++i) {
// int first = data[i];
// if (mMap[first] > 0) {
// --mMap[first];
// bool isSuccess = false;
// for (int j = i + 1; j + 1 < size; ++j) {
//
// int second = data[j];
// if (mMap[second] > 0) {
// --mMap[second];
// int third = -i - j;
// if (mMap[third] > 0) {
// --mMap[third];
// isSuccess = true;
// result.emplace_back(std::vector{first, second, third});
// } else {
// ++mMap[second];
// }
// }
//
// }
// if (! isSuccess) {
// ++mMap[first];
// }
// }
// }
//threeSumFirstAnswer(data);
std::vector data{-2, 0, 1, 1, 2};
// threeSumSecondAnswer(data);
// 使用 sort 的方法找到的当前的 需要的
auto answer = [&data]()mutable {
std::sort(data.begin(), data.end());
auto size = std::size(data);
dbg(data);
std::vector> results;
int left = 1;
int right = size - 1;
for (int i = 0; i < size;) {
int cur = data[i];
dbg(i, left, right);
bool isFind = false;
while (left < right) {
const string &basicString = fmt::format("{} {} {}", cur, data[left], data[right]);
dbg(basicString);
//找到当前符合的两个位置的
int curResult = data[left] + data[right] + cur;
if (curResult > 0) {
--right;
} else if (curResult < 0) {
++left;
} else {
results.emplace_back(std::vector{cur, data[left], data[right]});
isFind = true;
break;
}
}
if (i + 1 < size && data[i + 1] == data[i]) {
while (i + 1 < size && data[i + 1] == data[i])
++i;
} else {
++i;
}
if (isFind)
right = right - 1;
left = i + 1;
}
dbg(results);
};
auto otherAnswer = [&data]()mutable {
std::vector> result;
std::sort(data.begin(), data.end());
auto size = std::size(data);
// 有两种情况
//1. 数字重复了 比如 -1,-1,0,0,1,1 -1,0,1 成功后 left从0 要到一个不等于0的地方
//2. 当前数字匹配多次 -2,-1,0,2,3 -2 0 2 -2 -1 3 所以匹配成功后left 要转到下一个地方 不能直接打破循环
for (int i = 0; i < size; ++i) {
if (i > 0 && data[i - 1] == data[i]) continue;
int left = i + 1;
int right = size - 1;
while (left < right) {
int curResult = data[left] + data[i] + data[right];
if (curResult == 0) {
result.emplace_back(std::vector{data[i], data[left], data[right]});
while (left < right && data[left] == data[1 + left])++left;
++left; //到达下一个 left 不相同的地方
continue;
} else if (curResult < 0) {
++left;
} else {
--right;
}
}
}
dbg(result);
};
otherAnswer();
}
void Offer::threeSumSecondAnswer(vector &data) {
std::unordered_map mMap;
for (int i: data) {
mMap[i]++;
}
std::vector> results;
auto size = data.size();
for (int i = 0; i < size; ++i) {
int cur = data[i];
if (mMap[cur] > 0) {
--mMap[cur];
bool isSuccess = false;
for (int j = i + 1; j < size; ++j) {
int first = data[j];
if (mMap[first] > 0) {
--mMap[first];
const auto &iterator = mMap.find(-cur - first);
if (iterator != mMap.end() && ((*iterator).second > 0)) {
dbg(*iterator);
results.emplace_back(std::vector{cur, first, (*iterator).first});
isSuccess = true;
continue;
}
++mMap[first];
}
}
if (! isSuccess) {
++mMap[cur];
}
}
// 跳过重复的数据
}
dbg(results);
}
void Offer::threeSumFirstAnswer(std::vector &data) {
std::vector> result;
std::sort(data.begin(), data.end());
int size = data.size();
for (int i = 0; i < size; ++i) {
while (i + 1 < size && data[i] == data[i + 1]) {
++i;
}
int left = i + 1;
int right = size - 1;
while (left < right) {
if (data[i] + data[left] + data[right] == 0) {
dbg(data[i], data[left], data[right]);
result.emplace_back(std::vector{data[i], data[left], data[right]});
left++;
right--;
continue;
} else if (data[i] + data[left] + data[right] > 0) {
--right;
} else {
++left;
}
}
}
}
void Offer::minSubArrayLen() {
// 滑动窗口
std::vector data{2, 3, 1, 2, 4, 3};
int target = 7;
auto size = data.size();
int right = 0;
int curResult = data[0];
int result = INT_MAX;
int left = 0;
while (left <= right && right < size) {
if (curResult < target) {
++right;
if (right < size)curResult += data[right];
} else if (curResult >= target) {
int curRange = right - left + 1;
if (result > curRange) {
result = curRange;
}
curResult -= data[left];
++left;
}
}
dbg(result);
}
void Offer::numSubarrayProductLessThanK() {
//给定一个正整数数组 nums和整数 k ,请找出该数组内乘积小于 k 的连续的子数组的个数。
// 给定一个长度 1850 长度为4 数组的个数相当于 1+2+3+4 不断进行[fast-slow+1]
auto answer = [] {
std::vector data{10, 5, 2, 6};
int k = 100;
int fast = 0;
int slow = 0;
auto size = data.size();
int tmp = 1;
int result = 0;
//如果当前要加入的fast 节点越界 证明没啥需要加的了 直接退出
while (fast < size) {
// 结果为 result += fast -slow+1 (fast 已经自增了)
if (data[fast] * tmp < k) {
tmp *= data[fast];
++fast;
result += fast - slow;
} else {
// tmp 除去 slow的部分 slow移动到 slow+1
// 如果 当前的只有一个元素都不行的话 fast和 slow需要一起+1
tmp /= data[slow];
if (fast == slow) {
++fast;
}
++slow;
}
}
return result;
};
// dbg(answer());
auto answerSumk = [] {
vector data{1, 1, 1};
int k = 2;
int size = data.size();
// 当数组元素存在负数的情况时 则滑动窗口可能存在失效的问题
// 当前的 大于当前元素的时候 无法前进 或者回溯
// 构建 辅助前缀和的数据
int preSum = 0;
// 问题就转化成 前缀和中相差 为k的数据对数有多个了
std::unordered_map map;
map.reserve(size + 1);
map[0] = 1;
int result = 0;
for (int i = 0; i < size; ++i) {
preSum += data[i];
dbg(map, preSum);
const auto &findIterator = map.find(preSum - k);
if (findIterator != map.end()) {
result += findIterator->second;
}
++map[preSum];
}
return result;
};
dbg(answerSumk());
}
void Offer::findMaxLengthWithSameCount() {
//给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。
// 不能使用滑动窗口 因为你不知道当前的 前进会增加0 还是后退会增加零
// 0,1 相同数量 进行前缀的异或和
std::vector data{0, 1};
auto size = data.size();
{
int countSum = data[0];
std::vector countCache;
countCache.reserve(size + 1);
countCache.push_back(0);
int result = 0;
for (int i = 0; i < size; ++i) {
int cur = data[i] ? 1 : -1;
countCache.push_back(cur + countCache[i]);
}
dbg(countCache);
}
{
std::unordered_map mMap;
mMap.reserve(size + 1);
mMap.insert({0, 0});
int count = 0;
int result = 0;
for (int i = 0; i < size; ++i) {
count += data[i] ? 1 : -1;
auto iterator = mMap.find(count);
if (iterator != mMap.end()) {
result = std::max(result, i - iterator->second + 1);
} else {
// 插入当前元素 第一次遇到则 赋值为 i
mMap[count] = i;
}
}
dbg(result);
}
}
int Offer::pivotIndex() {
/*
* 给你一个整数数组 nums ,请计算数组的 中心下标 。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
*/
auto a = [] {
std::vector data{1, 7, 3, 6, 5, 6};
dbg(data);
auto size = data.size();
if (size == 1) return -1;
std::vector sumCache;
sumCache.reserve(size);
int sum = 0;
for (int i = 0; i < size; ++i) {
sum += data[i];
sumCache.emplace_back(sum);
}
if (sum - data[0] == 0) {
return 0;
}
dbg(data);
// 将当前的 下标中索引求出
dbg(sumCache);
for (int i = 1; i < size; ++i) {
dbg(sum - sumCache[i], sumCache[i - 1]);
if (sum - sumCache[i] == sumCache[i - 1])return i;
}
return -1;
};
auto b = [] {
std::vector data{1, 7, 3, 6, 5, 6};
auto size = data.size();
int total = std::accumulate(data.begin(), data.end(), 0);
int sum = 0;
for (int i = 0; i < size; ++i) {
sum += data[i];
if (total - sum == sum - data[i]) {
return i;
}
}
return -1;
};
// return a();
std::vector> sumCache{};
sumCache.emplace_back(std::vector{-4});
sumCache.emplace_back(std::vector{-5});
size_t row = sumCache.size();
size_t col = sumCache[0].size();
for (int i = 0; i < row; ++i) {
for (int j = 1; j < col; ++j) {
sumCache[i][j] += sumCache[i][j - 1];
}
}
int result = 0;
int row1 = 0;
std::random_device device; //输出机器级别的随机数
std::default_random_engine e{device()}; //固定好种子后
// 将当前的 随机数发生器传给 分布实现去
std::binomial_distribution distribution(3, 2);
int col1 = distribution(e) % 2 ? 0 : 1;
int row2 = 0;
int col2 = 1;
for (int i = row1; i <= row2; ++i) {
if (col1 != 0) {
result += sumCache[i][col2] - sumCache[i][col1 - 1];
} else {
result += sumCache[i][col2];
}
}
dbg(result);
return 0;
}
int Offer::NumMatrix() {
vector> matrix{{-4, -5},
{1, 2}};
int row = matrix.size();
int col = matrix[0].size();
auto answer = [&matrix, row, col] {
std::vector> preSum(row + 1, std::vector(col + 1));
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
preSum[i + 1][j + 1] = preSum[i][j + 1] + preSum[i + 1][j] - preSum[i][j] + matrix[i][j];
}
}
auto sumRegion = [&](int row1, int col1, int row2, int col2) {
++row1;
++col1;
++row2;
++col2;
return preSum[row2][col2] + preSum[row1 - 1][col1 - 1] - preSum[row1 - 1][col2] - preSum[row2][col1 - 1];
};
dbg(preSum);
dbg(sumRegion(0, 0, 1, 1));
int row1 = 1;
int col1 = 1;
int row2 = 2;
int col2 = 2;
dbg(preSum[row2][col2], preSum[row1 - 1][col1 - 1], preSum[row1 - 1][col2], preSum[row2][col - 1]);
};
auto inPlaceAnswer = [&matrix, row, col] {
for (int i = 1; i < row; ++i) {
matrix[i][0] += matrix[i - 1][0];
}
for (int j = 1; j < col; ++j) {
matrix[0][j] += matrix[0][j - 1];
}
for (int i = 1; i < row; ++i) {
for (int j = 1; j < col; ++j) {
matrix[i][j] += matrix[i - 1][j] + matrix[i][j - 1] - matrix[i - 1][j - 1];
}
}
dbg(matrix);
};
inPlaceAnswer();
return 0;
}
void Offer::checkInclusion() {
//给定两个字符串 pattern 和 text,写一个函数来判断 text 是否包含 pattern 的某个变位词。
//换句话说,第一个字符串的排列之一是第二个字符串的 子串 。
//pattern = "ab" text = "eidbaooo" true
auto answer = [] {
string pattern = "ab";
string text = "eidboaoo";
const int patternLen = pattern.size();
const int textLen = text.size();
std::vector data(26);
for (int i = 0; i < patternLen; ++i) {
++data[pattern[i] - 'a'];
}
int left = 0;
int right = left;
while (right < textLen) {
dbg(data);
int curPos = text[right] - 'a';
--data[curPos];
while (data[curPos] < 0) {
int leftPos = text[left] - 'a';
++data[leftPos];
++left;
}
//到达匹配的位置处
// 如果是部分匹配则 可知当前的 right-left+1 < patternLen
if (patternLen == right - left + 1) {
return true;
}
++right;
}
return false;
};
dbg(answer());
}
int Offer::lengthOfLongestSubstring(string &s) {
std::array cache{};
const int length = s.length();
int left = 0;
int right = 0;
int result = 0;
while (right < length) {
const char cur = s[right];
++cache[cur];
while (cache[cur] > 1) {
const char leftPos = s[left];
--cache[leftPos];
++left;
}
result = std::max(right - left + 1, result);
++right;
}
return result;
}
int Offer::countSubstrings() {
// 回文子串的个数
string varString = "abababaadhqjqqq";
const int len = varString.length();
int result = 0;
// 中心点为 一时 有 len 个
// 中心点 为二时 有 len-1 个 故为 2*len-1
for (int cur = 0; cur < 2 * len - 1; ++cur) {
int left = cur / 2;
// right 可能为 中心点为两个元素
// right 应该字符串的 长度相关 可能为 偶数 或者奇数
int right = left + cur % 2;
while (right < len && left >= 0 && varString[left] == varString[right]) {
--left;
++right;
++result;
}
}
return result;
}
void Offer::removeNthFromEnd() {
const std::unique_ptr &ptr = Offer::ListNode::new_list(10);
auto root = ptr.get();
ListNode::printAll(root);
auto a = ListNode(0, root);
auto dummy = std::addressof(a);
int n = 2;
auto first = dummy;
auto second = dummy;
while (n-- != 0) {
second = second->next;
}
while (second != nullptr) {
second = second->next;
first = first->next;
}
first->next = first->next->next;
// dummy->left;
}
void Offer::maxPathSum() {
// 二叉树的最大路径和
// 分为当前的两种情况 将通过根节点的 和 不同通过根节点的
int maximum = INT_MIN;
fbstring str{"[1,-2,-3,1,3,-2,#,-1]"};
auto a = TreeNode::newTree(str);
int result = INT_MIN;
std::function answer = [&](TreeNode *root) {
if (root == nullptr)return 0;
int maxLeft = std::max(0, answer(root->left));
int maxRight = std::max(0, answer(root->right));
int curResult = std::max({root->val, root->val + maxLeft, root->val + maxRight});
// 因为是选择 一条路径 所以 子答案中的 root+left+right不能直接作为结果返回
result = std::max({maxLeft + maxRight + root->val, curResult, result});
return curResult;
};
dbg(answer(a.get()));
}
void Offer::setZero() {
//给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。
vector> matrix{{0, 1, 2, 0},
{3, 4, 5, 2},
{1, 3, 1, 5}};
auto answer = [&matrix]() mutable {
auto row = matrix.size();
auto col = matrix[0].size();
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
if (matrix[i][j] == 0) {
matrix[i][j] = INT_MIN;
// search in different row && col
for (int next = 0; next < col; ++next) {
if (next == j) continue;
if (matrix[i][next] != 0)
matrix[i][next] = 0;
else
matrix[i][next] = INT_MIN;
}
break;
}
}
}
dbg(matrix);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
if (matrix[i][j] == INT_MIN) {
for (int k = 0; k < row; ++k) {
matrix[k][j] = 0;
}
}
}
}
};
// answer();
// dbg(matrix);
dbg(matrix);
auto answer_without_space = [&]() {
auto row = matrix.size();
auto col = matrix[0].size();
// 使用数组的 第一行 第一列 作为存储
auto iterator = std::find(matrix.front().begin(), matrix.front().end(), 0);
bool findZeroInFirstRow = iterator != matrix.front().end();
bool findZeroInFirstCol = std::find_if(matrix.begin(),
matrix.end(),
[](const std::vector &data) { return data[0] == 0; }) !=
matrix.end();
// 从第二行进行 搜索出来 找到了 0则 从 0的对应的 第一行 第一列 做标记
for (int i = 1; i < row; ++i) {
for (int j = 1; j < col; ++j) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
dbg(matrix);
// 填列
for (int j = 1; j < col; ++j) {
if (matrix[0][j] == 0) {
for (int i = 1; i < row; ++i) {
matrix[i][j] = 0;
}
}
}
// 填充对应的零元素 填行
for (int i = 1; i < row; ++i) {
if (matrix[i][0] == 0) {
for (int j = 1; j < col; ++j) {
matrix[i][j] = 0;
}
}
}
if (findZeroInFirstRow) {
for (int j = 0; j < col; ++j) matrix[0][j] = 0;
}
if (findZeroInFirstCol) {
for (int i = 0; i < row; ++i) matrix[i][0] = 0;
}
dbg(matrix);
};
answer_without_space();
dbg(matrix);
}
void Offer::groupAnagrams() {
// ["eat", "tea", "tan", "ate", "nat", "bat"]
//vector data = {"eat", "tea", "tan", "ate", "nat", "bat"};
auto answer_ = [](std::vector &data) -> std::vector> {
if (data.empty()) return {};
auto size = data.size();
std::unordered_map> map;
for (int i = 0; i < size; ++i) {
int count = 0;
for (char ch: data[i]) {
count = count | (1 << (ch - 'a'));
}
if (map.find(count) == map.end()) {
map[count] = std::vector{i};
} else {
map[count].emplace_back(i);
}
}
dbg(map);
std::vector> result;
result.resize(map.size());
int curIndex = 0;
for (const auto &cur: map) {
const auto &ele = cur.second;
for (const int index: ele) {
result[curIndex].emplace_back(std::move(data[index]));
}
++curIndex;
}
dbg(result);
return result;
};
// answer_(data);
auto answer_other = [](std::vector &data) -> std::vector> {
if (data.empty()) return {};
auto size = data.size();
std::unordered_map> map;
for (int i = 0; i < size; ++i) {
string basicString{};
basicString.resize(26);
for (char ch: data[i]) {
++basicString[ch - 'a'];
}
if (map.find(basicString) != map.end()) {
map[basicString].emplace_back(std::move(data[i]));
} else {
map[basicString] = std::vector{std::move(data[i])};
}
}
std::vector> result;
result.reserve(map.size());
for (auto &&sd: map) {
result.emplace_back(std::move(sd.second));
}
return result;
};
// std::hash fn{};
// dbg(fn(10));
// //
auto answer_hashmap = [](std::vector data) -> std::vector> {
std::unordered_map> container;
for (std::string &cur: data) {
auto copy = cur;
std::sort(cur.begin(), cur.end());
container[cur].emplace_back(std::move(copy));
}
std::vector> result;
result.reserve(container.size());
for (auto &&item: container) {
result.emplace_back(std::move(item.second));
}
return result;
};
// 使用质数实现 设计 hash 值使得 拥有相同各个数据的数量 字符串 是一致的
auto answer_order = [](std::vector &data1) {
std::vector result;
result.reserve(data1.size());
std::array order = {2, 3, 5, 7, 11, 13,
17, 19, 23, 29, 31, 37,
41, 43, 47, 53, 59, 61,
67, 71, 73, 79, 83, 89,
97, 101};
for (const auto &item: data1) {
int t = 1;
for (const char ch: item) {
t *= order[ch - 'a'];
}
result.emplace_back(t);
}
};
}
void Offer::toGoatLatin() {
//824 拉丁山羊文
auto answer_latin = [](std::string &data) {
std::stringstream stream(data);
std::string word;
int idx = 1;
std::string result;
while (stream >> word) {
if (word[0] == 'a' || word[0] == 'e' || word[0] == 'i' || word[0] == 'o' || word[0] == 'u') {
}
}
};
}
void Offer::wordBreak() {
/*
* 给你一个字符串 s 和一个字符串列表 wordDict 作为字典(包含的字符串各不相同)。请你判断是否可以利用字典中出现的单词拼接出 s 。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。
*/
vector wordDict1 = {"leet", "code"};
std::string cur1 = "leetcode";
// 使用暴力递归
auto answer_word = [](const std::vector &data, std::string &word) {
auto answer_impl = [&](int dataIndex, int wordIndex, auto answer_impl) {
size_t wordSize = word.size();
if (wordIndex == wordSize)return true;
if (dataIndex >= data.size())return false;
// 还有单词的长度并未匹配到
int howManyLeft = wordSize - wordIndex;
int curWordSize = data[dataIndex].size();
int matchTime = howManyLeft / curWordSize;
if (word.compare(wordIndex, curWordSize, data[dataIndex]) == 0) {
return false;
}
for (int i = 0; i < matchTime; ++i) {
if (answer_impl(dataIndex + 1, wordIndex + curWordSize * (i + 1), answer_impl))return true;
}
return false;
};
};
// 使用字典数
struct TrieNode {
std::unique_ptr next[26]{};
bool isEnd = false;
};
// 建树
TrieNode root;
{
for (const string &word: wordDict1) {
TrieNode *p = std::addressof(root);
for (char ch: word) {
int curPos = ch - 'a';
if (p->next[curPos] == nullptr) {
p->next[curPos] = std::make_unique();
}
p = p->next[curPos].get();
}
p->isEnd = true;
}
}
bool failMemo[301]{false}; // 记录dfs中失败时对应的s中的index
auto answer_dfs = [&failMemo](std::string &word, int startPos, const TrieNode &root, auto answer_dfs) {
if (failMemo[startPos])return false;
int wordSize = word.size();
if (startPos == wordSize)return true;
const TrieNode *p = std::addressof(root);
for (int i = startPos; i < wordSize; ++i) {
int curWordIndex = word[i] - 'a';
if (p->next[curWordIndex] != nullptr) {
p = p->next[curWordIndex].get();
if (p->isEnd && answer_dfs(word, i + 1, root, answer_dfs))return true;
} else break;
}
failMemo[startPos] = true; // 记录当前的失败的前缀
return false;
};
}
void Offer::containsNearbyAlmostDuplicate() {
auto answer_ = [](vector &nums, int k, int t) {
if (nums.size() <= 1)return false;
int left = 0;
int right = 1;
while (left != right && right < nums.size()) {
if (abs(nums[left] - nums[right]) <= t) {
return true;
}
if (right - left != k) { ++right; }
else { ++left; }
}
return false;
};
vector data{1, 2, 1, 1, 1};
dbg(answer_(data, 3, 1));
}
void Offer::mergeKLists() {
// 合并升序排序
auto answer_ = [](vector lists) {
ListNode *result = nullptr;
if (lists.empty()) { return result; }
// for_each
ListNode *cur = nullptr;
do {
cur = nullptr;
int index = -1;
int curIndex = 0;
std::for_each(lists.begin(), lists.end(), [&](ListNode *item) {
if (item != nullptr) {
if (cur == nullptr || cur->val > item->val) {
cur = item;
index = curIndex;
}
++curIndex;
}
});
if (result == nullptr) { result = cur; }
else {
result->next = cur;
result = result->next;
}
if (curIndex != -1) { cur = cur->next; }
} while (cur != nullptr);
return result;
};
}
void Offer::eightnum() {
// 八数码
auto impl = []() {
string cur{"123x46758"};
std::queue queue;
string end = "12345678x";
std::unordered_map result_distance;
result_distance[cur] = 0;
queue.push(cur);
int x_four[4] = {-1, 0, 1, 0};
int y_four[4] = {0, 1, 0, -1};
while (! queue.empty()) {
auto cur_data = queue.front();
queue.pop();
int dist = result_distance[cur_data];
if (cur_data == end) return dist;
int k = static_cast(cur_data.find('x'));
int x = k / 3;
int y = k % 3;
for (int i: x_four) {
for (int j: y_four) {
int a = x + i;
int b = y + j;
if (x >= 0 && x <= 3 && y >= 0 && y <= 3) {
std::swap(cur_data[k], cur_data[a * 3 + b]);
if (! result_distance.count(cur_data)) {
result_distance[cur_data] = dist + 1;
queue.push(cur_data);
}
std::swap(cur_data[k], cur_data[a * 3 + b]);
}
}
}
}
return -1;
};
}
Offer::TreeNode::TreeNode() : val(0), left{nullptr}, right{nullptr} {}
Offer::TreeNode::TreeNode(int x) : val(x), left{nullptr}, right{nullptr} {}
std::unique_ptr Offer::TreeNode::newTree(folly::fbstring &data) {
folly::fbvector cur_list;
folly::StringPiece view(data.begin() + 1, data.end() - 1);
folly::split(",", view, cur_list);
fmt::print("three: {} \n", fmt::join(cur_list, ","), cur_list.size());
if (cur_list.empty())return {};
std::vector container;
auto result = std::make_unique(folly::to(cur_list[0]));
decode(cur_list, 1, true, result.get(), container);
decode(cur_list, 2, true, result.get(), container);
return result;
}
Offer::TreeNode::~TreeNode() {
for (auto data: node) {
delete data;
}
}
void Offer::TreeNode::setNode(std::vector &&container) {
node = std::forward(container);
}
void Offer::TreeNode::decode(const folly::fbvector &data, int pos, bool isLeft, TreeNode *preNode,
std::vector &container) {
if (preNode == nullptr || pos >= data.size() || data[pos].front() == '#') return;
auto curNode = new TreeNode(folly::to(data[pos]));
if (isLeft) {
preNode->left = curNode;
} else {
preNode->right = curNode;
}
decode(data, pos * 2 + 1, true, curNode, container);
decode(data, (pos + 1) * 2, false, curNode, container);
container.emplace_back(curNode);
}
std::unique_ptr Offer::TreeNode::newTree(int length) {
assert(length != 0);
std::vector data;
data.reserve(length);
for (int i = 0; i < length; ++i) {
data.push_back(i + 1);
}
auto tree = TreeNode();
std::vector container;
decode(data, std::addressof(tree), 0, length - 1, true, container);
std::unique_ptr result{tree.left};
tree.left->setNode(std::move(container));
return result;
}
void Offer::TreeNode::decode(const std::vector &data, TreeNode *parent, int left, int right, bool isLeft,
std::vector &container) {
if (left > right)return;
int mid = (right + left) >> 1;
if (isLeft) {
parent->left = new TreeNode(data[mid]);
container.emplace_back(parent->left);
decode(data, parent->left, left, mid - 1, true, container);
decode(data, parent->left, mid + 1, right, false, container);
} else {
parent->right = new TreeNode(data[mid]);
container.emplace_back(parent->right);
decode(data, parent->right, left, mid - 1, true, container);
decode(data, parent->right, mid + 1, right, false, container);
}
}
Offer::ListNode::ListNode() : val(0), next{nullptr} {}
Offer::ListNode::ListNode(int x) : val(x), next(nullptr) {}
Offer::ListNode::ListNode(int x, ListNode *raw_ptr) : val(x), next(raw_ptr) {}
void Offer::ListNode::printAll(ListNode *cur) {
std::cout << "list:[";
while (cur != nullptr) {
std::cout << cur->val << ' ';
cur = cur->next;
}
std::cout << "]\n";
}
std::unique_ptr Offer::ListNode::new_list(size_t length) {
assert(length != 0);
auto result = std::make_unique(0);
result->node.reserve(length - 1);
auto root = result.get();
for (size_t i = 1; i < length; i++) {
root->next = new ListNode(i);
root = root->next;
result->node.emplace_back(root);
}
return result;
}
std::unique_ptr Offer::ListNode::new_list(const std::vector &data) {
if (data.empty())return nullptr;
auto result = std::make_unique(data[0]);
auto root = result.get();
result->node.reserve(data.size() - 1);
size_t size = data.size();
for (size_t i = 1; i < size; i++) {
root->next = new ListNode(data[i]);
root = root->next;
result->node.emplace_back(root);
}
return result;
}
Offer::ListNode::~ListNode() {
for (auto data: node) {
delete data;
}
}