0%

LeetCode 刷题环境搭建

1
2
3
4
5
6
编程环境:macOS + [Clion](https://www.jetbrains.com/zh-cn/clion/) + LLVM \
LeetCode 插件:
- [LeetCode Editor](https://plugins.jetbrains.com/plugin/12132-leetcode-editor)
- [旧版 v7.3](https://plugins.jetbrains.com/plugin/12132-leetcode-editor/versions/stable/133338) [[leetcode-editor-7.3.zip]]

插件使用介绍: [Github Doc](https://github.com/shuzijun/leetcode-editor/blob/master/README_ZH.md)

首先是编译工具链的配置

然后是 LeetCode 插件配置

Code FileName

1
Q_$!velocityTool.leftPadZeros(${question.frontendQuestionId},4)_${question.titleSlug}

Code Template

1
2
3
4
5
6
7
8
9
10
${question.content}

\#include "headers.hpp"

${question.code}

int main() {
cout << "Hello, ${question.title}!" << endl;
return 0;
}

以第一题 两数之和 为例

文件名:Q_0001_two-sum.cpp

文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 
//
// 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
//
// 你可以按任意顺序返回答案。
//
//
//
// 示例 1:
//
//
//输入:nums = [2,7,11,15], target = 9
//输出:[0,1]
//解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
//
//
// 示例 2:
//
//
//输入:nums = [3,2,4], target = 6
//输出:[1,2]
//
//
// 示例 3:
//
//
//输入:nums = [3,3], target = 6
//输出:[0,1]
//
//
//
//
// 提示:
//
//
// 2 <= nums.length <= 10⁴
// -10⁹ <= nums[i] <= 10⁹
// -10⁹ <= target <= 10⁹
// 只会存在一个有效答案
//
//
// 进阶:你可以想出一个时间复杂度小于 O(n²) 的算法吗?
// Related Topics 数组 哈希表 👍 12817 👎 0

#include "headers.hpp"

//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public:
vector<int> twoSum(vector<int> &nums, int target) {

}
};

//leetcode submit region end(Prohibit modification and deletion)

int main() {
cout << "Hello, 两数之和!" << endl;
return 0;
}

项目结构如下

CMakeList.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cmake_minimum_required(VERSION 3.17)  
project(LeetCode VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)

include_directories(${CMAKE_SOURCE_DIR})
ADD_DEFINITIONS(-DLOCAL_MODE)
ADD_DEFINITIONS(-Dnull=nullptr)
# 遍历 ${CMAKE_SOURCE_DIR}/editor/cn 下面所有的题目代码文件,存储到 LEETCODE_SOURCE 数组中
file(GLOB LEETCODE_SOURCE RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/editor/cn/Q_*.cpp)
set(COUNT 0)
# 遍历 LEETCODE_SOURCE 数组,添加编译目标
foreach (LEETCODE_SOURCE_FILE ${LEETCODE_SOURCE})
# 获取不带后缀的文件名
STRING(REGEX REPLACE ".+/(.+)\\..*" "\\1" FILE_NAME ${LEETCODE_SOURCE_FILE})
# 替换中文,空格
STRING(REPLACE "剑指 Offer II " "Offer_II-" FILE_NAME ${FILE_NAME})
STRING(REPLACE "剑指 Offer " "Offer_I-" FILE_NAME ${FILE_NAME})
STRING(REPLACE "面试题 " "Interview-" FILE_NAME ${FILE_NAME})
add_executable(${FILE_NAME} ${LEETCODE_SOURCE_FILE})
MATH(EXPR COUNT "${COUNT}+1")
message(${COUNT} "\tADD EXECUTABLE " ${FILE_NAME})
endforeach ()
add_executable(main main.cpp)

headers.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//  
// Created by 徐磊磊 on 2021/12/9.//

#ifndef LEETCODE_HEADERS_HPP
#define LEETCODE_HEADERS_HPP

#include <vector>
#include <iostream>
#include <unordered_map>
#include <deque>
#include <queue>
#include <stack>
#include <variant>
#include <map>
#include <unordered_set>
#include <sstream>
#include <algorithm>
#include "TreePrinter.hpp"
#include <regex>
#include <random>
using namespace std;

struct ListNode {
int val;
ListNode *next;

ListNode() : val(0), next(nullptr) {}

ListNode(int x) : val(x), next(nullptr) {}

ListNode(int x, ListNode *next) : val(x), next(next) {}
};

struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;

TreeNode() : val(0), left(nullptr), right(nullptr) {}

TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

namespace utils {

ListNode *init_list(const std::vector<int> &nums) {
ListNode *res = nullptr;
for (int i = (int) nums.size() - 1; i >= 0; --i)
res = new ListNode(nums[i], res);
return res;
}

TreeNode *init_tree(deque<variant<int, nullptr_t>> nums) {
TreeNode *result = nullptr;
if (nums.empty())
return result;
result = new TreeNode(get<int>(nums.front()));
nums.pop_front();

queue<TreeNode *> node_queue;
node_queue.push(result);

while (!node_queue.empty()) {
TreeNode *curNode = node_queue.front();
node_queue.pop();
if (!nums.empty()) {
curNode->left = std::holds_alternative<int>(nums.front()) ? new TreeNode(get<int>(nums.front()))
: nullptr;
nums.pop_front();
}
if (!nums.empty()) {
curNode->right = std::holds_alternative<int>(nums.front()) ? new TreeNode(get<int>(nums.front()))
: nullptr;
nums.pop_front();
}
if (curNode->left)
node_queue.push(curNode->left);
if (curNode->right)
node_queue.push(curNode->right);
}
return result;
}

void print_link_list(ListNode *list) {
if (!list) {
std::cout << std::endl;
return;
}
while (list) {
std::cout << list->val << (list->next ? " --> " : "\n");
list = list->next;
}
}

void print_tree(TreeNode *root) {
tree_printer::TreePrinter<TreeNode> printer(
[](TreeNode *node) -> std::string { return std::to_string(node->val); },
[](TreeNode *node) -> TreeNode * { return node->left; },
[](TreeNode *node) -> TreeNode * { return node->right; }
);
printer.setHspace(5);
printer.printTree(root);
}

template<typename T>
void print_vector(const vector<T> &list) {
cout << "[";
for (int i = 0; i < list.size(); ++i) {
string delimiter;
if (is_same<T, string>::value)
delimiter = "\"";
if (is_same<T, char>::value)
delimiter = "\'";
cout << (i == 0 ? "" : ", ") << delimiter << list[i] << delimiter;
}
cout << "]" << endl;
}
}
#endif //LEETCODE_HEADERS_HPP

Tips:

  1. 每次新增题目的时候 重新加载 CMake 项目即可运行当前文件。
  2. 如果需要本地调试,在当前文件 main 函数中进行调用即可。
  3. 如果需要额外引入头文件,将其添加到 headers.hpp 文件即可实现
  4. 如果需要编写工具函数,需要在 headers.hpp 文件的 utils 命名空间中实现,采用类如 utils:: init_list() 的方式调用

下面的第 21 题就是很好的实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/**
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。



示例 1:


输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]


示例 2:


输入:l1 = [], l2 = []
输出:[]


示例 3:


输入:l1 = [], l2 = [0]
输出:[0]




提示:


两个链表的节点数目范围是 [0, 50]
-100 <= Node.val <= 100
l1 和 l2 均按 非递减顺序 排列

Related Topics 递归 链表 👍 2084 👎 0

*/

#include "headers.hpp"

//leetcode submit region begin(Prohibit modification and deletion)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode *mergeTwoLists(ListNode *list1, ListNode *list2) {
ListNode *result = new ListNode(), *tail = result;
while (list1 || list2) {
if (not list1) {
tail->next = list2;
break;
}
if (not list2) {
tail->next = list1;
break;
}
if (list1->val < list2->val) {
tail->next = list1;
tail = tail->next;
list1 = list1->next;
} else {
tail->next = list2;
tail = tail->next;
list2 = list2->next;
}
}
return result->next;
}
};
//leetcode submit region end(Prohibit modification and deletion)


int main() {
cout << "Hello, 合并两个有序链表!" << endl;
ListNode *list1 = utils::init_list({1, 3, 4});
ListNode *list2 = utils::init_list({1, 2, 4});
cout << "list1 ";
utils::print_list(list1);
cout << "list2 ";
utils::print_list(list2);
ListNode *list3 = Solution().mergeTwoLists(list1, list2);
cout << "list3 ";
utils::print_list(list3);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
6:24 PM	构建 在 413毫秒 内完成

6:24 PM info: 已提交,请稍等

6:24 PM info
运行成功:
测试用例:[1,2,4]
[1,3,4]
测试结果:[1,1,2,3,4,4]
期望结果:[1,1,2,3,4,4]
stdout:


6:25 PM info: 已提交,请稍等

6:25 PM info
解答成功:
执行耗时:4 ms,击败了93.00% 的C++用户
内存消耗:14.4 MB,击败了55.64% 的C++用户