Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;

}
51 changes: 51 additions & 0 deletions lab4extra.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <iostream>
#include <vector>
#include <set>

using namespace std;

int main() {
vector<set<int>> sets = {{1, 2}, {2, 3}, {3, 4}}; // заданные множества
set<int> universe = {1, 2, 3}; // множество которое нужно покрыть

int n = sets.size(); // количество подмножеств
vector<int> best_cover; // оптимальное покрытие

// перебираем все возможные комбинации подмножеств — их 2^n, сложность O(2^n)
for (int mask = 0; mask < (1 << n); ++mask) {
set<int> covered; // множество покрытых элементов
vector<int> selected; // индексы выбранных подмножеств

// проверяем, какие множества включены в текущую комбинацию — O(n)
for (int i = 0; i < n; ++i) {
if (mask & (1 << i)) { // Если i-е множество включено в комбинацию
selected.push_back(i);
covered.insert(sets[i].begin(), sets[i].end()); // добавляем элементы множества в покрытие — O(k), где k — размер множества
}
}

// проверяем, покрыли ли мы все элементы universe — O(u), где u — размер universe
if (includes(covered.begin(), covered.end(), universe.begin(), universe.end())) {
// если покрытие полное и оно меньше текущего оптимального по размеру — обновляем
if (best_cover.empty() || selected.size() < best_cover.size()) {
best_cover = selected;
}
}
}

// выводим минимальное покрывающее подмножество
cout << "[";
for (int i = 0; i < best_cover.size(); ++i) {
int idx = best_cover[i];
cout << "{";
for (auto it = sets[idx].begin(); it != sets[idx].end(); ++it) {
if (it != sets[idx].begin()) cout << ", ";
cout << *it;
}
cout << "}";
if (i < best_cover.size() - 1) cout << ", ";
}
cout << "]" << endl;

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;
}
Loading