Skip to content
Open
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;

}
97 changes: 97 additions & 0 deletions lab4.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include <iostream>
#include <vector>
#include <cmath>
#include <limits>

using namespace std;

// Функция для подсчёта суммы отклонений в кластере
vector<vector<double>> costMatrix;

void computeCostMatrix(const vector<int>& arr) {
int n = arr.size();
costMatrix.assign(n, vector<double>(n, 0));

for (int i = 0; i < n; ++i) {
double sum = 0, mean = 0;
for (int j = i; j < n; ++j) {
sum += arr[j];
mean = sum / (j - i + 1);
double cost = 0;
for (int k = i; k <= j; ++k) {
cost += abs(arr[k] - mean);
}
costMatrix[i][j] = cost;
}
}
}

// Функция для разбиения массива на k кластеров
vector<vector<int>> clusterArray(const vector<int>& arr, int k) {
int n = arr.size();
computeCostMatrix(arr);

vector<vector<double>> dp(k, vector<double>(n, numeric_limits<double>::max()));
vector<vector<int>> split(k, vector<int>(n, -1));

for (int j = 0; j < n; ++j) {
dp[0][j] = costMatrix[0][j];
}

for (int clusters = 1; clusters < k; ++clusters) {
for (int j = clusters; j < n; ++j) {
for (int i = clusters - 1; i < j; ++i) {
double cost = dp[clusters - 1][i] + costMatrix[i + 1][j];
if (cost < dp[clusters][j]) {
dp[clusters][j] = cost;
split[clusters][j] = i;
}
}
}
}

vector<vector<int>> clusters(k);
int end = n - 1;
for (int i = k - 1; i >= 0; --i) {
int start = (i > 0) ? split[i][end] + 1 : 0;
clusters[i].assign(arr.begin() + start, arr.begin() + end + 1);
end = start - 1;
}

return clusters;
}

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