Задание 1 Отличное
Решение:
Это классическая простая задача для использования хеш-набора или другой структуры данных, которая позволяет быстро добавлять и находить значения. Никаких уловок нет.
В C ++ это выглядит так:
int count_distinct(vector<int> &v) { return std::unordered_set<int>(v.begin(), v.end()).size(); }
Задача 2 MaxProductOfThree
Решение:
Здесь нам не нужно сортировать массив или делать что-то сложное. Нам просто нужно просканировать данный массив, чтобы найти 3 наибольших числа (неважно положительные или отрицательные) и два наименьших отрицательных числа. Затем мы сравниваем, какой продукт больше - произведение трех наибольших чисел или произведение наибольшего числа и двух наименьших отрицательных чисел.
Как вы помните, результат умножения двух отрицательных чисел положительный, а результат умножения отрицательных и положительных чисел отрицательный. Значит должно быть как минимум два отрицательных множителя для увеличения произведения. Единственный отрицательный множитель уменьшит результат умножения. Но если у нас тоже самое большое отрицательное число, это меньше всего повлияет на результат.
Я использовал здесь 3 переменные вместо очереди, потому что она короче и выглядит более очевидной. В случае, если вам нужно будет найти произведение, состоящее из более чем трех чисел, удобнее будет использовать std :: deque.
Мы начинаем поиск наименьших отрицательных чисел с нуля и переходим к меньшим числам, но мы начинаем поиск наибольших чисел с -1000 и переходим к большим числам, потому что наибольшее число также может быть отрицательным.
В C ++ это выглядит так:
int max_product_of_three(vector<int> &v) { vector<int> max_num(3,-1000); vector<int> min_neg(2,0); const int v_size = v.size(); for (auto i = 0; i < v_size; ++i) { if (v[i] < min_neg[0] ) { min_neg[1]=min_neg[0]; min_neg[0]=v[i]; } else if (v[i] < min_neg[1]) { min_neg[1]=v[i]; } if (v[i] > max_num[0]) { max_num[2]=max_num[1]; max_num[1]=max_num[0]; max_num[0]=v[i]; } else if (v[i] > max_num[1]) { max_num[2]=max_num[1]; max_num[1]=v[i]; } else if (v[i] > max_num[2]) { max_num[2]=v[i]; } } auto res_neg = max_num[0] * min_neg[0] * min_neg[1]; auto res_pos = max_num[0] * max_num[1] * max_num[2]; return max (res_pos, res_neg); }
Задание 3 NumberOfDiscIntersections
Решение:
Вообще в этой задаче лучше думать не о дисках, а о отрезках на оси координат.
Поскольку эта задача находится в уроке о сортировке, классический алгоритм этого решения должен выглядеть так:
1. Создайте массив пар, каждая пара содержит начальный и конечный индексы диска. Другими словами, массив состоит из сегментов, покрывающих диаметры дисков.
2. Отсортируйте массив по первой записи каждой пары: индексам начала диска. Другими словами, отсортируйте массив по первым точкам отрезков, охватывающих диаметры дисков.
3. Подсчитайте количество пересечений на «активном» участке. Для этого обхода по массиву, начиная с крайнего левого интервала (то есть с наименьшего i-A [i]). Для текущего сегмента выполните двоичный поиск, чтобы увидеть, куда пойдет правая конечная точка сегмента (т.е. i + A [i]). Теперь вы знаете, что он пересекает все элементы слева.
Увеличьте счетчик с правой конечной точкой текущего сегмента и вычтите текущую позицию, так как мы не хотим дублировать интервалы и самопересечения.
Сложность O (NlogN) раз, O (N) пробела.
Решение на C ++ выглядит так:
Но есть намного лучшее, короче и понятное решение со сложностью Log (N)
1. Создайте массив пар, как в предыдущем решении.
2. Затем пройдите мимо массива и подсчитайте сегменты, которые содержат текущую точку «i» на оси.
Каждый раз, когда новый сегмент начинается в позиции «i», он пересекается со всеми существующими сегментами (дисками) в этом месте. Вот почему у нас есть часть «active * start [i]» в формуле. Нам также необходимо добавить количество пересечений для всех сегментов, которые только что начались в местоположении «i», т. Е. Количество пересечений внутри самих себя, за исключением того, что уже существует »(start [i] * (start [i] - 1)) / 2 ”. Например, если началось 5 сегментов (дисков) в одной точке, она увеличится на 1 + 2 + 3 + 4 пересечения, или 5 * (5–1) / 2.
Решение на C ++ выглядит так:
Задание 4 Треугольник
Решение:
Данный массив содержит отрезки длины. Вопрос в том, чтобы найти отрезки такой длины, чтобы из них можно было построить треугольник. По определению из описания задачи стороны треугольника всегда P ‹Q‹ R.
В этой задаче, кажется, нет простого решения без сортировки. Таким образом, если мы отсортируем данный массив, будет легко найти все сегменты, которые могут построить треугольник. После сортировки массива A [R] всегда больше, чем A [Q] и A [P], поэтому A [Q] + A [R] ›A [P] и A [R] + A [P]› A [ Q] всегда истинны, поэтому нам нужно проверить только A [P] + A [Q] ›A [R].
По определению задачи элементы массива могут быть достаточно большими, чтобы переполнять переменную int во время добавления. Чтобы избежать этой проблемы, мы можем сравнить A [P] ›A [R] - A [Q] вместо A [P] + A [Q]› A [R]
Таким образом, решение на C ++ выглядит так:
int find_triangle(vector<int> &v) { const int v_size = v.size(); if(v_size < 3) { return 0; } std::sort(v.begin(), v.end()); for (auto i = 2; i < v_size; ++i) { if (v[i - 2] > v[i] - v[i - 1]) { return 1; } } return 0; }
Вернитесь к оглавлению.