From 2f68211f80876cbec9e4c07b0ee6ffeb150a8999 Mon Sep 17 00:00:00 2001 From: Kanata Raiden Date: Sun, 9 Apr 2023 02:12:40 +0800 Subject: [PATCH] First commit --- .gitignore | 2 + .idea/.gitignore | 8 ++ .idea/.name | 1 + CMakeLists.txt | 23 ++++ src/chapter-2/10_get_fibonacci_item.cpp | 50 +++++++++ src/chapter-2/11_get_min_in_rotated_array.cpp | 48 ++++++++ src/chapter-2/12_exist_word_in_matrix.cpp | 62 +++++++++++ src/chapter-2/13_robot_moving_count.cpp | 60 ++++++++++ src/chapter-2/14_cutting_rope.cpp | 73 +++++++++++++ src/chapter-2/15_get_number_of_1B.cpp | 17 +++ src/chapter-2/3_find_repeat_number.cpp | 35 ++++++ src/chapter-2/4_find_number_in_2darray.cpp | 31 ++++++ src/chapter-2/5_replace_space.cpp | 37 +++++++ src/chapter-2/6_reverse_print.cpp | 26 +++++ src/chapter-2/7_build_tree.cpp | 53 +++++++++ src/chapter-2/8_get_next.cpp | 33 ++++++ src/chapter-2/9_cqueue.cpp | 29 +++++ src/chapter-3/16_integer_pow.cpp | 33 ++++++ src/chapter-3/17_print_one_to_n.cpp | 19 ++++ src/chapter-3/18_delete_node.cpp | 76 +++++++++++++ src/chapter-3/19_match_regular_expression.cpp | 16 +++ src/chapter-3/20_is_number.cpp | 59 ++++++++++ src/data-structure/binary_tree.cpp | 17 +++ src/include/data_structure.h | 26 +++++ src/include/solution.h | 103 ++++++++++++++++++ src/include/util.h | 8 ++ src/main.cpp | 12 ++ 27 files changed, 957 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/.name create mode 100644 CMakeLists.txt create mode 100644 src/chapter-2/10_get_fibonacci_item.cpp create mode 100644 src/chapter-2/11_get_min_in_rotated_array.cpp create mode 100644 src/chapter-2/12_exist_word_in_matrix.cpp create mode 100644 src/chapter-2/13_robot_moving_count.cpp create mode 100644 src/chapter-2/14_cutting_rope.cpp create mode 100644 src/chapter-2/15_get_number_of_1B.cpp create mode 100644 src/chapter-2/3_find_repeat_number.cpp create mode 100644 src/chapter-2/4_find_number_in_2darray.cpp create mode 100644 src/chapter-2/5_replace_space.cpp create mode 100644 src/chapter-2/6_reverse_print.cpp create mode 100644 src/chapter-2/7_build_tree.cpp create mode 100644 src/chapter-2/8_get_next.cpp create mode 100644 src/chapter-2/9_cqueue.cpp create mode 100644 src/chapter-3/16_integer_pow.cpp create mode 100644 src/chapter-3/17_print_one_to_n.cpp create mode 100644 src/chapter-3/18_delete_node.cpp create mode 100644 src/chapter-3/19_match_regular_expression.cpp create mode 100644 src/chapter-3/20_is_number.cpp create mode 100644 src/data-structure/binary_tree.cpp create mode 100644 src/include/data_structure.h create mode 100644 src/include/solution.h create mode 100644 src/include/util.h create mode 100644 src/main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c289a1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Project exclude paths +/cmake-build-debug/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..fc00f0f --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +coding-interviews-cpp \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..36ae981 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.24) +project(coding-interviews-cpp) + +set(CMAKE_CXX_STANDARD 17) + +aux_source_directory( + src/chapter-2 + CHAPTER_2 +) + +aux_source_directory( + src/chapter-3 + CHAPTER_3 +) + +aux_source_directory( + src/data-structure + DS +) + +include_directories(src/include) + +add_executable(coding-interviews-cpp src/main.cpp ${CHAPTER_2} ${CHAPTER_3} ${DS}) diff --git a/src/chapter-2/10_get_fibonacci_item.cpp b/src/chapter-2/10_get_fibonacci_item.cpp new file mode 100644 index 0000000..aca431b --- /dev/null +++ b/src/chapter-2/10_get_fibonacci_item.cpp @@ -0,0 +1,50 @@ +#include "solution.h" + +/* + * 10-1. 斐波那契数列 + * 写一个函数,输入 n ,求斐波那契 (Fibonacci) 数列的第 n 项(即 F(N))。 + */ + +int solution::GetFibonacciItem(int n) { + constexpr int result[2] = {0, 1}; + if (n < 2) { + return result[n]; + } + + int fibN = 0; + int fibNMinusOne = 1; + int fibNMinusTwo = 0; + + for (int i = 2; i <= n; ++i) { + fibN = (fibNMinusOne + fibNMinusTwo) % 1000000007; + fibNMinusTwo = fibNMinusOne; + fibNMinusOne = fibN; + } + + return fibN; +} + +/* + * 10-2. 青蛙跳台阶问题 + * 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级的台阶总共有多少种跳法。 + * 答案需要取模1e9+7(1000000007),如计算初始结果为:1000000008,请返回1。 + */ + +int solution::NumWays(int n) { + constexpr int result[2] = {1, 1}; + if (n < 2) { + return result[n]; + } + + int fibN = 0; + int fibNMinusOne = 1; + int fibNMinusTwo = 1; + + for (int i = 2; i <= n; ++i) { + fibN = (fibNMinusOne + fibNMinusTwo) % 1000000007; + fibNMinusTwo = fibNMinusOne; + fibNMinusOne = fibN; + } + + return fibN; +} diff --git a/src/chapter-2/11_get_min_in_rotated_array.cpp b/src/chapter-2/11_get_min_in_rotated_array.cpp new file mode 100644 index 0000000..6b9a2bb --- /dev/null +++ b/src/chapter-2/11_get_min_in_rotated_array.cpp @@ -0,0 +1,48 @@ +#include "solution.h" + +/* + * 11. 旋转数组的最小数字 + * 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 + * 给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。 + * 请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。 + */ + +int solution::GetMinInRotatedArray(vector& numbers) { + int index1 = 0; + int index2 = numbers.size() - 1; + int indexMid = index1; + + auto GetMinInOrder = [numbers]() -> int { + int min = INT32_MAX; + for (const int num: numbers) { + if (num < min) { + min = num; + } + } + return min; + }; + + while (numbers[index1] >= numbers[index2]) { + // 跳出条件 + if (index2 - index1 == 1) { + indexMid = index2; + break; + } + + indexMid = (index1 + index2) / 2; + + // 若无法比较,则按照顺序查找 + if (numbers[index1] == numbers[index2] && numbers[index1] == numbers[indexMid]) { + return GetMinInOrder(); + } + + // 迭代中间元素 + if (numbers[index1] <= numbers[indexMid]) { + index1 = indexMid; + } else if (numbers[index2] >= numbers[indexMid]) { + index2 = indexMid; + } + } + + return numbers[indexMid]; +} diff --git a/src/chapter-2/12_exist_word_in_matrix.cpp b/src/chapter-2/12_exist_word_in_matrix.cpp new file mode 100644 index 0000000..b235f44 --- /dev/null +++ b/src/chapter-2/12_exist_word_in_matrix.cpp @@ -0,0 +1,62 @@ +#include "solution.h" + +/* + * 12. 矩阵中的路径 + * 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true;否则,返回 false。 + * 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。 + * 同一个单元格内的字母不允许被重复使用。 + */ + +bool solution::ExistWordInMatrix(vector>& board, string word) { + if (board.empty()) { + return false; + } + + const int rows = board.size(); + const int cols = board[0].size(); + int pathLength = 0; + + bool** visited = new bool* [rows]; + for (int i = 0; i < rows; ++i) { + visited[i] = new bool[cols]; + std::fill(visited[i], visited[i] + cols + 1, false); + } + + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < cols; ++j) { + if (HasPath(board, word, i, j, pathLength, visited)) { + return true; + } + } + } + + delete[] visited; + return false; +} + +bool solution::HasPath(vector>& board, string word, int row, int col, int& pathLength, bool**& visited) { + if (pathLength == word.length()) { + return true; + } + + bool hasPath = false; + + if ((row >= 0 && row < board.size()) && (col >= 0 && col < board[0].size()) + && board[row][col] == word[pathLength] + && !visited[row][col]) { + ++pathLength; + visited[row][col] = true; + + hasPath = HasPath(board, word, row + 1, col, pathLength, visited) || + HasPath(board, word, row, col + 1, pathLength, visited) || + HasPath(board, word, row - 1, col, pathLength, visited) || + HasPath(board, word, row, col - 1, pathLength, visited); + + if (!hasPath) { + --pathLength; + visited[row][col] = false; + } + } + + return hasPath; +} diff --git a/src/chapter-2/13_robot_moving_count.cpp b/src/chapter-2/13_robot_moving_count.cpp new file mode 100644 index 0000000..9d9d3c2 --- /dev/null +++ b/src/chapter-2/13_robot_moving_count.cpp @@ -0,0 +1,60 @@ +#include "solution.h" + +/* + * 13. 机器人的运动范围 + * 地上有一个m行n列的方格。一个机器人从坐标(0, 0)的格子开始移动, + * 它每次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和大于k的格子。 + */ + +int solution::MovingCount(int m, int n, int k) { + if (m <= 0 || n <= 0 || k < 0) { + return 0; + } + + bool** visited = new bool* [m]; + for (int i = 0; i < m; ++i) { + visited[i] = new bool[n]; + std::fill(visited[i], visited[i] + n, false); + } + + int count = MovingCountCore(m, n, k, 0, 0, visited); + for (int i = 0; i < m; ++i) { + delete[] visited[i]; + } + delete[] visited; + + return count; +} + +int solution::MovingCountCore(int m, int n, int k, int row, int col, bool** visited) { + int count = 0; + if (IsReached(m, n, k, row, col, visited)) { + visited[row][col] = true; + + count = 1 + MovingCountCore(m, n, k, row + 1, col, visited) + + MovingCountCore(m, n, k, row, col + 1, visited) + + MovingCountCore(m, n, k, row - 1, col, visited) + + MovingCountCore(m, n, k, row, col - 1, visited); + } + + return count; +} + +bool solution::IsReached(int m, int n, int k, int row, int col, bool** visited) { + if ((row >= 0 && row < m) && (col >= 0 && col < n) + && !visited[row][col] + && GetDigitSum(row) + GetDigitSum(col) <= k) { + return true; + } else { + return false; + } +} + +int solution::GetDigitSum(int num) { + int sum = 0; + while (num > 0) { + sum += num % 10; + num /= 10; + } + return sum; +} diff --git a/src/chapter-2/14_cutting_rope.cpp b/src/chapter-2/14_cutting_rope.cpp new file mode 100644 index 0000000..ad828b9 --- /dev/null +++ b/src/chapter-2/14_cutting_rope.cpp @@ -0,0 +1,73 @@ +#include "solution.h" + +/* + * 14-1. 剪绳子-I + * 给你一根长度为n的绳子,请把绳子剪成整数长度的m段(m、n都是整数,n>1并且m>1), + * 每段绳子的长度记为k[0],k[1]...k[m-1]。请问k[0]*k[1]*...*k[m-1]可能的 + * 最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时 + * 得到的最大乘积是18。 + */ + +int solution::CuttingRope_DP(int n) { + if (n <= 1) return 0; + if (n == 2) return 1; + if (n == 3) return 2; + + vector products = {0, 1, 2, 3}; + products.resize(n + 1); + + int maxProduct; + for (int i = 4; i <= n; ++i) { + maxProduct = 0; + for (int j = 1; j <= i / 2; ++j) { + int product = products[j] * products[i - j]; + if (maxProduct < product) { + maxProduct = product; + } + products[i] = maxProduct; + } + } + + maxProduct = products[n]; + return maxProduct; +} + + +/* + * 14-2. 剪绳子-II + * 给你一根长度为n的绳子,请把绳子剪成整数长度的m段(m、n都是整数,n>1并且m>1), + * 每段绳子的长度记为k[0],k[1]...k[m - 1] 。请问 k[0]*k[1]*...*k[m - 1] + * 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段, + * 此时得到的最大乘积是18。答案需要取模 e9+7(1000000007,如计算初始结果为:1000000008,请返回 1。 + */ + +int solution::CuttingRope_GD(int n) { + if (n <= 1) return 0; + if (n == 2) return 1; + if (n == 3) return 2; + + int timesOf3 = n / 3; + if (n - timesOf3 * 3 == 1) --timesOf3; + int timesOf2 = (n - timesOf3 * 3) / 2; + + long long result = + (FastPowerRemainder(3, timesOf3, 1000000007) * FastPowerRemainder(2, timesOf2, 1000000007)) % 1000000007; + return static_cast(result); +} + +long long solution::FastPowerRemainder(int x, int a, int p) { + long long remainder = 1; + long long base = x; + long long exp = a; + long long divisor = p; + + while (exp > 0) { + if (exp % 2 == 1) { + remainder = (remainder * base) % divisor; + } + base = (base * base) % divisor; + exp /= 2; + } + + return remainder; +} diff --git a/src/chapter-2/15_get_number_of_1B.cpp b/src/chapter-2/15_get_number_of_1B.cpp new file mode 100644 index 0000000..d34d480 --- /dev/null +++ b/src/chapter-2/15_get_number_of_1B.cpp @@ -0,0 +1,17 @@ +#include "solution.h" + +/* + * 15. 二进制中1的个数 + * 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为'1'的个数(也被称为 汉明重量).)。 + */ + +int solution::GetNumberOf1B(uint32_t n) { + int count = 0; + + while (n) { + ++count; + n = (n - 1) & n; + } + + return count; +} diff --git a/src/chapter-2/3_find_repeat_number.cpp b/src/chapter-2/3_find_repeat_number.cpp new file mode 100644 index 0000000..f778f2f --- /dev/null +++ b/src/chapter-2/3_find_repeat_number.cpp @@ -0,0 +1,35 @@ +#include "solution.h" + +/* + * 03. 数组中重复的数字 + * 在一个长度为n的数组 nums 里的所有数字都在0~n-1的范围内。 + * 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。 + */ + +int solution::FindRepeatNumber(vector& nums) { + const int length = nums.size(); + + if (length == 0) { + return false; + } + + for (int i = 0; i < length; ++i) { + if (nums[i] < 0 || nums[i] > length - 1) { + return false; + } + } + + for (int i = 0; i < length; ++i) { + while (nums[i] != i) { + int& value = nums[i]; + + if (nums[value] == value) { + return value; + } + + std::swap(value, nums[value]); + } + } + + return -1; +} diff --git a/src/chapter-2/4_find_number_in_2darray.cpp b/src/chapter-2/4_find_number_in_2darray.cpp new file mode 100644 index 0000000..66d6267 --- /dev/null +++ b/src/chapter-2/4_find_number_in_2darray.cpp @@ -0,0 +1,31 @@ +#include "solution.h" + +/* + * 04. 二维数组中的查找 + * 在一个 n * m 的二维数组中,每一行都按照从左到右非递减的顺序排序, + * 每一列都按照从上到下非递减的顺序排序。请完成一个高效的函数, + * 输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 + */ + +bool solution::FindNumberIn2DArray(vector>& matrix, int target) { + if (matrix.empty() || matrix[0].empty()) { + return false; + } + + int row = 0; + int col = matrix[0].size() - 1; + + while (row <= matrix.size() - 1 && col >= 0) { + const int value = matrix[row][col]; + + if (value == target) { + return true; + } else if (value > target) { + --col; + } else { + ++row; + } + } + + return false; +} diff --git a/src/chapter-2/5_replace_space.cpp b/src/chapter-2/5_replace_space.cpp new file mode 100644 index 0000000..fd3bb62 --- /dev/null +++ b/src/chapter-2/5_replace_space.cpp @@ -0,0 +1,37 @@ +#include "solution.h" + +/* + * 05. 替换空格 + * 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。 + */ + +string solution::ReplaceSpace(string s) { + int numOfSpace = 0; + const int originalLength = s.size(); + + for (const char ch: s) { + if (ch == ' ') { + ++numOfSpace; + } + } + + const int newLength = originalLength + numOfSpace * 2; + s.resize(newLength); + + int indexOfOriginal = originalLength - 1; + int indexOfNew = newLength - 1; + + while (indexOfOriginal != indexOfNew) { + if (s[indexOfOriginal] != ' ') { + s[indexOfNew--] = s[indexOfOriginal]; + } else { + s[indexOfNew--] = '0'; + s[indexOfNew--] = '2'; + s[indexOfNew--] = '%'; + } + + --indexOfOriginal; + } + + return s; +} diff --git a/src/chapter-2/6_reverse_print.cpp b/src/chapter-2/6_reverse_print.cpp new file mode 100644 index 0000000..8be8f3a --- /dev/null +++ b/src/chapter-2/6_reverse_print.cpp @@ -0,0 +1,26 @@ +#include "solution.h" + +/* + * 06. 从尾到头打印链表 + * 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。 + */ + +vector solution::ReversePrint(ListNode* head) { + ListNode* pNode = head; + std::stack nodes; + + while (pNode != nullptr) { + nodes.push(pNode); + pNode = pNode->next; + } + + vector result; + + while (!nodes.empty()) { + pNode = nodes.top(); + result.push_back(pNode->val); + nodes.pop(); + } + + return result; +} diff --git a/src/chapter-2/7_build_tree.cpp b/src/chapter-2/7_build_tree.cpp new file mode 100644 index 0000000..edb14c7 --- /dev/null +++ b/src/chapter-2/7_build_tree.cpp @@ -0,0 +1,53 @@ +#include "solution.h" +#include "data_structure.h" + +/* + * 07. 重建二叉树 + * 输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。 + * 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 + */ + +ds::TreeNode* solution::BuildTree(vector& preOrder, vector& inOrder) { + if (preOrder.empty() || inOrder.empty()) { + return nullptr; + } + + return ConstructCore(preOrder, inOrder); +} + +ds::TreeNode* solution::ConstructCore(vector& preOrder, vector& inOrder) { + // 通过前序遍历找到根节点 + const int rootValue = preOrder[0]; + TreeNode* root = new TreeNode(rootValue); + + // 若该树只有根节点,则直接返回 + if (preOrder.size() == 1 && inOrder.size() == 1 && preOrder[0] == inOrder[0]) { + return root; + } + + // 找到根节点在中序遍历中的位置 + auto rootInOrder = inOrder.begin(); + while (rootInOrder < inOrder.end() && *rootInOrder != rootValue) { + ++rootInOrder; + } + + // 划分左右子树 + const int leftChildLength = rootInOrder - inOrder.begin(); + vector leftChildInOrder(inOrder.begin(), rootInOrder); + vector leftChildPreOrder(preOrder.begin() + 1, preOrder.begin() + 1 + leftChildLength); + + const int rightChildLength = preOrder.size() - leftChildLength - 1; + vector rightChildInOrder(rootInOrder + 1, inOrder.end()); + vector rightChildPreOrder(preOrder.end() - rightChildLength, preOrder.end()); + + // 通过递归分配子节点 + if (leftChildLength > 0) { + root->left = ConstructCore(leftChildPreOrder, leftChildInOrder); + } + + if (rightChildLength > 0) { + root->right = ConstructCore(rightChildPreOrder, rightChildInOrder); + } + + return root; +} diff --git a/src/chapter-2/8_get_next.cpp b/src/chapter-2/8_get_next.cpp new file mode 100644 index 0000000..328a7a8 --- /dev/null +++ b/src/chapter-2/8_get_next.cpp @@ -0,0 +1,33 @@ +#include "solution.h" +#include "data_structure.h" + +/* + * 8. 二叉树的下一个节点 + * 给定一颗二叉树和其中一个节点,如何找出中序遍历序列的下一个节点。 + */ + +ds::TreeNode* solution::GetNext(TreeNode* pNode) { + if (pNode == nullptr) { + return nullptr; + } + + TreeNode* pNext = nullptr; + + if (pNode->right != nullptr) { + TreeNode* pRight = pNode->right; + while (pRight->left != nullptr) { + pRight = pRight->left; + } + pNext = pRight; + } else if (pNode->parent != nullptr) { + TreeNode* pCurrent = pNode; + TreeNode* pParent = pNode->parent; + while (pParent != nullptr && pCurrent == pParent->right) { + pCurrent = pParent; + pParent = pParent->parent; + } + pNext = pParent; + } + + return pNext; +} diff --git a/src/chapter-2/9_cqueue.cpp b/src/chapter-2/9_cqueue.cpp new file mode 100644 index 0000000..e43fdbf --- /dev/null +++ b/src/chapter-2/9_cqueue.cpp @@ -0,0 +1,29 @@ +#include "solution.h" + +/* + * 09. 用两个栈实现队列 + * 用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead, + * 分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回-1) + */ + +void solution::CQueue::AppendTail(int value) { + inputStack.push(value); +} + +int solution::CQueue::DeleteHead() { + if (outputStack.empty()) { + if (inputStack.empty()) { + return -1; + } + + while (!inputStack.empty()) { + int temp = inputStack.top(); + inputStack.pop(); + outputStack.push(temp); + } + } + + const int result = outputStack.top(); + outputStack.pop(); + return result; +} diff --git a/src/chapter-3/16_integer_pow.cpp b/src/chapter-3/16_integer_pow.cpp new file mode 100644 index 0000000..86b6f0e --- /dev/null +++ b/src/chapter-3/16_integer_pow.cpp @@ -0,0 +1,33 @@ +#include "solution.h" + +/* + * 16. 数值的整数次方 + * 实现 pow(x, n) ,即计算 x 的 n 次幂函数。不得使用库函数,同时不需要考虑大数问题。 + */ + +double solution::MyPow(double x, int n) { + if (n == 0) { + return 1; + } + if (n == 1) { + return x; + } + + bool isMinus = false; + if (n < 0) { + n = abs(n); + isMinus = true; + } + + double result = MyPow(x, n / 2); + result *= result; + if (n % 2 == 1) { + result *= x; + } + + if (isMinus) { + return 1 / result; + } else { + return result; + } +} diff --git a/src/chapter-3/17_print_one_to_n.cpp b/src/chapter-3/17_print_one_to_n.cpp new file mode 100644 index 0000000..c3320c6 --- /dev/null +++ b/src/chapter-3/17_print_one_to_n.cpp @@ -0,0 +1,19 @@ +#include "solution.h" + +#include + +/* + * 17. 打印从1到最大的n位数 + * 输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1、2、3 一直到最大的3位数999。 + */ + +vector solution::PrintNumbers(int n) { + int maxNum = pow(10, n); + vector result; + + for (int i = 1; i < maxNum; ++i) { + result.push_back(i); + } + + return result; +} diff --git a/src/chapter-3/18_delete_node.cpp b/src/chapter-3/18_delete_node.cpp new file mode 100644 index 0000000..9c37dd4 --- /dev/null +++ b/src/chapter-3/18_delete_node.cpp @@ -0,0 +1,76 @@ +#include "solution.h" +#include "data_structure.h" + +/* + * 18-1. 删除链表的节点 + * 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。 + * 返回删除后的链表的头节点。 + */ + +ds::ListNode* solution::DeleteNode(ListNode* head, int val) { + if (head == nullptr) { + return nullptr; + } + + ListNode* pHead = new ListNode(0); + pHead->next = head; + + ListNode* pPreNode = pHead; + ListNode* pNode = head; + while (pNode != nullptr) { + if (pNode->val == val) { + pPreNode->next = pNode->next; + break; + } + pPreNode = pNode; + pNode = pNode->next; + } + + return pHead->next; +} + + +/* + * 18-2. 删除链表中重复的节点 + * 在一个排序的链表中,删除重复的节点。 + * 返回删除后的链表的头节点。 + */ + +void solution::DeleteDuplication(ListNode** pHead) { + if (pHead == nullptr || *pHead == nullptr) { + return; + } + + ListNode* pPreNode = nullptr; + ListNode* pNode = *pHead; + + while (pNode != nullptr) { + ListNode* pNext = pNode->next; + bool isDeleted = false; + + if (pNext != nullptr && pNext->val == pNode->val) { + isDeleted = true; + } + + if (!isDeleted) { + pPreNode = pNode; + pNode = pNext; + } else { + int value = pNode->val; + ListNode* pDeleted = pNode; + + while (pDeleted != nullptr && pDeleted->val == value) { + pNext = pDeleted->next; + delete pDeleted; + pDeleted = pNext; + } + + if (pPreNode == nullptr) { + *pHead = pNext; + } else { + pPreNode->next = pNext; + } + pNode = pNext; + } + } +} diff --git a/src/chapter-3/19_match_regular_expression.cpp b/src/chapter-3/19_match_regular_expression.cpp new file mode 100644 index 0000000..9e057d2 --- /dev/null +++ b/src/chapter-3/19_match_regular_expression.cpp @@ -0,0 +1,16 @@ +#include "solution.h" + +/* + * 19. 正则表达式匹配 + * 请实现一个函数用来匹配包含'. '和'*'的正则表达式。模式中的字符'.'表示任意一个字符, + * 而'*'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。 + * 例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但与"aa.a"和"ab*a"均不匹配。 + */ + +bool solution::MatchRegularExpression(string str, string pattern) { + if(str== ""||pattern==""){ + return false; + } + + +} diff --git a/src/chapter-3/20_is_number.cpp b/src/chapter-3/20_is_number.cpp new file mode 100644 index 0000000..ac91520 --- /dev/null +++ b/src/chapter-3/20_is_number.cpp @@ -0,0 +1,59 @@ +#include "solution.h" + +using std::string; + +/* + * 20. 表示数值的字符串 + * 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。 + */ + +bool solution::IsNumber(string s) { + if (s.empty()) { + return false; + } + + // 去除首尾空格 + s.erase(0, s.find_first_not_of(" ")); + s.erase(s.find_last_not_of(" ") + 1); + + bool isNumber = ScanInteger(s); + + // 处理小数部分 + if (s[0] == '.') { + s = CutNumString(s); + isNumber = ScanUnsignedInteger(s) || isNumber; + } + // 处理指数部分 + if (s[0] == 'e' || s[0] == 'E') { + s = CutNumString(s); + isNumber = ScanInteger(s) && isNumber; + } + // 处理其他情况 + if (!s.empty()) { + isNumber = false; + } + + return isNumber; +} + +string solution::CutNumString(string& s) { + string newStr; + return newStr.assign(s, 1, s.length() - 1); +} + +bool solution::ScanUnsignedInteger(string& s) { + string before = s; + while (s[0] >= '0' && s[0] <= '9') { + s = CutNumString(s); + } + bool res = s.length() < before.length(); + return res; +} + +bool solution::ScanInteger(string& s) { + if (s[0] == '+' || s[0] == '-') { + s = CutNumString(s); + } + bool res = ScanUnsignedInteger(s); + return res; +} diff --git a/src/data-structure/binary_tree.cpp b/src/data-structure/binary_tree.cpp new file mode 100644 index 0000000..2a144ab --- /dev/null +++ b/src/data-structure/binary_tree.cpp @@ -0,0 +1,17 @@ +#include + +#include "data_structure.h" + +using namespace ds; + +void PrintListNode(ListNode* head) { + if (head == nullptr) { + return; + } + + ListNode* pNode = head; + while (pNode != nullptr) { + std::printf("node value = %d\n", pNode->val); + pNode = pNode->next; + } +} diff --git a/src/include/data_structure.h b/src/include/data_structure.h new file mode 100644 index 0000000..1ace627 --- /dev/null +++ b/src/include/data_structure.h @@ -0,0 +1,26 @@ +#pragma once + +namespace ds { +// The implementation of LinkedList +struct ListNode { + int val; + ListNode* next; + + explicit ListNode(int x) : val(x), next(nullptr) {} + + explicit ListNode(int x, ListNode* next) : val(x), next(next) {} +}; + +void PrintListNode(ListNode* head); + + +// The implementation of BinaryTree +struct TreeNode { + int val; + TreeNode* left; + TreeNode* right; + TreeNode* parent; + + explicit TreeNode(int x) : val(x), left(nullptr), right(nullptr), parent(nullptr) {} +}; +} diff --git a/src/include/solution.h b/src/include/solution.h new file mode 100644 index 0000000..7a5dad1 --- /dev/null +++ b/src/include/solution.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include +#include + +#include "data_structure.h" + +using namespace ds; +using std::vector; +using std::stack; +using std::string; + +namespace solution { +// Question 3 +int FindRepeatNumber(vector& nums); + +// Question 4 +bool FindNumberIn2DArray(vector>& matrix, int target); + +// Question 5 +string ReplaceSpace(string s); + +// Question 6 +vector ReversePrint(ListNode* head); + +// Question 7 +TreeNode* BuildTree(vector& preOrder, vector& inOrder); + +TreeNode* ConstructCore(vector& preOrder, vector& inOrder); + +// Question 8 +TreeNode* GetNext(TreeNode* pNode); + +// Question 9 +class CQueue { +public: + CQueue() = default; + + void AppendTail(int value); + + int DeleteHead(); + +private: + stack inputStack; + stack outputStack; +}; + +// Question 10 +int GetFibonacciItem(int n); + +int NumWays(int n); + +// Question 11 +int GetMinInRotatedArray(vector& numbers); + +// Question 12 +bool ExistWordInMatrix(vector>& board, string word); + +bool HasPath(vector>& board, string word, int row, int col, int& pathLength, bool**& visited); + +// Question 13 +int MovingCount(int m, int n, int k); + +int MovingCountCore(int m, int n, int k, int row, int col, bool** visited); + +bool IsReached(int m, int n, int k, int row, int col, bool** visited); + +int GetDigitSum(int num); + +// Question 14 +int CuttingRope_DP(int n); + +int CuttingRope_GD(int n); + +long long FastPowerRemainder(int x, int a, int p); + +// Question 15 +int GetNumberOf1B(uint32_t n); + +// Question 16 +double MyPow(double x, int n); + +// Question 17 +vector PrintNumbers(int n); + +// Question 18 +ListNode* DeleteNode(ListNode* head, int val); + +void DeleteDuplication(ListNode** pHead); + +// Question 19 +bool MatchRegularExpression(string str, string pattern); + +// Question 20 +bool IsNumber(string s); + +string CutNumString(string& s); + +bool ScanInteger(string& s); + +bool ScanUnsignedInteger(string& s); +} diff --git a/src/include/util.h b/src/include/util.h new file mode 100644 index 0000000..f62e3f8 --- /dev/null +++ b/src/include/util.h @@ -0,0 +1,8 @@ +#pragma once + +#include "data_structure.h" + +using namespace ds; + +namespace util { +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..15f1a6a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,12 @@ +#include + +#include "solution.h" +#include "data_structure.h" + +using namespace solution; +using namespace ds; + +int main() { + + return 0; +}