Фрукты в корзинах

Фрукты в корзинах


Условие задачи

Дан массив ASCII-символов, в котором каждый символ обозначает вид фруктового дерева. У вас есть две корзины, и в каждую можно складывать фрукты только одного вида.

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

Пример 1:

1
2
3
Вход: ['A', 'B', 'C', 'A', 'C']
Выход: 3
Пояснение: на участке ['C', 'A', 'C'] можно собрать два фрукта C и один фрукт A.

Пример 2:

1
2
3
Вход: ['A', 'B', 'C', 'B', 'B', 'C']
Выход: 5
Пояснение: на участке ['B', 'C', 'B', 'B', 'C'] можно собрать три фрукта B и два фрукта C.

Решение

Задача сводится к поиску самого длинного непрерывного подмассива, содержащего не более двух различных видов фруктов. Это частный случай задачи о самой длинной подстроке с k различными символами при k=2.

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

Код

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
package main

import "fmt"

func fruitsIntoBaskets(fruits []byte) int {
	frequencies := make(map[byte]int)
	windowStart := 0
	maxFruits := 0

	for windowEnd, fruit := range fruits {
		frequencies[fruit]++

		for len(frequencies) > 2 {
			leftFruit := fruits[windowStart]
			frequencies[leftFruit]--
			if frequencies[leftFruit] == 0 {
				delete(frequencies, leftFruit)
			}
			windowStart++
		}

		windowLength := windowEnd - windowStart + 1
		if windowLength > maxFruits {
			maxFruits = windowLength
		}
	}

	return maxFruits
}

func main() {
	fmt.Println("Максимальное количество фруктов:", fruitsIntoBaskets([]byte{'A', 'B', 'C', 'A', 'C'}))
	fmt.Println("Максимальное количество фруктов:", fruitsIntoBaskets([]byte{'A', 'B', 'C', 'B', 'B', 'C'}))
}

Вывод:

1
2
Максимальное количество фруктов: 3
Максимальное количество фруктов: 5

Временная сложность

Каждый элемент добавляется в окно и удаляется из него не более одного раза, поэтому временная сложность равна \(O(N)\).

Пространственная сложность

В частотной таблице одновременно находится не более трёх видов фруктов, поэтому алгоритм использует \(O(1)\) дополнительной памяти.