Compare commits
8 Commits
9ddcad2f08
...
master
Author | SHA1 | Date | |
---|---|---|---|
b3dba32504
|
|||
f438304378
|
|||
c0cd44f606
|
|||
70d44b7e9e
|
|||
fd548c7ba8
|
|||
88959d6513
|
|||
b70046b7da
|
|||
52d9629a5c
|
@@ -110,8 +110,8 @@ IndentGotoLabels: false
|
||||
# #endif
|
||||
# #endif
|
||||
IndentPPDirectives: BeforeHash
|
||||
# IndentAccessModifiers: true
|
||||
IndentWidth: 4
|
||||
AccessModifierOffset: -4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 3
|
||||
NamespaceIndentation: None
|
||||
|
@@ -6,6 +6,9 @@ include_directories(include)
|
||||
|
||||
find_package(CURL REQUIRED)
|
||||
find_package(nlohmann_json REQUIRED)
|
||||
find_package(GTest REQUIRED)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
add_executable(leetcode-fetcher main.cpp
|
||||
src/fetcher.cpp)
|
||||
|
@@ -59,25 +59,27 @@ struct CodeDefinition
|
||||
struct ProblemContent
|
||||
{
|
||||
std::string title;
|
||||
std::string title_slug;
|
||||
std::string titleSlug;
|
||||
std::string content;
|
||||
std::vector<CodeDefinition> codeDefinitions;
|
||||
int questionId;
|
||||
|
||||
ProblemContent(std::string title,
|
||||
std::string title_slug,
|
||||
std::string titleSlug,
|
||||
std::string content,
|
||||
std::vector<CodeDefinition> codeDefinitions,
|
||||
int questionId)
|
||||
: title(std::move(title))
|
||||
, title_slug(std::move(title_slug))
|
||||
, titleSlug(std::move(titleSlug))
|
||||
, content(std::move(content))
|
||||
, codeDefinitions(std::move(codeDefinitions))
|
||||
, questionId(questionId)
|
||||
{
|
||||
}
|
||||
|
||||
std::string formatTemplate(const std::string &templateContent) const;
|
||||
[[nodiscard]] std::string formatTemplate(const std::string &templateContent) const;
|
||||
|
||||
[[nodiscard]] std::string formatFilename() const;
|
||||
};
|
||||
|
||||
struct Fetcher
|
||||
@@ -104,6 +106,8 @@ private:
|
||||
|
||||
[[nodiscard]] std::vector<LeetCodeProblem> getProblems() const;
|
||||
|
||||
[[nodiscard]] std::unique_ptr<ProblemContent> fetchProblemContent(const LeetCodeProblem &problem) const;
|
||||
|
||||
/// The callback function used by curl to write the http response content into a string.
|
||||
static size_t httpWriteCallback(void *contents, const size_t size, size_t bufferLength, void *userData)
|
||||
{
|
||||
@@ -121,6 +125,8 @@ private:
|
||||
const LeetCodeProblem &problem);
|
||||
|
||||
static std::string readTemplateFile();
|
||||
|
||||
static bool validateExistedProblem(const ProblemContent &problem);
|
||||
};
|
||||
|
||||
#endif //FETCHER_H
|
31
justfile
Normal file
31
justfile
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env just --justfile
|
||||
|
||||
update:
|
||||
git pull
|
||||
|
||||
build: update
|
||||
#!/usr/bin/env bash
|
||||
set -euxo pipefail
|
||||
mkdir -p cmake-build-debug-clang
|
||||
cd cmake-build-debug-clang
|
||||
cmake .. -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
ninja
|
||||
|
||||
fmt:
|
||||
clang-format -i src/problems/*.cpp
|
||||
|
||||
test: fmt build
|
||||
./cmake-build-debug-clang/src/problem-tests
|
||||
|
||||
commit: test
|
||||
#!/usr/bin/env bash
|
||||
set -euxo pipefail
|
||||
time=$(date "+%Y%m%d")
|
||||
message="$time finished."
|
||||
|
||||
git add -A
|
||||
git commit -m "$message"
|
||||
git push
|
||||
|
||||
pull id: build
|
||||
./cmake-build-debug-clang/leetcode-fetcher {{ id }}
|
3
main.cpp
3
main.cpp
@@ -6,8 +6,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
std::cout << "The fetcher expect the program id.";
|
||||
return -1;
|
||||
throw std::invalid_argument("The fetcher expect the program id.");
|
||||
}
|
||||
|
||||
fetcher.fetchProblem(argv[1]);
|
||||
|
7
src/CMakeLists.txt
Normal file
7
src/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
enable_testing()
|
||||
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/problems PROBLEMS_SRC)
|
||||
|
||||
add_executable(problem-tests ${PROBLEMS_SRC})
|
||||
|
||||
target_link_libraries(problem-tests GTest::gtest_main)
|
104
src/fetcher.cpp
104
src/fetcher.cpp
@@ -49,9 +49,40 @@ std::vector<LeetCodeProblem> Fetcher::getProblems() const
|
||||
return problems;
|
||||
}
|
||||
|
||||
std::string replaceString(const std::string &original,
|
||||
const std::string_view old_sub,
|
||||
const std::string_view new_sub)
|
||||
std::unique_ptr<ProblemContent> Fetcher::fetchProblemContent(const LeetCodeProblem &problem) const
|
||||
{
|
||||
curl_easy_setopt(client.get(), CURLOPT_URL, kGraphQlUrl.c_str());
|
||||
curl_easy_setopt(client.get(), CURLOPT_POST, 1L);
|
||||
|
||||
curl_slist *headers = nullptr;
|
||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||
|
||||
curl_easy_setopt(client.get(), CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
std::string requestBody = formatQueryJson(problem.questionTitleSlug).dump();
|
||||
|
||||
curl_easy_setopt(client.get(), CURLOPT_POSTFIELDS, requestBody.c_str());
|
||||
curl_easy_setopt(client.get(), CURLOPT_POSTFIELDSIZE, requestBody.size());
|
||||
|
||||
std::string responseBody;
|
||||
|
||||
curl_easy_setopt(client.get(), CURLOPT_WRITEFUNCTION, Fetcher::httpWriteCallback);
|
||||
curl_easy_setopt(client.get(), CURLOPT_WRITEDATA, &responseBody);
|
||||
|
||||
CURLcode code = curl_easy_perform(client.get());
|
||||
|
||||
if (code != CURLE_OK)
|
||||
{
|
||||
throw std::runtime_error("Failed to fetch problem.");
|
||||
}
|
||||
|
||||
const nlohmann::json jsonResponse = nlohmann::json::parse(responseBody);
|
||||
return extractContentFromJson(jsonResponse, problem);
|
||||
}
|
||||
|
||||
static std::string replaceString(const std::string &original,
|
||||
const std::string_view old_sub,
|
||||
const std::string_view new_sub)
|
||||
{
|
||||
if (old_sub.empty())
|
||||
return original; // 防止空字符串导致死循环
|
||||
@@ -108,10 +139,21 @@ std::string ProblemContent::formatTemplate(const std::string &templateContent) c
|
||||
std::string result = replaceString(templateContent, "__PROBLEM_ID__", std::to_string(questionId));
|
||||
result = replaceString(result, "__PROBLEM_TITLE__", title);
|
||||
result = replaceString(result, "__PROBLEM_DEFAULT_CODE__", it->defaultCode);
|
||||
std::string testCaseName = "P" + std::to_string(questionId);
|
||||
result = replaceString(result, "__TEST_CASE_NAME__", testCaseName);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ProblemContent::formatFilename() const
|
||||
{
|
||||
std::ostringstream stream("p");
|
||||
stream << questionId;
|
||||
stream << "-" << titleSlug << ".cpp";
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
void Fetcher::fetchProblem(const std::string &idString) const
|
||||
{
|
||||
std::vector<LeetCodeProblem> problems = getProblems();
|
||||
@@ -127,37 +169,21 @@ void Fetcher::fetchProblem(const std::string &idString) const
|
||||
throw std::runtime_error("The target problem does not exist.");
|
||||
}
|
||||
|
||||
curl_easy_setopt(client.get(), CURLOPT_URL, kGraphQlUrl.c_str());
|
||||
curl_easy_setopt(client.get(), CURLOPT_POST, 1L);
|
||||
std::unique_ptr<ProblemContent> problemContent = fetchProblemContent(*it);
|
||||
const std::string templateFile = readTemplateFile();
|
||||
std::string problemFileContent = problemContent->formatTemplate(templateFile);
|
||||
std::string problemFilename = problemContent->formatFilename();
|
||||
|
||||
curl_slist *headers = nullptr;
|
||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||
auto problemFile = std::ofstream("src/problems/" + problemFilename);
|
||||
|
||||
curl_easy_setopt(client.get(), CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
std::string requestBody = formatQueryJson(it->questionTitleSlug).dump();
|
||||
|
||||
curl_easy_setopt(client.get(), CURLOPT_POSTFIELDS, requestBody.c_str());
|
||||
curl_easy_setopt(client.get(), CURLOPT_POSTFIELDSIZE, requestBody.size());
|
||||
|
||||
std::string responseBody;
|
||||
|
||||
curl_easy_setopt(client.get(), CURLOPT_WRITEFUNCTION, Fetcher::httpWriteCallback);
|
||||
curl_easy_setopt(client.get(), CURLOPT_WRITEDATA, &responseBody);
|
||||
|
||||
CURLcode code = curl_easy_perform(client.get());
|
||||
|
||||
if (code != CURLE_OK)
|
||||
if (!problemFile.is_open())
|
||||
{
|
||||
throw std::runtime_error("Failed to fetch problem.");
|
||||
throw std::runtime_error("Failed to open problem file.");
|
||||
}
|
||||
|
||||
const nlohmann::json jsonResponse = nlohmann::json::parse(responseBody);
|
||||
const std::unique_ptr<ProblemContent> problemContent = extractContentFromJson(jsonResponse, *it);
|
||||
problemFile << problemFileContent;
|
||||
|
||||
std::string templateFile = readTemplateFile();
|
||||
|
||||
std::cout << problemContent->formatTemplate(templateFile) << std::endl;
|
||||
problemFile.close();
|
||||
}
|
||||
|
||||
nlohmann::json Fetcher::formatQueryJson(const std::string &title)
|
||||
@@ -225,4 +251,26 @@ std::string Fetcher::readTemplateFile()
|
||||
file.close();
|
||||
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
bool Fetcher::validateExistedProblem(const ProblemContent &problem)
|
||||
{
|
||||
std::filesystem::path problemDirectory = "src/problems";
|
||||
std::string defaultFilename = problem.formatFilename();
|
||||
|
||||
if (!std::filesystem::exists(problemDirectory))
|
||||
{
|
||||
throw std::runtime_error("The problem directory is not exitsed.");
|
||||
}
|
||||
|
||||
return std::ranges::any_of(std::filesystem::directory_iterator(problemDirectory),
|
||||
[&](const std::filesystem::directory_entry &entry)
|
||||
{
|
||||
if (!entry.is_regular_file())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return entry.path().filename() == defaultFilename;
|
||||
});
|
||||
}
|
40
src/problems/1-two-sum.cpp
Normal file
40
src/problems/1-two-sum.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* [1] Two Sum
|
||||
*/
|
||||
#include <bits/stdc++.h>
|
||||
#include <gtest/gtest.h>
|
||||
using namespace std;
|
||||
|
||||
|
||||
// submission codes start here
|
||||
|
||||
class Solution
|
||||
{
|
||||
public:
|
||||
vector<int> twoSum(vector<int> &nums, int target)
|
||||
{
|
||||
unordered_map<int, int> map;
|
||||
|
||||
for (int i = 0; i < nums.size(); ++i)
|
||||
{
|
||||
if (const auto &it = map.find(target - nums[i]); it != map.end())
|
||||
{
|
||||
return {it->second, i};
|
||||
}
|
||||
|
||||
map.insert({nums[i], i});
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
// submission codes endo
|
||||
|
||||
TEST(P1, Test1)
|
||||
{
|
||||
Solution s;
|
||||
vector nums = {2, 7, 11, 15};
|
||||
vector result = {0, 1};
|
||||
ASSERT_EQ(s.twoSum(nums, 9), result);
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* [1432] Max Difference You Can Get From Changing an Integer
|
||||
*/
|
||||
#include <bits/stdc++.h>
|
||||
#include <gtest/gtest.h>
|
||||
using namespace std;
|
||||
|
||||
|
||||
// submission codes start here
|
||||
|
||||
class Solution
|
||||
{
|
||||
public:
|
||||
int maxDiff(int num)
|
||||
{
|
||||
string numString = to_string(num);
|
||||
|
||||
// Select the first, not 9 number.
|
||||
int targetPos = 0;
|
||||
while (targetPos < numString.size() - 1)
|
||||
{
|
||||
if (numString[targetPos] != '9')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
targetPos += 1;
|
||||
}
|
||||
|
||||
auto maxNumber = replaceDigit(numString, numString[targetPos], '9');
|
||||
|
||||
targetPos = 0;
|
||||
char minimumChar = '1';
|
||||
// If the first number is not 1, select the first number.
|
||||
// If the first number is 1, select next, not zero number.
|
||||
if (numString[targetPos] == '1')
|
||||
{
|
||||
targetPos = 1;
|
||||
minimumChar = '0';
|
||||
while (targetPos < numString.size())
|
||||
{
|
||||
if (numString[targetPos] == '1')
|
||||
{
|
||||
// Can not replace 1 when the first number is 1.
|
||||
targetPos += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (numString[targetPos] != '0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
targetPos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
int minNumber = num;
|
||||
if (targetPos != numString.size())
|
||||
{
|
||||
minNumber = replaceDigit(numString, numString[targetPos], minimumChar);
|
||||
}
|
||||
|
||||
return maxNumber - minNumber;
|
||||
}
|
||||
|
||||
static auto replaceDigit(const string &num, char source, char target) -> int
|
||||
{
|
||||
int result = 0;
|
||||
for (const char i : num)
|
||||
{
|
||||
if (i == source)
|
||||
{
|
||||
result = result * 10 + target - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result * 10 + i - '0';
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// submission codes end
|
||||
|
||||
TEST(P1432, Test1)
|
||||
{
|
||||
ASSERT_EQ(888, Solution().maxDiff(555));
|
||||
ASSERT_EQ(8, Solution().maxDiff(9));
|
||||
ASSERT_EQ(888, Solution().maxDiff(111));
|
||||
ASSERT_EQ(80000, Solution().maxDiff(10000));
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* [2016] Maximum Difference Between Increasing Elements
|
||||
*/
|
||||
#include <bits/stdc++.h>
|
||||
#include <gtest/gtest.h>
|
||||
using namespace std;
|
||||
|
||||
|
||||
// submission codes start here
|
||||
|
||||
class Solution
|
||||
{
|
||||
public:
|
||||
int maximumDifference(vector<int> &nums)
|
||||
{
|
||||
vector<int> heap;
|
||||
heap.reserve(nums.size());
|
||||
|
||||
ranges::make_heap(heap, greater());
|
||||
|
||||
int result = -1;
|
||||
for (int i = 1; i < nums.size(); ++i)
|
||||
{
|
||||
heap.push_back(nums[i - 1]);
|
||||
ranges::push_heap(heap, greater());
|
||||
|
||||
if (heap[0] < nums[i])
|
||||
{
|
||||
result = max(result, nums[i] - heap[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// submission codes end
|
||||
|
||||
TEST(P2016, Test1)
|
||||
{
|
||||
vector nums1 = {7, 1, 5, 4};
|
||||
ASSERT_EQ(4, Solution().maximumDifference(nums1));
|
||||
|
||||
vector nums2 = {9, 4, 3, 2};
|
||||
ASSERT_EQ(-1, Solution().maximumDifference(nums2));
|
||||
|
||||
vector nums3 = {1, 5, 2, 10};
|
||||
ASSERT_EQ(9, Solution().maximumDifference(nums3));
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* [2294] Partition Array Such That Maximum Difference Is K
|
||||
*/
|
||||
#include <bits/stdc++.h>
|
||||
#include <gtest/gtest.h>
|
||||
using namespace std;
|
||||
|
||||
|
||||
// submission codes start here
|
||||
|
||||
class Solution
|
||||
{
|
||||
public:
|
||||
int partitionArray(vector<int> &nums, int k)
|
||||
{
|
||||
ranges::sort(nums);
|
||||
|
||||
// At least to split into one segment.
|
||||
int result = 1;
|
||||
int pos = 1;
|
||||
int minValue = nums[0];
|
||||
|
||||
while (pos < nums.size())
|
||||
{
|
||||
if (nums[pos] > minValue + k)
|
||||
{
|
||||
result += 1;
|
||||
minValue = nums[pos];
|
||||
}
|
||||
else
|
||||
{
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// submission codes end
|
||||
|
||||
TEST(P2294, Test1)
|
||||
{
|
||||
vector nums1 = {3, 6, 1, 2, 5};
|
||||
ASSERT_EQ(2, Solution().partitionArray(nums1, 2));
|
||||
vector nums2 = {1, 2, 3};
|
||||
ASSERT_EQ(2, Solution().partitionArray(nums2, 1));
|
||||
vector nums3 = {2, 2, 4, 5};
|
||||
ASSERT_EQ(3, Solution().partitionArray(nums3, 0));
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* [2566] Maximum Difference by Remapping a Digit
|
||||
*/
|
||||
#include <bits/stdc++.h>
|
||||
#include <gtest/gtest.h>
|
||||
using namespace std;
|
||||
|
||||
|
||||
// submission codes start here
|
||||
|
||||
class Solution
|
||||
{
|
||||
public:
|
||||
int minMaxDifference(int num)
|
||||
{
|
||||
const string numString = to_string(num);
|
||||
|
||||
// Select the first not 9 number when converting to maximum value.
|
||||
int targetPos = 0;
|
||||
while (targetPos < numString.size() - 1)
|
||||
{
|
||||
if (numString[targetPos] != '9')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
targetPos += 1;
|
||||
}
|
||||
|
||||
int maxNum = 0;
|
||||
|
||||
char targetChar = numString[targetPos];
|
||||
for (const auto c : numString)
|
||||
{
|
||||
if (c == targetChar)
|
||||
{
|
||||
maxNum = maxNum * 10 + 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxNum = maxNum * 10 + c - '0';
|
||||
}
|
||||
}
|
||||
|
||||
// The minimum value is replacing the first number into zero.
|
||||
|
||||
targetChar = numString[0];
|
||||
int minNum = 0;
|
||||
for (const auto c : numString)
|
||||
{
|
||||
if (c == targetChar)
|
||||
{
|
||||
minNum = minNum * 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
minNum = minNum * 10 + c - '0';
|
||||
}
|
||||
}
|
||||
|
||||
return maxNum - minNum;
|
||||
}
|
||||
};
|
||||
|
||||
// submission codes end
|
||||
|
||||
TEST(P2566, Test1)
|
||||
{
|
||||
ASSERT_EQ(99009, Solution().minMaxDifference(11891));
|
||||
ASSERT_EQ(99, Solution().minMaxDifference(90));
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* [2616] Minimize the Maximum Difference of Pairs
|
||||
*/
|
||||
#include <bits/stdc++.h>
|
||||
#include <gtest/gtest.h>
|
||||
using namespace std;
|
||||
|
||||
|
||||
// submission codes start here
|
||||
|
||||
class Solution
|
||||
{
|
||||
public:
|
||||
int minimizeMax(vector<int> &nums, int p)
|
||||
{
|
||||
ranges::sort(nums);
|
||||
|
||||
auto check = [&](int value) -> bool
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < nums.size() - 1; ++i)
|
||||
{
|
||||
if (nums[i + 1] - nums[i] <= value)
|
||||
{
|
||||
count += 1;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return count >= p;
|
||||
};
|
||||
|
||||
int left = 0, right = nums.back() - nums[0];
|
||||
|
||||
while (left < right)
|
||||
{
|
||||
int middle = (left + right) >> 1;
|
||||
if (check(middle))
|
||||
{
|
||||
right = middle;
|
||||
}
|
||||
else
|
||||
{
|
||||
left = middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
};
|
||||
|
||||
// submission codes end.
|
||||
|
||||
TEST(P2616, Test1)
|
||||
{
|
||||
vector nums = {10, 1, 2, 7, 1, 3};
|
||||
Solution s;
|
||||
ASSERT_EQ(s.minimizeMax(nums, 2), 1);
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* [2966] Divide Array Into Arrays With Max Difference
|
||||
*/
|
||||
#include <bits/stdc++.h>
|
||||
#include <gtest/gtest.h>
|
||||
using namespace std;
|
||||
|
||||
|
||||
// submission codes start here
|
||||
|
||||
class Solution
|
||||
{
|
||||
public:
|
||||
vector<vector<int>> divideArray(vector<int> &nums, int k)
|
||||
{
|
||||
ranges::sort(nums);
|
||||
|
||||
vector<vector<int>> result;
|
||||
bool flag = true;
|
||||
result.reserve(nums.size() / 3);
|
||||
|
||||
for (int i = 0; i < nums.size(); i += 3)
|
||||
{
|
||||
if (nums[i + 2] - nums[i + 1] > k || nums[i + 1] - nums[i] > k || nums[i + 2] - nums[i] > k)
|
||||
{
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
vector array = {nums[i], nums[i + 1], nums[i + 2]};
|
||||
result.push_back(move(array));
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
// submission codes end
|
||||
|
||||
TEST(P2966, Test1)
|
||||
{
|
||||
vector nums = {1, 3, 4, 8, 7, 9, 3, 5, 1};
|
||||
vector<vector<int>> result = {{1, 1, 3}, {3, 4, 5}, {7, 8, 9}};
|
||||
|
||||
ASSERT_EQ(result, Solution().divideArray(nums, 2));
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* [3405] Count the Number of Arrays with K Matching Adjacent Elements
|
||||
*/
|
||||
#include <bits/stdc++.h>
|
||||
#include <gtest/gtest.h>
|
||||
using namespace std;
|
||||
|
||||
|
||||
// submission codes start here
|
||||
|
||||
constexpr long long MOD = 1e9 + 7;
|
||||
constexpr long long UPPER_BOUND = 1e5;
|
||||
|
||||
static long long fact[UPPER_BOUND];
|
||||
static long long inverseFact[UPPER_BOUND];
|
||||
|
||||
class Solution
|
||||
{
|
||||
static long long quickPower(long long x, int n)
|
||||
{
|
||||
long long result = 1;
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
if ((n & 1) == 1)
|
||||
{
|
||||
result = result * x % MOD;
|
||||
}
|
||||
|
||||
x = x * x % MOD;
|
||||
n >>= 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static long long combine(int n, int m)
|
||||
{
|
||||
return fact[n] * inverseFact[m] % MOD * inverseFact[n - m] % MOD;
|
||||
}
|
||||
|
||||
static void init()
|
||||
{
|
||||
if (fact[0] != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fact[0] = 1;
|
||||
for (int i = 1; i < UPPER_BOUND; ++i)
|
||||
{
|
||||
fact[i] = fact[i - 1] * i % MOD;
|
||||
}
|
||||
|
||||
// Modular Multiplicative Inverse is calculated by the quick power.
|
||||
inverseFact[UPPER_BOUND - 1] = quickPower(fact[UPPER_BOUND - 1], MOD - 2);
|
||||
for (int i = UPPER_BOUND - 1; i > 0; --i)
|
||||
{
|
||||
inverseFact[i - 1] = inverseFact[i] * i % MOD;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
int countGoodArrays(int n, int m, int k)
|
||||
{
|
||||
init();
|
||||
const long long result = combine(n - 1, k) * m % MOD * quickPower(m - 1, n - k - 1) % MOD;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// submission codes end
|
||||
|
||||
TEST(P3405, Test1)
|
||||
{
|
||||
Solution s;
|
||||
ASSERT_EQ(4, s.countGoodArrays(3, 2, 1));
|
||||
ASSERT_EQ(6, s.countGoodArrays(4, 2, 2));
|
||||
ASSERT_EQ(2, s.countGoodArrays(5, 2, 0));
|
||||
}
|
@@ -1,9 +1,17 @@
|
||||
/**
|
||||
* [__PROBLEM_ID__] __PROBLEM_TITLE__
|
||||
*/
|
||||
#include <bits/stdc++.h>
|
||||
#include <gtest/gtest.h>
|
||||
using namespace std;
|
||||
|
||||
|
||||
// submission codes start here
|
||||
|
||||
__PROBLEM_DEFAULT_CODE__
|
||||
|
||||
// submission codes end
|
||||
|
||||
TEST(__TEST_CASE_NAME__, Test1)
|
||||
{
|
||||
}
|
Reference in New Issue
Block a user