Skip to content
98 changes: 98 additions & 0 deletions C3100_tregubov_vadim_lab4.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include <iostream>
#include <vector>
#include <cmath>
#include <limits>
#include <algorithm>

using namespace std;

// функция для подсчета суммы отклонений в кластере
double calculateClusterCost(const vector<int>& arr, int start, int end) {
double mean = 0;
for (int i = start; i <= end; ++i) {
mean += arr[i];
}
mean /= (end - start + 1); // среднее значение кластера

double cost = 0;
for (int i = start; i <= end; ++i) {
cost += abs(arr[i] - mean); // сумма модулей отклонений
}
return cost;
}

// рекурсивная функция для поиска оптимального разбиения
void findOptimalClustering(const vector<int>& arr, int k, int start, vector<int>& currentCluster, vector<vector<int>>& bestClusters, double& minCost) {
if (k == 1) {
// базовый случай: один кластер от start до конца массива
double cost = calculateClusterCost(arr, start, arr.size() - 1);
if (cost < minCost) {
minCost = cost;
bestClusters.clear();
bestClusters.push_back(vector<int>(arr.begin() + start, arr.end()));
}
return;
}

// перебираем все возможные позиции разделения кластера
for (int i = start; i < arr.size() - (k - 1); ++i) {
// добавляем текущий кластер
for (int j = start; j <= i; ++j) {
currentCluster.push_back(arr[j]);
}

// рекурсивно ищем разбиение для оставшихся кластеров
vector<int> nextCluster;
findOptimalClustering(arr, k - 1, i + 1, nextCluster, bestClusters, minCost);

// удаляем текущий кластер
currentCluster.clear();
}
}

// основная функция кластеризации
vector<vector<int>> clusterArray(const vector<int>& arr, int k) {
vector<vector<int>> bestClusters;
double minCost = numeric_limits<double>::max();
vector<int> currentCluster;

findOptimalClustering(arr, k, 0, currentCluster, bestClusters, minCost);

return bestClusters;
}

int main() {
vector<int> arr = {1, -2, 3, 4, -5, 6};
int k = 3;

vector<vector<int>> clusters = clusterArray(arr, k);

cout << "Кластеры:" << endl;
for (size_t i = 0; i < clusters.size(); ++i) {
cout << "Кластер " << i + 1 << ": ";
for (int num : clusters[i]) {
cout << num << " ";
}
cout << endl;
}

/*
Время:
calculateClusterCost: O(n) для вычисления среднего и суммы отклонений.
findOptimalClustering: O(n * k) из-за перебора всех возможных разбиений.
Итого: O(n^2 * k) в худшем случае из-за рекурсивного перебора.

Память:
Используется O(n) для хранения текущего кластера и O(n) для хранения лучших кластеров.
Итого: O(n).

Итоговая асимптотика:
- calculateClusterCost: O(n) на каждое вычисление
- заполнение dp: O(k * n^2), так как перебираем все разбиения
- восстановление разбиения: O(k), так как идем по split
Итого: O(k * n^2), что гораздо быстрее рекурсивного O(n^k)
*/

return 0;
}

34 changes: 34 additions & 0 deletions c3100_tregubov_vadim_lab3
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
using namespace std;

void fisherYatesShuffle(vector<int>& arr) {
random_device rd; // O(1)
mt19937 gen(rd()); // O(1)

for (int i = arr.size() - 1; i > 0; i--) { // O(N)
uniform_int_distribution<> dis(0, i); // O(1)
int j = dis(gen); // O(1)
swap(arr[i], arr[j]); // O(1)
}
}

int main() {
int n = 10; // O(1)
vector<int> arr(n); // O(N)

for (int i = 0; i < n; i++) { // O(N)
arr[i] = i + 1; // O(1)
}

fisherYatesShuffle(arr); // O(N)

for (int num : arr) { // O(N)
cout << num << " "; // O(1)
}
cout << endl; // O(1)

return 0;
}
30 changes: 30 additions & 0 deletions lab0.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <iostream>

int secondLargest(int arr[], int size) {
int first = -1;
int second = -1;

for (int i = 0; i < size; i++) {
if (arr[i] > first) {
second = first;
first = arr[i];
}
else if (arr[i] > second and arr[i] != first) {
second = arr[i];
}
}

return second;
}

int main() {
int array[] = {1, 5, 2, 54, 23, 56, 7};
int size = sizeof(array) / sizeof(array[0]);

int answer = secondLargest(array, size);

std::cout << answer;

return 0;

}
167 changes: 167 additions & 0 deletions lab5.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <cmath>
#include <chrono>

using namespace std;

// Сортировка методом Bucket Sort
void bucketSort(vector<double>& arr) {
int n = arr.size();
vector<vector<double>> buckets(n);

for (double num : arr) {
int bucketIndex = static_cast<int>(num * n);
buckets[bucketIndex].push_back(num);
}

for (auto& bucket : buckets) {
sort(bucket.begin(), bucket.end());
}

int index = 0;
for (const auto& bucket : buckets) {
for (double num : bucket) {
arr[index++] = num;
}
}
}

// Память и сложность Bucket Sort:
/*
Память:
1. Вектора для корзин: O(n).
2. Исходный массив: O(n).
Итого: O(n).

Время:
1. Распределение по корзинам: O(n).
2. Сортировка каждой корзины: O(n log(n/k)), где k - средний размер корзины.
Итого: O(n + n log(n/k)) ≈ O(n log n) в худшем случае.
*/

// Сортировка методом Heap Sort
void heapify(vector<int>& arr, int n, int i) {
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;

if (left < n && arr[left] > arr[largest])
largest = left;

if (right < n && arr[right] > arr[largest])
largest = right;

if (largest != i) {
swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}

void heapSort(vector<int>& arr) {
int n = arr.size();

for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);

for (int i = n - 1; i >= 0; i--) {
swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}

// Память и сложность Heap Sort:
/*
Память:
1. Исходный массив: O(n).
2. Дополнительный стек для рекурсии в heapify: O(log n).
Итого: O(n).

Время:
1. Построение кучи: O(n).
2. Извлечение элементов: O(n log n).
Итого: O(n log n).
*/

// Сортировка методом Shaker Sort
void shakerSort(vector<int>& arr) {
bool swapped = true;
int start = 0;
int end = arr.size() - 1;

while (swapped) {
swapped = false;

for (int i = start; i < end; ++i) {
if (arr[i] > arr[i + 1]) {
swap(arr[i], arr[i + 1]);
swapped = true;
}
}

if (!swapped)
break;

swapped = false;
--end;

for (int i = end - 1; i >= start; --i) {
if (arr[i] > arr[i + 1]) {
swap(arr[i], arr[i + 1]);
swapped = true;
}
}
++start;
}
}

// Память и сложность Shaker Sort:
/*
Память:
1. Исходный массив: O(n).
2. Дополнительные переменные: O(1).
Итого: O(n).

Время:
1. Худший случай: O(n^2) (если массив сильно неупорядочен).
2. Лучший случай: O(n) (если массив уже отсортирован).
*/

int main() {
// Пример для Bucket Sort
vector<double> bucketArr = {0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21, 0.12, 0.23, 0.68};
auto startBucket = chrono::high_resolution_clock::now();
bucketSort(bucketArr);
auto endBucket = chrono::high_resolution_clock::now();
for (double num : bucketArr) {
cout << num << " ";
}
cout << "\nВремя выполнения Bucket Sort: "
<< chrono::duration_cast<chrono::microseconds>(endBucket - startBucket).count() << " микросекунд\n";

// Пример для Heap Sort
vector<int> heapArr = {4, 10, 3, 5, 1};
auto startHeap = chrono::high_resolution_clock::now();
heapSort(heapArr);
auto endHeap = chrono::high_resolution_clock::now();
for (int num : heapArr) {
cout << num << " ";
}
cout << "\nВремя выполнения Heap Sort: "
<< chrono::duration_cast<chrono::microseconds>(endHeap - startHeap).count() << " микросекунд\n";

// Пример для Shaker Sort
vector<int> shakerArr = {5, 3, 8, 6, 2, 7, 4, 1};
auto startShaker = chrono::high_resolution_clock::now();
shakerSort(shakerArr);
auto endShaker = chrono::high_resolution_clock::now();
for (int num : shakerArr) {
cout << num << " ";
}
cout << "\nВремя выполнения Shaker Sort: "
<< chrono::duration_cast<chrono::microseconds>(endShaker - startShaker).count() << " микросекунд\n";

return 0;
}
30 changes: 30 additions & 0 deletions lab6.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class Solution {
public:
int uniquePaths(int m, int n) {
// подсчет памяти:
// - используем одномерный вектор dp размером n.
// - память: O(n), так как храним только одну строку таблицы DP.

// асимптотика:
// - временная сложность: O(m * n), так как заполняем таблицу DP.
// - пространственная сложность: O(n), так как используем одномерный массив.

// инициализация вектора dp:
// - dp[j] хранит количество путей до клетки (текущая строка, j).
// - изначально все элементы равны 1, так как в первой строке только один путь (вправо).
vector<int> dp(n, 1);

// заполнение таблицы DP:
// - для каждой строки (начиная со второй) обновляем значения dp[j].
// - dp[j] = dp[j] (количество путей сверху) + dp[j - 1] (количество путей слева).
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
dp[j] += dp[j - 1];
}
}

// возвращаем количество путей до конечной клетки (m-1, n-1):
// - dp[n - 1] содержит результат для последней клетки.
return dp[n - 1];
}
};
35 changes: 35 additions & 0 deletions lab6no2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class Solution {
public:
int minDistance(string word1, string word2) {
const int m = word1.length(); // длина первой строки
const int n = word2.length(); // длина второй строки

// создаем двумерный вектор dp размером (m + 1) * (n + 1)
// он займет O(m * n) памяти
vector<vector<int>> dp(m + 1, vector<int>(n + 1));

for (int i = 1; i <= m; ++i)
dp[i][0] = i; // для преобразования word1[0..i) в пустую строку нужно i операций удаления

for (int j = 1; j <= n; ++j)
dp[0][j] = j; // для преобразования пустой строки в word2[0..j) нужно j операций вставки

// Заполнение таблицы dp
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (word1[i - 1] == word2[j - 1]) {
// если буквы совпадают, берем значение из диагонали
dp[i][j] = dp[i - 1][j - 1]; // Ничего не нужно делать
} else {
// если буквы разные, берем минимум из трех операций
dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;
}
}
}

// возвращаем минимальное количество операций для преобразования word1 в word2
return dp[m][n];
}
};

// асимптотика и память O(m * n)
Loading