Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
zhaojianfan committed Apr 8, 2023
0 parents commit 2f68211
Show file tree
Hide file tree
Showing 27 changed files with 957 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Project exclude paths
/cmake-build-debug/
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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})
50 changes: 50 additions & 0 deletions src/chapter-2/10_get_fibonacci_item.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
48 changes: 48 additions & 0 deletions src/chapter-2/11_get_min_in_rotated_array.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "solution.h"

/*
* 11. 旋转数组的最小数字
* 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
* 给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。
* 请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。
*/

int solution::GetMinInRotatedArray(vector<int>& 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];
}
62 changes: 62 additions & 0 deletions src/chapter-2/12_exist_word_in_matrix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "solution.h"

/*
* 12. 矩阵中的路径
* 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true;否则,返回 false。
* 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。
* 同一个单元格内的字母不允许被重复使用。
*/

bool solution::ExistWordInMatrix(vector<vector<char>>& 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<vector<char>>& 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;
}
60 changes: 60 additions & 0 deletions src/chapter-2/13_robot_moving_count.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
73 changes: 73 additions & 0 deletions src/chapter-2/14_cutting_rope.cpp
Original file line number Diff line number Diff line change
@@ -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<int> 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<int>(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;
}
17 changes: 17 additions & 0 deletions src/chapter-2/15_get_number_of_1B.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
35 changes: 35 additions & 0 deletions src/chapter-2/3_find_repeat_number.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "solution.h"

/*
* 03. 数组中重复的数字
* 在一个长度为n的数组 nums 里的所有数字都在0~n-1的范围内。
* 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
*/

int solution::FindRepeatNumber(vector<int>& 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;
}
Loading

0 comments on commit 2f68211

Please sign in to comment.