Add ru version (#1865)

* Add Russian docs site baseline

* Add Russian localized codebase

* Polish Russian code wording

* Update ru code translation.

* Update code translation and chapter covers.

* Fix pythontutor extraction.

* Add README and landing page.

* placeholder of profiles

* Use figures of English version

* Remove chapter paperbook
This commit is contained in:
Yudong Jin
2026-03-28 04:24:07 +08:00
committed by GitHub
parent 2ca570cc33
commit 772183705e
1958 changed files with 108186 additions and 0 deletions
@@ -0,0 +1,4 @@
add_executable(binary_search binary_search.c)
add_executable(two_sum two_sum.c)
add_executable(binary_search_edge binary_search_edge.c)
add_executable(binary_search_insertion binary_search_insertion.c)
@@ -0,0 +1,59 @@
/**
* File: binary_search.c
* Created Time: 2023-03-18
* Author: Guanngxu (446678850@qq.com)
*/
#include "../utils/common.h"
/* Бинарный поиск (двусторонне замкнутый интервал) */
int binarySearch(int *nums, int len, int target) {
// Инициализировать двусторонне замкнутый интервал [0, n-1], то есть i и j указывают на первый и последний элементы массива соответственно
int i = 0, j = len - 1;
// Цикл завершается, когда диапазон поиска пуст (при i > j диапазон пуст)
while (i <= j) {
int m = i + (j - i) / 2; // Вычислить индекс середины m
if (nums[m] < target) // Это означает, что target находится в интервале [m+1, j]
i = m + 1;
else if (nums[m] > target) // Это означает, что target находится в интервале [i, m-1]
j = m - 1;
else // Целевой элемент найден, вернуть его индекс
return m;
}
// Целевой элемент не найден, вернуть -1
return -1;
}
/* Бинарный поиск (лево замкнутый, право открытый интервал) */
int binarySearchLCRO(int *nums, int len, int target) {
// Инициализировать лево замкнутый, право открытый интервал [0, n), то есть i и j указывают на первый элемент массива и позицию сразу за последним элементом соответственно
int i = 0, j = len;
// Цикл завершается, когда диапазон поиска пуст (при i = j диапазон пуст)
while (i < j) {
int m = i + (j - i) / 2; // Вычислить индекс середины m
if (nums[m] < target) // Это означает, что target находится в интервале [m+1, j)
i = m + 1;
else if (nums[m] > target) // Это означает, что target находится в интервале [i, m)
j = m;
else // Целевой элемент найден, вернуть его индекс
return m;
}
// Целевой элемент не найден, вернуть -1
return -1;
}
/* Driver Code */
int main() {
int target = 6;
int nums[10] = {1, 3, 6, 8, 12, 15, 23, 26, 31, 35};
/* Бинарный поиск (двусторонне замкнутый интервал) */
int index = binarySearch(nums, 10, target);
printf("Индекс целевого элемента 6 = %d\n", index);
/* Бинарный поиск (лево замкнутый, право открытый интервал) */
index = binarySearchLCRO(nums, 10, target);
printf("Индекс целевого элемента 6 = %d\n", index);
return 0;
}
@@ -0,0 +1,67 @@
/**
* File: binary_search_edge.c
* Created Time: 2023-09-09
* Author: Gonglja (glj0@outlook.com)
*/
#include "../utils/common.h"
/* Бинарный поиск точки вставки (с повторяющимися элементами) */
int binarySearchInsertion(int *nums, int numSize, int target) {
int i = 0, j = numSize - 1; // Инициализировать двусторонне замкнутый интервал [0, n-1]
while (i <= j) {
int m = i + (j - i) / 2; // Вычислить индекс середины m
if (nums[m] < target) {
i = m + 1; // target находится в интервале [m+1, j]
} else {
j = m - 1; // Первый элемент меньше target находится в интервале [i, m-1]
}
}
// Вернуть точку вставки i
return i;
}
/* Бинарный поиск самого левого target */
int binarySearchLeftEdge(int *nums, int numSize, int target) {
// Эквивалентно поиску точки вставки target
int i = binarySearchInsertion(nums, numSize, target);
// target не найден, вернуть -1
if (i == numSize || nums[i] != target) {
return -1;
}
// Найти target и вернуть индекс i
return i;
}
/* Бинарный поиск самого правого target */
int binarySearchRightEdge(int *nums, int numSize, int target) {
// Преобразовать задачу в поиск самого левого target + 1
int i = binarySearchInsertion(nums, numSize, target + 1);
// j указывает на самый правый target, а i — на первый элемент больше target
int j = i - 1;
// target не найден, вернуть -1
if (j == -1 || nums[j] != target) {
return -1;
}
// Найти target и вернуть индекс j
return j;
}
/* Driver Code */
int main() {
// Массив с повторяющимися элементами
int nums[] = {1, 3, 6, 6, 6, 6, 6, 10, 12, 15};
printf("\nМассив nums = ");
printArray(nums, sizeof(nums) / sizeof(nums[0]));
// Бинарный поиск левой и правой границы
int targets[] = {6, 7};
for (int i = 0; i < sizeof(targets) / sizeof(targets[0]); i++) {
int index = binarySearchLeftEdge(nums, sizeof(nums) / sizeof(nums[0]), targets[i]);
printf("Индекс самого левого элемента %d = %d\n", targets[i], index);
index = binarySearchRightEdge(nums, sizeof(nums) / sizeof(nums[0]), targets[i]);
printf("Индекс самого правого элемента %d = %d\n", targets[i], index);
}
return 0;
}
@@ -0,0 +1,68 @@
/**
* File: binary_search_insertion.c
* Created Time: 2023-09-09
* Author: Gonglja (glj0@outlook.com)
*/
#include "../utils/common.h"
/* Бинарный поиск точки вставки (без повторяющихся элементов) */
int binarySearchInsertionSimple(int *nums, int numSize, int target) {
int i = 0, j = numSize - 1; // Инициализировать двусторонне замкнутый интервал [0, n-1]
while (i <= j) {
int m = i + (j - i) / 2; // Вычислить индекс середины m
if (nums[m] < target) {
i = m + 1; // target находится в интервале [m+1, j]
} else if (nums[m] > target) {
j = m - 1; // target находится в интервале [i, m-1]
} else {
return m; // Найти target и вернуть точку вставки m
}
}
// target не найден, вернуть точку вставки i
return i;
}
/* Бинарный поиск точки вставки (с повторяющимися элементами) */
int binarySearchInsertion(int *nums, int numSize, int target) {
int i = 0, j = numSize - 1; // Инициализировать двусторонне замкнутый интервал [0, n-1]
while (i <= j) {
int m = i + (j - i) / 2; // Вычислить индекс середины m
if (nums[m] < target) {
i = m + 1; // target находится в интервале [m+1, j]
} else if (nums[m] > target) {
j = m - 1; // target находится в интервале [i, m-1]
} else {
j = m - 1; // Первый элемент меньше target находится в интервале [i, m-1]
}
}
// Вернуть точку вставки i
return i;
}
/* Driver Code */
int main() {
// Массив без повторяющихся элементов
int nums1[] = {1, 3, 6, 8, 12, 15, 23, 26, 31, 35};
printf("\nМассив nums = ");
printArray(nums1, sizeof(nums1) / sizeof(nums1[0]));
// Бинарный поиск точки вставки
int targets1[] = {6, 9};
for (int i = 0; i < sizeof(targets1) / sizeof(targets1[0]); i++) {
int index = binarySearchInsertionSimple(nums1, sizeof(nums1) / sizeof(nums1[0]), targets1[i]);
printf("Индекс позиции вставки для элемента %d = %d\n", targets1[i], index);
}
// Массив с повторяющимися элементами
int nums2[] = {1, 3, 6, 6, 6, 6, 6, 10, 12, 15};
printf("\nМассив nums = ");
printArray(nums2, sizeof(nums2) / sizeof(nums2[0]));
// Бинарный поиск точки вставки
int targets2[] = {2, 6, 20};
for (int i = 0; i < sizeof(targets2) / sizeof(int); i++) {
int index = binarySearchInsertion(nums2, sizeof(nums2) / sizeof(nums2[0]), targets2[i]);
printf("Индекс позиции вставки для элемента %d = %d\n", targets2[i], index);
}
return 0;
}
+86
View File
@@ -0,0 +1,86 @@
/**
* File: two_sum.c
* Created Time: 2023-01-19
* Author: Reanon (793584285@qq.com)
*/
#include "../utils/common.h"
/* Метод 1: полный перебор */
int *twoSumBruteForce(int *nums, int numsSize, int target, int *returnSize) {
for (int i = 0; i < numsSize; ++i) {
for (int j = i + 1; j < numsSize; ++j) {
if (nums[i] + nums[j] == target) {
int *res = malloc(sizeof(int) * 2);
res[0] = i, res[1] = j;
*returnSize = 2;
return res;
}
}
}
*returnSize = 0;
return NULL;
}
/* Хеш-таблица */
typedef struct {
int key;
int val;
UT_hash_handle hh; // Реализовано на основе uthash.h
} HashTable;
/* Поиск в хеш-таблице */
HashTable *find(HashTable *h, int key) {
HashTable *tmp;
HASH_FIND_INT(h, &key, tmp);
return tmp;
}
/* Вставка элемента в хеш-таблицу */
void insert(HashTable **h, int key, int val) {
HashTable *t = find(*h, key);
if (t == NULL) {
HashTable *tmp = malloc(sizeof(HashTable));
tmp->key = key, tmp->val = val;
HASH_ADD_INT(*h, key, tmp);
} else {
t->val = val;
}
}
/* Метод 2: вспомогательная хеш-таблица */
int *twoSumHashTable(int *nums, int numsSize, int target, int *returnSize) {
HashTable *hashtable = NULL;
for (int i = 0; i < numsSize; i++) {
HashTable *t = find(hashtable, target - nums[i]);
if (t != NULL) {
int *res = malloc(sizeof(int) * 2);
res[0] = t->val, res[1] = i;
*returnSize = 2;
return res;
}
insert(&hashtable, nums[i], i);
}
*returnSize = 0;
return NULL;
}
/* Driver Code */
int main() {
// ======= Test Case =======
int nums[] = {2, 7, 11, 15};
int target = 13;
// ====== Driver Code ======
int returnSize;
int *res = twoSumBruteForce(nums, sizeof(nums) / sizeof(int), target, &returnSize);
// Метод 1
printf("Способ 1: res = ");
printArray(res, returnSize);
// Метод 2
res = twoSumHashTable(nums, sizeof(nums) / sizeof(int), target, &returnSize);
printf("Способ 2: res = ");
printArray(res, returnSize);
return 0;
}