Форум программистов, компьютерный форум, киберфорум
Алгоритмы
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
57 / 43 / 12
Регистрация: 27.10.2018
Сообщений: 454

Оптимизировать алгоритм

10.07.2019, 04:11. Показов 3001. Ответов 37
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Не углубляясь в детали , суть задачи - добавлять в конец вектора два элемента с значением первого и удалять первый элемент из вектора .
Я реализировал так :
C++
1
2
3
4
5
6
#include <string>
#include <vector>
std::string who_is_next(std::vector<std::string> &names, long long r) {
for (int i = r;; --i) {
if (i == 1)  { return names[0]; }
else{ names.vector::push_back(names[0]); names.vector::push_back(names[0]);names.erase(names.begin());}}}
Данный код проходит 10063 итераций цикла в тесте за 4875-6285 мс (почему разное время - незнаю )при таком инпуте :
C++
1
2
3
4
std::vector<std::string> names = {"Sheldon", "Leonard", "Penny", "Rajesh", "Howard"};  
        Assert::That(who_is_next(names, 1), Equals("Sheldon"));
        Assert::That(who_is_next(names, 52), Equals("Penny"));
        Assert::That(who_is_next(names, 10010), Equals("Howard"));
Ограничение на прохождение теста - 12000 мс.
Как уложиться в это время при таких значениях на входе не представляю :
C++
1
2
3
4
string[] names = new string[] { "Sheldon", "Leonard", "Penny", "Rajesh", "Howard" };
Line.WhoIsNext(names, 1) == "Sheldon"
Line.WhoIsNext(names, 52) == "Penny"
Line.WhoIsNext(names, 7230702951) == "Leonard"
Помогите пожалуста оптимизировать данное решение \подсказать иную реализацию,заранее спасибо.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
10.07.2019, 04:11
Ответы с готовыми решениями:

Оптимизировать алгоритм
Приятель подкинул задачку: Получить новую матрицу В, элемент b которой равен наименьшему из элементов a исходной матрицы, где k меняется...

Помогите оптимизировать алгоритм
Помогите, пожалуйста, оптимизировать алгоритм. Задача следующая. Есть 5 форм, например, с 10 текстбоксами в каждой форме. Необходимо...

Как оптимизировать этот алгоритм до O(n)?
У меня есть список m и число n. Нужно найти два элемента из этого списка, сумма которых будет ближе всего к n. Как это можно сделать за...

37
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
10.07.2019, 16:50
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от plzvtl Посмотреть сообщение
вместо начального.Но поскольку данный тест проходит , я считаю что так надо.
Он может проходить случайно, т.к. в очереди появляется множество одноименных персонажей.

Добавлено через 6 минут
Несколько вариантов. В каждом следующем чуть больше оптимизаций. Вроятно, можно оптимизировать еще.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <chrono>
#include <deque>
#include <functional>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
 
std::string who_is_next(std::vector<std::string> names, long long r) {
  for (int i = r;; --i) {
    if (i == 1) {
      return names[0];
    } else {
      names.vector::push_back(names[0]);
      names.vector::push_back(names[0]);
      names.erase(names.begin());
    }
  }
}
 
std::string who_is_next_deque(std::vector<std::string> names, long long n) {
  std::deque<std::string> names_deque(names.begin(), names.end());
  for (long long i = 1; i < n; ++i) {
    names_deque.push_back(names_deque.front());
    names_deque.push_back(names_deque.front());
    names_deque.pop_front();
  }
  return names_deque.front();
}
 
std::string who_is_next_deque_idxs(std::vector<std::string> names,
                                   long long n) {
  std::deque<int> names_deque(names.size());
  std::iota(names_deque.begin(), names_deque.end(), 0);
  for (long long i = 1; i < n; ++i) {
    names_deque.push_back(names_deque.front());
    names_deque.push_back(names_deque.front());
    names_deque.pop_front();
  }
  return names[names_deque.front()];
}
 
std::string who_is_next_deque_idxs_compressed(std::vector<std::string> names,
                                              long long n) {
  std::deque<std::pair<int, int>> names_deque(names.size());
  for (size_t i = 0; i < names_deque.size(); ++i) {
    names_deque[i].first = i;
    // В начале все в единственном экземпляре
    names_deque[i].second = 1;
  }
  for (long long i = 1; i < n; ++i) {
    auto& head = names_deque.front();
    auto& tail = names_deque.back();
    if (tail.first == head.first) {
      tail.second += 2;
    } else {
      names_deque.emplace_back(head.first, 2);
    }
    if (head.second > 1) {
      --head.second;
    } else {
      names_deque.pop_front();
    }
  }
  return names[names_deque.front().first];
}
 
using Names = std::vector<std::string>;
 
void run_test(std::function<std::string(Names&, long long)> func,
              Names& names,
              long long n,
              std::string expected) {
  const auto begin = std::chrono::steady_clock::now();
  const auto result = func(names, n);
  const auto end = std::chrono::steady_clock::now();
  const auto elapsed =
      std::chrono::duration_cast<std::chrono::microseconds>(end - begin);
  const std::string status = result == expected ? "Ok" : "Fail";
  std::cout << status << " - " << elapsed.count() << " us\n";
}
 
void run_tests(std::string title,
               std::function<std::string(Names&, long long)> func) {
  Names names = {"Sheldon", "Leonard", "Penny", "Rajesh", "Howard"};
 
  std::cout << title << "\n";
  run_test(func, names, 1, "Sheldon");
  run_test(func, names, 52, "Penny");
  run_test(func, names, 10010, "Howard");
  run_test(func, names, 101000, "Leonard");
  std::cout << "\n";
}
 
int main() {
  run_tests("Origin by plzvtl", who_is_next);
  run_tests("Simple with dequeue", who_is_next_deque);
  run_tests("Simple with dequeue idxs", who_is_next_deque_idxs);
  run_tests("Compressed with dequeue idxs", who_is_next_deque_idxs_compressed);
}
Результаты моего прогона, ymmv:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Origin by plzvtl
Ok - 1 us
Ok - 17 us
Ok - 303565 us
Ok - 27308711 us
 
Simple with dequeue
Ok - 2 us
Ok - 2 us
Ok - 339 us
Ok - 3296 us
 
Simple with dequeue idxs
Ok - 0 us
Ok - 0 us
Ok - 51 us
Ok - 322 us
 
Compressed with dequeue idxs
Ok - 0 us
Ok - 0 us
Ok - 51 us
Ok - 234 us
0
57 / 43 / 12
Регистрация: 27.10.2018
Сообщений: 454
10.07.2019, 17:23  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Для вектора предлагаю сделать так
Максимально не могу понять как это работает.
Почему
C++
1
 names.erase(names.begin(), names.begin() + i);
вне цикла , оно же удалит 1 раз всего.

И почему оно удаляет только элемент с индексом 0 , а не элементы с индексами 0 и 1 , как написано ?
Так же , при 1 , должен вернутся сразу элемент с индексом 0 , а у вас получается всегда удаление первого а потом возврат , тоесть возврат значение которое должно быть с и ндексом 1.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
10.07.2019, 17:49
Цитата Сообщение от plzvtl Посмотреть сообщение
вне цикла , оно же удалит 1 раз всего.
Здесь мы не удаляем элементы из головы вектора, а просто перемещаемся по нему, i - это индекс первого элемента.
Все элементы удаляем за раз после выхода из цикла.
Должно сэкономить массу ресурсов.

Добавлено через 33 секунды
Цитата Сообщение от plzvtl Посмотреть сообщение
И почему оно удаляет только элемент с индексом 0 , а не элементы с индексами 0 и 1 , как написано ?
оно удаляет все элементы с нулевого по i

Добавлено через 20 минут
У меня для 101000 отработал за 6 мс
0
698 / 140 / 57
Регистрация: 20.08.2017
Сообщений: 255
10.07.2019, 17:57
plzvtl, зачем вообще нужно что-то делать с вектором? Нужно просто вычислить формулу последовательности.
1
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
10.07.2019, 17:58
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
У меня для 101000 отработал за 6 мс
У меня замеры в микросекундах.
0
10.07.2019, 18:15

Не по теме:

Цитата Сообщение от plzvtl Посмотреть сообщение
Не углубляясь в детали , суть задачи - добавлять в конец вектора два элемента с значением первого и удалять первый элемент из вектора .
Но как часто бывает, оказалось, что суть задачи совсем другая. 🤣

0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
10.07.2019, 18:16
Цитата Сообщение от plzvtl Посмотреть сообщение
Вот как звучит условие
"Sheldon, Leonard, Penny, Rajesh and Howard are in the queue for a "Double Cola" drink vending machine; there are no other people in the queue. The first one in the queue (Sheldon) buys a can, drinks it and doubles! The resulting two Sheldons go to the end of the queue. Then the next in the queue (Leonard) buys a can, drinks it and gets to the end of the queue as two Leonards, and so on."
plzvtl, это часть условия. Нет главного - того что ожидается от описания данного процесса - алгоритма.
Но как бы там ни было я бы не стал удалять с головы при каждом шаге (распития безалкогольного напитка в общественном месте). Тут важно понимать, сколько шагов может быть, чтобы оценить хватит ли size_t (long long уберите) для того чтобы не удалять их вообще. И если удалять то сколько шагов на один акт удаления возможен.
То есть вы постоянно держите индекс головного элемента как начальный (начиная от начала и ++ при каждом шаге), а добавляете на самом деле (не понарошку )
А когда нужен результат - выводите от текущего и до конца. В крайнем разе, если нужен готовый контейнер - вконце удалите всё от начала и до текущего "головного".
Чтобы сказать более точно, нужно бы знать, что является результатом (что требуется в задаче).
0
1719 / 568 / 187
Регистрация: 12.03.2016
Сообщений: 2,169
10.07.2019, 18:23
Цитата Сообщение от IGPIGP Посмотреть сообщение
Чтобы сказать более точно, нужно бы знать, что является результатом (что требуется в задаче).
Да вроде сказано, когда выпытали. Пост 17.
Не надо тут никаких векторов, пушей и т.д. Нужен нормальный алгоритм вычисления и больше ничего.
2
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
10.07.2019, 18:34
Я прочел до 9 поста и решил что это по мысли ТС - условие. Шире нужно думать.
Manowar, то есть вектор нужн для задания последовательности
Цитата Сообщение от IGPIGP Посмотреть сообщение
Sheldon, Leonard, Penny, Rajesh and Howard
??
Там пьют колу с полным содержанием коки если дают вектор (имхо). То есть, результат должен быть числом от 0 до 5 (индексом жаждущего и страждущего в изначальной очереди из 5-ти). При чём тут контейнера вообще?
0
698 / 140 / 57
Регистрация: 20.08.2017
Сообщений: 255
10.07.2019, 19:23
Немного подумав можно дойти до вот такой вот таблички:

C
1
2
3
4
5
Sheldon |1| 6  7|16 17 18 19|36 37 38 39 40 41 42 43
Leonard |2| 8  9|20 21 22 23|44 45 46 47 48 49 50 51
Penny   |3|10 11|24 25 26 27|.......................
Rajesh  |4|12 13|28 29 30 31|.......................
Howard  |5|14 15|32 33 34 35|.......................
Т. е. нам нужно просто проверить, в какую из последовательностей (по строкам) попадает заданное число. Вот схематичная проверка "в лоб" на C:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
bool check_index(size_t index, long long r)
{
    const size_t sequence_start = index;
    size_t temp = sequence_start;
    size_t step = 1;
    size_t delta = index + 4;
 
    while (temp <= r) {
        if (temp == r)
            return true;
 
        size_t sequence_member = temp;
 
        for (size_t i = 1; i <= step; i++) {
            if (r == sequence_member)
                return true;
 
            sequence_member++;
        }
 
        temp += delta;
        step *= 2;
        delta *= 2;
    }
 
    return false;
}
Можно прикрутить к оригинальному коду ТС:

C
1
2
3
4
5
6
std::string who_is_next(std::vector<std::string> &names, long long r)
{
    for (size_t i = 1; i <= 5; i++)
        if (check_index(i, r))
            return names[i - 1];
}
Нужно еще оптимизировать, конечно. Скорее всего, можно вообще без циклов обойтись, но тут уже думать нужно.
1
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
10.07.2019, 20:11
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int log2(int x)
{
    int ret = 0;
    while (x >>= 1) ret++;
    
    return ret;
}
 
int index(int n)
{
    int l2 = log2(n / 5 + 1);
    int w = 1 << l2;
    int b = 5 * (w - 1);
    return (n - b) / w;
}
 
#include <iostream>
using namespace std;
 
int main()
{
    const char* names[] = { "Sheldon", "Leonard", "Penny", "Rajesh", "Howard" };
    for (int n = 0; n < 100; n++)
        cout << names[index(n)] << endl;
}
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
10.07.2019, 20:31
Цитата Сообщение от 0x10 Посмотреть сообщение
У меня замеры в микросекундах.
Ну, у меня все твои функции отработали медленнее, чем моя (особенно, если убрать у меня names.erase). Кроме who_is_next_deque_idxs_compressed, тут да. Это собственно и есть формула, я б не смог догадаться.
Но и её можно ускорить, по той же схеме

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
std::string who_is_next_deque_idxs_compressed(std::vector<std::string> names, long long n) 
{
    std::vector<std::pair<size_t, int>> names_deque;
    names_deque.reserve(names.size() + n);
    for (size_t i = 0; i < names.size(); ++i)
        names_deque.emplace_back(i, 1);
 
    size_t idx = 0;
    for (long long i = 1; i < n; ++i) 
    {
        auto& head = names_deque[idx];
        auto& tail = names_deque.back();
        if (tail.first == head.first) 
            tail.second += 2;
        else 
            names_deque.emplace_back(head.first, 2);
 
        if (head.second > 1) 
            --head.second;
        else 
            ++idx;
    }
    return names[names_deque[idx].first];
}
0
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
10.07.2019, 20:33
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Это собственно и есть формула
Выше уже предложили нормальные способы вычисления.
0
698 / 140 / 57
Регистрация: 20.08.2017
Сообщений: 255
10.07.2019, 20:49
Если кто не понял, как работает решение, найденное, rat0r:

C
1
2
3
4
5
Sheldon |1| 6  7|16 17 18 19|36 37 38 39 40 41 42 43|...
Leonard |2| 8  9|20 21 22 23|44 45 46 47 48 49 50 51|...
Penny   |3|10 11|24 25 26 27|52 53 54 55 56 57 58 59|...
Rajesh  |4|12 13|28 29 30 31|60 61 62 63 64 65 66 67|...
Howard  |5|14 15|32 33 34 35|68 69 70 71 72 73 74 75|...
C
1
2
3
4
5
6
7
8
int index(int n)
{
    int l2 = log2(n / 5 + 1); /* Находим номер "прямоугольника", в котором находится число (см. таблицу выше). */
    int w = 1 << l2;          /* Получаем ширину этого прямоугольника. */
    int b = 5 * (w - 1);      /* Получаем последнее (по счету) число в предыдущем прямоугольнике. */
    return (n - b)            /* Получаем позицию числа N в прямоугольнике. */
           / w;               /* Получаем строку, в которой находится число. */
}
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
10.07.2019, 20:59
Eanmos, я считаю с нуля, так что int b = 5 * (w - 1); /* Получаем число, с которого начинается прямоугольник, которому принадлежит n */
0
57 / 43 / 12
Регистрация: 27.10.2018
Сообщений: 454
11.07.2019, 03:25  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
plzvtl, это часть условия. Нет главного - того что ожидается от описания данного процесса - алгоритма.
Я полностю предоставил условие. И текст и вид инпута и аутпута.
Да , я не додумался применить какую-либо формулу вычисления номера , а решил работать прямо таки с вектором.
Цитата Сообщение от IGPIGP Посмотреть сообщение
Чтобы сказать более точно, нужно бы знать, что является результатом (что требуется в задаче).
Это есть в моем 1 сообщении (посте , незнаю почему это так называют).
Кроме того меня спросили и я написал пояснение :я предоставил вид фиксированного теста в котором результат работы функции сравнивают со строкой которая является именем , которую мы собственно ищем.
Цитата Сообщение от plzvtl Посмотреть сообщение
Эти 2 вызова - это фиксированные тесты , их условия видны тем кто проходит , условий , других тестов не видно , но я сомневаюсь что там не вектор.
Цитата Сообщение от Manowar Посмотреть сообщение
17
1 и 9
Цитата Сообщение от Manowar Посмотреть сообщение
Не надо тут никаких векторов
Вектор всегда на входе .Для вычислений решения не нужен как оказалось ,но инпут нужно обработать.
Цитата Сообщение от Manowar Посмотреть сообщение
пушей
Да ,опять же оказалось не надо.

Добавлено через 6 минут
Цитата Сообщение от plzvtl Посмотреть сообщение
сравнивают со строкой которая является именем
Для получения , тру\фолс. И собстевенно собщить корректен ли результат у того кто тест проходит.

Добавлено через 2 часа 31 минуту
Хотя , вдруг ко мне пришла мысль : почему все дружно решили что инпут всегда вектор на 5 элементов?
Я написал что это инпут фиксед теста , а в моем понимании при инпуте с вектором другого кол-ва элементов формула вычислений уже будет другая.
0
698 / 140 / 57
Регистрация: 20.08.2017
Сообщений: 255
11.07.2019, 05:07
Цитата Сообщение от plzvtl Посмотреть сообщение
формула вычислений уже будет другая.
Нет. Ответ rat0r после тривиальных изменений подойдет под любую размерность исходного вектора.
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
11.07.2019, 08:58
Цитата Сообщение от plzvtl Посмотреть сообщение
Я полностю предоставил условие. И текст и вид инпута и аутпута.
С третьей попытки.
Цитата Сообщение от plzvtl Посмотреть сообщение
Цитата Сообщение от IGPIGP
Чтобы сказать более точно, нужно бы знать, что является результатом (что требуется в задаче).
Это есть в моем 1 сообщении (посте , незнаю почему это так называют).
Дело даже не в том, что в вашем 1 посте нет полного описания условия, и даже не в том, что вы (следовательно) не понимаете, что его там нет, раз утверждаете, что оно там есть. Хуже то, что похоже, что вы не понимаете что такое условие.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
11.07.2019, 08:58

Преобразование строки в байты: оптимизировать алгоритм
Часть программы .... которая строку(довольно большую) содержащую 0 и 1 преобразует в байты( читает по 8 символов получаем байт удаляем...

Оптимизировать алгоритм проверки ударения слов
Здравствуйте, уважаемые участники форума. На образовательном сайте решал задание, система решение приняла. Так как я неопытный в...

оптимизировать алгоритм поиска вхождений строки в текстовый файл (1 Мб)
Здравствуйте. По заданию требовалось составить программу для подсчета вхождений разных сочетаний букв с алфавита от 1 буквы до 4 в...

Исправить алгоритм расчета ЕИ и максимально оптимизировать с целью повышения быстродействия
Всем доброго времени суток. Помогите выполнить тестовое задание. Условия: Запрос от Министерства энергетики Нской области: ...

Оптимизировать алгоритм, чтобы уменьшить количество операций для проверок деления
Всего один вопрос. Как оптимизировать алгоритм, чтобы уменьшить количество операций для проверок деления? #include &lt;iostream&gt; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
38
Ответ Создать тему
Новые блоги и статьи
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru