Форум программистов, компьютерный форум, киберфорум
Web-мастеринг
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
Супер-модератор
Эксперт JSЭксперт HTML/CSSЭксперт PHP
 Аватар для gogolik
3983 / 2154 / 833
Регистрация: 13.03.2010
Сообщений: 7,057

Задача на подумать: подсчёт заданной суммы из элементов массива

10.11.2023, 17:49. Показов 2640. Ответов 39
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем добрый вечер.
В спорах с товарищем пришли к такой задаче:

Задан массив int и float чисел, одинаковые числа могут повторяться сколько угодно раз.
Есть сумма, которую нужно получить из чисел этого массива. Заранее известно, что сумму можно получить как минимум одной комбинацией чисел неизвестной длины. Нужно вывести комбинацию индексов чисел, из которых можно получить данную сумму.

Например:
Есть массив [100, 3, 20, 60, 50] и нужно получить число 123 из его элементов. Значит, правильным ответом будет любая комбинация из ключей [0, 1, 2]. Если же нужно получить число 133, то ответ будет, например, [3, 2, 1, 4].

Какое на ваш взгляд здесь самое оптимальное решение? Интересуют больше логические рассуждения, а не сам код (но и код обсудить будет интересно).

Я реализовал через 2 while и перебор сумм по разным ключам. Да, оно работает, но это явно не лучший и однозначно не самый оптимальный вариант. Плюс кушает достаточно много памяти на дальних дистанциях.

Всем заранее спасибо за отклик и уделённое время.

 Комментарий модератора 
Изначально тема была в разделе PHP, но т.к. решения поступают из разных ЯП, было принято решение перенести в Web-мастеринг.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
10.11.2023, 17:49
Ответы с готовыми решениями:

Подсчет суммы элементов в главной и побочной диагоналях в произвольно заданной квадратной
3) Составить функцию подсчета суммы элементов в главной и побочной диагоналях в произвольно заданной квадратной матрице В.

Подсчет суммы элементов массива
подскажите в чем ошибка??? надо посчитать сумму элементов одномерного массива из 7 элементов MASM model small .stack 100h .data ...

Функция: подсчет числа отрицательных элементов массива, и суммы положительных элементов матрицы
написать функцию подсчета отрицательных элементов одномерного массива А(6) и сумму положит-х эл-ов матрицы В(6x6)

39
 Аватар для sad67man
2605 / 1509 / 689
Регистрация: 23.08.2015
Сообщений: 3,841
15.11.2023, 17:47
Студворк — интернет-сервис помощи студентам
Не читал выше посты. Не силен в алгоритмах, сильно не бейте) Первое что пришло в голову отсортировать массив в порядке убывания, и начинать от наибольших значений, заполняя сумму. Если сумма превышена, то вместо последнего числа пытаемся найти подходящее учитывая, что массив отсортирован и т.д.
0
Заблокирован
15.11.2023, 17:59
Цитата Сообщение от sad67man Посмотреть сообщение
вместо последнего числа пытаемся найти подходящее учитывая, что массив отсортирован
Идея понятна, но может не сработать. Вот показываю пример. Массив тот же [100, 3, 20, 60, 50]. Следует получить 213. Берем 100 + 100 и остается 13. Получить уже невозможно.
0
 Аватар для sad67man
2605 / 1509 / 689
Регистрация: 23.08.2015
Сообщений: 3,841
15.11.2023, 18:16
Цитата Сообщение от Bent Посмотреть сообщение
Получить уже невозможно.
Я не понял, а числа могут повторяться? Значит вы не до конца поняли идею)
Решение в лоб, делать полный перебор, а алгоритм должен быть направлен на сокращение количества выборок.
Смысл в том и есть, что суммируем числа до переполнения необходимой суммы и потом вместо числа переполнившего сумму попытаться найти другое число, и зная что массив отсортирован, можно искать к примеру делением пополам. Если такого нет, то тогда отметается предыдущее число и т.д.
А так как массив отсортирован в порядке убывания, то мы получается начинаем с больших чисел. Это как вам нужно набрать 6750 рублей, вы мысленно начнете набирать с наибольших купюр (5000, 1000, 500, 100, 100, 50)
0
Супер-модератор
Эксперт JSЭксперт HTML/CSSЭксперт PHP
 Аватар для gogolik
3983 / 2154 / 833
Регистрация: 13.03.2010
Сообщений: 7,057
15.11.2023, 18:30  [ТС]
sad67man, исходный массив нельзя трогать. А если и трогать, то с сохранением индексов, т.к. по задаче нужно вернуть именно индексы из исходного массива.

И, да, в массиве одинаковые числа могут быть, а вот в решении одинаковых индексов быть не может. Т.е. 1 элемент массива может быть использован только 1 раз.
В этом и основная проблема.

Решения выше, как я понимаю, повторно могут использовать один и тот же элемент массива. Но всё равно интересно и на такие решения посмотреть, вызывают дискуссию.
0
 Аватар для sad67man
2605 / 1509 / 689
Регистрация: 23.08.2015
Сообщений: 3,841
15.11.2023, 18:32
Цитата Сообщение от gogolik Посмотреть сообщение
Решения выше, как я понимаю, повторно могут использовать один и тот же элемент массива.
Можно и так и так.. Это определяется условием и как мы будем брать числа. Либо 1-е 3 раза возьмем, либо набираем 1-е число, 2-е, 3-е До переполнения.
0
Заблокирован
15.11.2023, 18:41
Цитата Сообщение от gogolik Посмотреть сообщение
Т.е. 1 элемент массива может быть использован только 1 раз.
Ааа... значит мы неверно решали задачу. Ну... я точно неверно. И выводил числа, а не индексы. Посчитал, что это будет нагляднее. Ну, тогда большие числа из этого массива составить невозможно. Максимально число - это сумма всех элементов массива. Я правильно понял?
0
 Аватар для sad67man
2605 / 1509 / 689
Регистрация: 23.08.2015
Сообщений: 3,841
15.11.2023, 18:43
Цитата Сообщение от Bent Посмотреть сообщение
Ааа... значит мы неверно решали задачу. Ну... я точно неверно. И выводил числа, а не индексы. Посчитал, что это будет нагляднее. Ну, тогда большие числа из этого массива составить невозможно. Максимально число - это сумма всех элементов массива. Я правильно понял?
По условию известно, что существует хотя бы одна комбинация.
Цитата Сообщение от gogolik Посмотреть сообщение
Заранее известно, что сумму можно получить как минимум одной комбинацией чисел неизвестной длины.
0
Супер-модератор
Эксперт JSЭксперт HTML/CSSЭксперт PHP
 Аватар для gogolik
3983 / 2154 / 833
Регистрация: 13.03.2010
Сообщений: 7,057
15.11.2023, 18:56  [ТС]
Цитата Сообщение от Bent Посмотреть сообщение
Максимально число - это сумма всех элементов массива.
Да, конечно. Но входящая сумма чисел всегда такая, что её можно составить как минимум одной комбинацией (считайте, аксиома такая).
Чем больше элементов у нас в массиве - тем сложнее обсчитать все возможные варианты и найти хотя бы одну подходящую комбинацию.

Я лично так и не смог найти нормальное решение на php, кроме тупого бесконечного подбора. Товарищ на python и go нашел (далеко не оптимальные, хоть и в многопотоке), но там чем больше "глубина" поиска решения, тем дольше его искать. И каждый дополнительный элемент в массиве увеличивает это время в геометрической прогрессии.
0
Заблокирован
15.11.2023, 19:44
Переделал. Но решает невсегда. Пришлось делать защиту от зависаний) Может завтра переделаю.

PHP
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
function test($mas, $out)
{
    $in = 0;
    $mas_key = [];
    $count = 0;
    while ($in !== $out) {
        ++$count;
        if ($count > 1000) {
            return null; #защита от зависаний
        } else if ($in > $out) {
            $in = 0;
            $mas_key = [];
        } else {
 
            $b = false;
            foreach ($mas as $key_ => $value) {
                if ($out - $in === $value) {
                    $key = $key_;
                    $b = true;
                    break;
                }
            }
            if (!$b) $key = rand(0, count($mas) - 1);
            if (!in_array($key, $mas_key)) {
                $in += $mas[$key];
                $mas_key[] = $key;
            }
 
        }
 
        if ($in === $out) {
            break;
        }
    }
    return $mas_key;
}
 
echo '<pre>';
echo "[100, 3, 20, 60, 50]<br>";
echo "123<br>";
print_r(test([100, 3, 20, 60, 50], 123));
echo '<hr>';
echo "133<br>";
print_r(test([100, 3, 20, 60, 50], 133));
echo '<hr>';
echo "173<br>";
print_r(test([100, 3, 20, 60, 50], 173));
echo '<hr>';
echo "183<br>";
print_r(test([100, 3, 20, 60, 50], 183));
echo '<hr>';
echo "213<br>";
print_r(test([100, 3, 20, 60, 50], 213));
echo '<hr>';
echo "233<br>";
print_r(test([100, 3, 20, 60, 50], 233));
echo '</pre>';
0
 Аватар для Дух системы
75 / 58 / 20
Регистрация: 01.10.2009
Сообщений: 208
15.11.2023, 21:09
интересно
Цитата Сообщение от gogolik Посмотреть сообщение
Задан массив int и float чисел, одинаковые числа могут повторяться сколько угодно раз.
входящий массив будет случайный или будет изначально задан как условие?

на сколько большим будет входящий массив?

смотреть массив (переменная=знаю что мы прошли ранее) в итерации массива порнуха?
0
Супер-модератор
Эксперт JSЭксперт HTML/CSSЭксперт PHP
 Аватар для gogolik
3983 / 2154 / 833
Регистрация: 13.03.2010
Сообщений: 7,057
15.11.2023, 21:12  [ТС]
Дух системы, изначально задан, конечно же. Количество элементов не ограничено (тестировали на 247 элементах изначально, но это ту мач, дай б-г с 10 посчитать быстро).
Про "смотреть массив" не понял, но ничего не запрещено, по сути.
0
 Аватар для Дух системы
75 / 58 / 20
Регистрация: 01.10.2009
Сообщений: 208
15.11.2023, 21:36
Цитата Сообщение от gogolik Посмотреть сообщение
Про "смотреть массив" не понял
типа этого

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$array=[];
for($i=0;$i<100;$i++)
{
    $array[$i]='цифра '.$i;
}
for($i=0;$i<100;$i++)
{
    echo $i.';';
    if($i > 0)
    {
        echo $array[round($i-1)].' на 1 назад';//смотрим массив назад
    }
    echo "\r\n";
}
0
Супер-модератор
Эксперт JSЭксперт HTML/CSSЭксперт PHP
 Аватар для gogolik
3983 / 2154 / 833
Регистрация: 13.03.2010
Сообщений: 7,057
15.11.2023, 21:39  [ТС]
Дух системы, кмк это не противоречит задаче, если поможет её решить.
0
Заблокирован
15.11.2023, 21:41
Сделал методом научного тыка) Уже не подвисает. Проверял различные варианты и различные массивы. Вроде работает

PHP
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
function test($mas, $out)
{
    $in = 0;
    $mas_key = [];
    while ($in !== $out) {
        if ($in > $out) {
            $in = 0;
            $mas_key = [];
        } else {
            $b = false;
            foreach ($mas as $key_ => $value) {
                if ($out - $in === $value) {
                    $key = $key_;
                    $b = true;
                    break;
                }
            }
            if (!$b) $key = rand(0, count($mas) - 1);
            if (!in_array($key, $mas_key)) {
                $in += $mas[$key];
                $mas_key[] = $key;
            } else {
                foreach ($mas as $key_ => $value) {
                    if (!in_array($key_, $mas_key)) {
                        $in += $mas[$key_];
                        $mas_key[] = $key_;
                        break;
                    }
 
                }
            }
 
        }
 
        if ($in === $out) {
            break;
        }
    }
    return $mas_key;
}
 
echo '<pre>';
echo "[100, 3, 20, 60, 50]<br>";
echo "123<br>";
print_r(test([100, 3, 20, 60, 50], 123));
echo '<hr>';
echo "133<br>";
print_r(test([100, 3, 20, 60, 50], 133));
echo '<hr>';
echo "173<br>";
print_r(test([100, 3, 20, 60, 50], 173));
echo '<hr>';
echo "183<br>";
print_r(test([100, 3, 20, 60, 50], 183));
echo '<hr>';
echo "213<br>";
print_r(test([100, 3, 20, 60, 50], 213));
echo '<hr>';
echo "233<br>";
print_r(test([100, 3, 20, 60, 50], 233));
echo '</pre>';
 
######## Другой массив ########
 
echo '<pre>';
echo "[88, 33, 20, 60, 11]<br>";
echo "91<br>";
print_r(test([88, 33, 20, 60, 11], 91));
echo '<hr>';
echo "179<br>";
print_r(test([88, 33, 20, 60, 11], 179));
echo '<hr>';
echo '</pre>';
1
 Аватар для Дух системы
75 / 58 / 20
Регистрация: 01.10.2009
Сообщений: 208
15.11.2023, 23:01
Цитата Сообщение от Bent Посмотреть сообщение
Сделал методом научного тыка) Уже не подвисает. Проверял различные варианты и различные массивы. Вроде работает
два перебора, автор хочет этого избежать я так понял
0
Заблокирован
16.11.2023, 06:45
Цитата Сообщение от Дух системы Посмотреть сообщение
два перебора, автор хочет этого избежать я так понял
Думаю, что автор хотел просто предложить задачу и посмотреть на варианты ответов.
0
Супер-модератор
Эксперт JSЭксперт HTML/CSSЭксперт PHP
 Аватар для gogolik
3983 / 2154 / 833
Регистрация: 13.03.2010
Сообщений: 7,057
16.11.2023, 11:34  [ТС]
Цитата Сообщение от Bent Посмотреть сообщение
Думаю, что автор хотел просто предложить задачу и посмотреть на варианты ответов.
Всё верно.
0
Молодой техлид)
Эксперт JSЭксперт HTML/CSS
 Аватар для mr_dramm
1818 / 1056 / 329
Регистрация: 17.07.2021
Сообщений: 2,147
Записей в блоге: 14
19.11.2023, 02:52
Не для соревнования примерно в двоее снизил время работы:
- убрал функцию swapparts теперь нет смены частей массива и копирования, вместо нее сделал валидацию устаревших занчений, смотри параметр sc - swapCount,
- убрал функцию memo, теперь объекты не пересоздаются для хранения предыдущих значений, вместо этого меняются значения в существующих объектах, которые не пересоздаются
- вместо array.slice выполняется цикл for (let k = 0; k < coins.length; k++) dp[imax].a[k] = prev.a[k]; - это изменение дало самый большой прирост, массивы тоже не пересоздаются, а копируются значения в существующие

Асимптотическая сложность по памяти O(максимальный элемент * 2 * количество монет)

Новый вариант
JavaScript
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
const coinChange = function (coins, amount) {
  // test base cases
  if (amount == 0) return 0;
 
  // убираем элементы которые нам точно не пригодятся
  coins = coins.filter((e) => amount >= e);
 
  if (coins.length == 0) return -1;
 
  // без сортировки, достаточно найти только максимум
  const maxVal = Math.max(...coins);
 
  if (maxVal == amount) return 1;
 
  const doubleMaxVal = maxVal * 2;
  // предыдущие значения от которых ведем отсчет
  let dpprev = Array.from({ length: maxVal }, () => ({
      a: new Array(coins.length).fill(0),
      // сумма элементов в массиве чтобы было проще выбирать какую дату оставить
      c: 0,
      // это значение будет использовано для отслеживания устаревания значения 
      sc: doubleMaxVal,
    })),
    // актуальные значения 
    dp = Array.from({ length: maxVal }, () => ({
      a: new Array(coins.length).fill(0),
      // сумма элементов в массиве чтобы было проще выбирать какую дату оставить
      c: 0,
      // это значение будет использовано для отслеживания устаревания значения 
      sc: doubleMaxVal,
    }));
 
  // заполняем массив предыдущих значений
  for (let j = 0; j < coins.length; j++) {
    for (let i = coins[j] - 1, count = 1; i < maxVal; i += 1) {
      if (i - (coins[j] - 1) == 0) {
        if (dpprev[i].c >= count) {
          (dpprev[i].c = 1), (dpprev[i].a[j] = 1);
        } else {
          dpprev[i].c++, dpprev[i].a[j]++;
        }
      } else {
        const prev = dpprev[i - coins[j]];
        if (prev.c) {
          if (dpprev[i].c && prev.c && dpprev[i].c <= prev.c) continue;
          dpprev[i].a = prev.a.slice();
          dpprev[i].a[j]++;
          dpprev[i].c = prev.c + 1;
        }
      }
    }
  }
  // если был элемент равный искомому значению 
  if (amount == maxVal) return dpprev[maxVal - 1].c;
  let imax = 0;
 
  for (let i = maxVal, swapCount = doubleMaxVal; i < amount; i++) {
    if (i == swapCount) {
      const tmp = dpprev;
      dpprev = dp;
      dp = tmp;
      swapCount += maxVal;
    }
    imax = i % maxVal;
    for (let j = 0; j < coins.length; j += 1) {
      const prevIndx = imax - coins[j];
      // определяем где будем искать предыдущее значение
      const prev = prevIndx < 0 ? dpprev[maxVal + prevIndx] : dp[prevIndx];
      if (prev.c) {
        if (dp[imax].c && dp[imax].sc == swapCount && dp[imax].c <= prev.c)
          continue;
        for (let k = 0; k < coins.length; k++) dp[imax].a[k] = prev.a[k];
        dp[imax].a[j]++;
        dp[imax].c = prev.c + 1;
        dp[imax].sc = swapCount;
      }
    }
  }
 
  return dp[imax] == null
    ? -1
    : dp[imax].a.reduce((r, e, i) => {
        r[coins[i]] = e;
        return r;
      }, {});
};
 
 
 
console.log(coinChange([10, 3], 36), 36); // { '3': 2, '10': 3 } 36
console.log(coinChange([474, 83, 404, 3], 264), 264); // { '3': 5, '83': 3 } 264
console.log(coinChange([41, 23, 21, 17, 13], 130), 130); // { '13': 2, '17': 1, '21': 0, '23': 2, '41': 1 } 130
console.log(coinChange([100, 3, 20, 60, 50], 123), 123); // { '3': 1, '20': 0, '50': 0, '60': 2, '100': 0 } 123
 
console.time("mr_dramm");
console.log(coinChange([474, 83, 404, 3], 1000264), 1000264); // { '3': 0, '83': 0, '404': 5, '474': 2106 } 1000264
console.timeEnd("mr_dramm"); // mr_dramm: текущее ~100ms предыдущее было ~200ms
Старый вариант для сравнения

JavaScript
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
function swapParts(source) {
  const halfLength = source.length / 2;
 
  const firstPart = new Array(halfLength).fill(null);
  const secondPart = source.slice(halfLength);
 
  return secondPart.concat(firstPart);
}
 
// source - { a: number[] - elements, c: number - count }
// source1 - dp[i], source2 - dp[i-coin], j index coin
const memo = (s1, s2, i) => {
  if (s1 && s2) {
    if (s1.c <= s2.c) return { a: s1.a.slice(), c: s1.c };
    const o = { a: s2.a.slice(), c: s2.c };
    o.a[i]++;
    o.c++;
    return o;
  } else if (s1) {
    return { a: s1.a.slice(), c: s1.c };
  } else if (s2) {
    const o = { a: s2.a.slice(), c: s2.c };
    o.a[i]++;
    o.c++;
    return o;
  }
  return null;
};
 
const coinChangeProto = function (coins, amount) {
  // test base cases
  if (amount == 0) return null;
 
  // убираем элементы которые нам точно не пригодятся
  coins = coins.filter((e) => amount >= e);
 
  if (coins.length == 0) return null;
 
  // без сортировки, достаточно найти только максимум
  const maxVal = Math.max(...coins);
  const doubleMaxVal = maxVal * 2;
  let dp = new Array(doubleMaxVal).fill(null);
 
  // готовим массив длинной max coin val * 2 для подсчета сумм
  // но заполняем только опервую половину
  for (let j = 0; j < coins.length; j++) {
    for (let i = coins[j] - 1; i < maxVal; i += 1) {
      if (i - (coins[j] - 1) == 0) {
        //dp[i] = Math.min(dp[i], 1);
        // создаем дату с массивом и суммой элементов в массиве чтобы было проще выбирать какую дату оставить
        // не тратить на подсчет тики
        dp[i] = memo(dp[i], { a: new Array(coins.length).fill(0), c: 0 }, j);
      } else {
        // dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
        dp[i] = memo(dp[i], dp[i - coins[j]], j);
      }
    }
  }
 
  let imax = 0;
  for (let i = maxVal, swapCount = doubleMaxVal; i < amount; i++) {
    if (i == swapCount) {
      dp = swapParts(dp);
      swapCount += maxVal;
    }
    imax = (i % maxVal) + maxVal;
    for (let j = 0; j < coins.length; j += 1) {
      // dp[imax] = Math.min(dp[imax], dp[imax - coins[j]] + 1);
      dp[imax] = memo(dp[imax], dp[imax - coins[j]], j);
    }
  }
 
  return dp[imax] == null
    ? -1
    : dp[imax].a.reduce((r, e, i) => {
        r[coins[i]] = e;
        return r;
      }, {});
};
 
console.log(coinChangeProto([10, 3], 36)); // { '3': 2, '10': 3 }
console.log(coinChangeProto([474, 83, 404, 3], 264)); // { '3': 5, '83': 3 }
console.log(coinChangeProto([41, 23, 21, 17, 13], 130)); // { '13': 2, '17': 1, '21': 0, '23': 2, '41': 1 }
console.log(coinChangeProto([100, 3, 20, 60, 50], 123)); // { '3': 1, '20': 0, '50': 0, '60': 2, '100': 0 }
 
console.time("mr_dramm");
console.log(coinChangeProto([474, 83, 404, 3], 1000264), 1000264); // { '3': 0, '83': 0, '404': 5, '474': 2106 } 1000264
console.timeEnd("mr_dramm"); // mr_dramm: ~200ms
0
Заблокирован
19.11.2023, 05:45
Цитата Сообщение от mr_dramm Посмотреть сообщение
console.log(coinChange([474, 83, 404, 3], 1000264), 1000264);
Цитата Сообщение от Bent Посмотреть сообщение
Максимально число - это сумма всех элементов массива. Я правильно понял?
Цитата Сообщение от gogolik Посмотреть сообщение
Да, конечно.
mr_dramm, мы неправильно решали и я уже свой скрипт переделал. Из массива [474, 83, 404, 3] по условию задачи не может получится число 1000264. Потому что один элемент массива можно использовать только один раз.
0
Молодой техлид)
Эксперт JSЭксперт HTML/CSS
 Аватар для mr_dramm
1818 / 1056 / 329
Регистрация: 17.07.2021
Сообщений: 2,147
Записей в блоге: 14
19.11.2023, 11:16
Цитата Сообщение от Bent Посмотреть сообщение
mr_dramm, мы неправильно решали и я уже свой скрипт переделал. Из массива [474, 83, 404, 3] по условию задачи не может получится число 1000264. Потому что один элемент массива можно использовать только один раз
это не мешает упражняться в бесполезности оптимизации =)

Добавлено через 1 час 13 минут
и еще я забыл переделать проверку на не правильные значения, она осталась от старой версии

JavaScript
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
101
102
103
104
105
const coinChange = function (coins, amount) {
  // test base cases
  if (amount == 0) return 0;
 
  // убираем элементы которые нам точно не пригодятся
  coins = coins.filter((e) => amount >= e);
 
  if (coins.length == 0) return -1;
 
  // без сортировки, достаточно найти только максимум
  const maxVal = Math.max(...coins);
 
  // базовый случай когда одно из значений в coins равно amount
  if (maxVal == amount)
    return coins.reduce((r, e, i) => {
      if (e == maxVal) r[e] = 1;
      else r[e] = 0;
      return r;
    }, {});
 
  const doubleMaxVal = maxVal * 2;
  // предыдущие значения от которых ведем отсчет
  let dpprev = Array.from({ length: maxVal }, () => ({
      a: new Array(coins.length).fill(0),
      // сумма элементов в массиве чтобы было проще выбирать какую дату оставить
      c: 0,
      // это значение будет использовано для отслеживания устаревания значения
      sc: doubleMaxVal,
    })),
    // актуальные значения
    dp = Array.from({ length: maxVal }, () => ({
      a: new Array(coins.length).fill(0),
      // сумма элементов в массиве чтобы было проще выбирать какую дату оставить
      c: 0,
      // это значение будет использовано для отслеживания устаревания значения
      sc: doubleMaxVal,
    }));
 
  // заполняем массив предыдущих значений, от минимального до максимального, на этом шаге задача не будет решена
  // так как предварительно мы уже проверили наличие максимального элемента в массиве
  for (let j = 0; j < coins.length; j++) {
    for (let i = coins[j] - 1, count = 1; i < maxVal; i += 1) {
      if (i - (coins[j] - 1) == 0) {
        if (dpprev[i].c >= count) {
          (dpprev[i].c = 1), (dpprev[i].a[j] = 1);
        } else {
          dpprev[i].c++, dpprev[i].a[j]++;
        }
      } else {
        const prev = dpprev[i - coins[j]];
        if (prev.c) {
          if (dpprev[i].c && prev.c && dpprev[i].c <= prev.c) continue;
          dpprev[i].a = prev.a.slice();
          dpprev[i].a[j]++;
          dpprev[i].c = prev.c + 1;
        }
      }
    }
  }
  // основной цикл решения проблемы
  let imax = 0;
  let swapCount = doubleMaxVal;
  for (let i = maxVal; i < amount; i++) {
    if (i == swapCount) {
      const tmp = dpprev;
      dpprev = dp;
      dp = tmp;
      swapCount += maxVal;
    }
    imax = i % maxVal;
    for (let j = 0; j < coins.length; j += 1) {
      const prevIndx = imax - coins[j];
      // определяем где будем искать предыдущее значение
      const prev = prevIndx < 0 ? dpprev[maxVal + prevIndx] : dp[prevIndx];
      if (!prev.c) continue;
 
      if (dp[imax].c && dp[imax].sc == swapCount && dp[imax].c <= prev.c)
        continue;
      for (let k = 0; k < coins.length; k++) dp[imax].a[k] = prev.a[k];
      dp[imax].a[j]++;
      dp[imax].c = prev.c + 1;
      dp[imax].sc = swapCount;
    }
  }
  if (dp[imax].sc == swapCount)
    return dp[imax].a.reduce((r, e, i) => {
      r[coins[i]] = e;
      return r;
    }, {});
  return -1;
};
// значение max равное amount
console.log(coinChange([3, 36], 36), 36); // { '3': 0, '36': 1 } 36
console.log(coinChange([1], 1), 1); // { '1': 1 } 1
 
console.log(coinChange([10, 15], 36), 36); // -1
 
console.log(coinChange([3, 10], 36), 36); // { '3': 2, '10': 3 } 36
console.log(coinChange([474, 83, 404, 3], 264), 264); // { '3': 5, '83': 3 } 264
console.log(coinChange([41, 23, 21, 17, 13], 130), 130); // { '13': 2, '17': 1, '21': 0, '23': 2, '41': 1 } 130
console.log(coinChange([100, 3, 20, 60, 50], 123), 123); // { '3': 1, '20': 0, '50': 0, '60': 2, '100': 0 } 123
 
console.time("mr_dramm");
console.log(coinChange([474, 83, 404, 3], 1000264), 1000264); // { '3': 0, '83': 0, '404': 5, '474': 2106 } 1000264
console.timeEnd("mr_dramm"); // mr_dramm: текущее ~100ms предыдущее было 200ms
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
19.11.2023, 11:16

Подсчет суммы двухбайтовых элементов массива
Здравствуйте. Возникла проблема, задание было такое: &quot;Задан одномерный массив двухбайтовых знаковых чисел. Необходимо разработать...

Подсчет суммы отрицательных элементов массива
Доброго времени суток! Ребят, очень нужна помощь,есть программа для подсчета количества отрицательных елементов массива, как сделать что б...

Подсчет суммы нечетных элементов массива
Создать функцию, которая подщитывает сумму нечетных элементов массива: #include &quot;stdafx.h&quot; #include &lt;iostream&gt; using...

Подсчет суммы отрицательных элементов массива А(10)
Помогите решить задачку подсчета суммы отрицательных элементов массива А(10) буду признателен

Подсчет суммы положительных элементов массива
#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #define MAX 20 int main() { int A = {0}; int B = {0}; int AB = {0}; int i,...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru