Задать вопрос
@VasyaM13221

Определить что элементы одной коллекции являются квадратными корнями другой?

Подскажите можно-ли написать более оптимальный алгоритм. Задача звучит так:

Нужно проверить что все в коллекции squares являются квадратными корнями чисел в коллекции numbers. Коллекции отсортированы по возрастанию и не имеют отрицательных значений.

update: если коллекции разной длины то считаем это как false

Примеры входных данных и ответы:
IN: {1, 2}, {1, 4} OUT: TRUE

IN: {1, 3, 5}, {1, 9, 25, 25} OUT: FALSE



Сигнатура функции:
bool TestForSquares(IEnumerable<int> numbers, IEnumerable<int> squares)


Моё решение:

public static bool TestForSquares(IEnumerable<int> numbers, IEnumerable<int> squares) {
    var isFirstIteration = true;
    var numbersEnumerator = numbers.GetEnumerator();
    var squaresEnumerator = squares.GetEnumerator();

    while (true) {
        bool numberHasNext = numbersEnumerator.MoveNext();
        bool squareHasNext = squaresEnumerator.MoveNext();

        if(numberHasNext != squareHasNext) {
            // случай когда две коллекции имеют разный размер

            return false;
        }

        if(!numberHasNext && !squareHasNext) {

            if (isFirstIteration) {
                // случай когда две коллекции пусты
                return false;
            }

            break;
        }

        var testData = numbersEnumerator.Current * numbersEnumerator.Current;
        if(testData != squaresEnumerator.Current) {
            return false;
        }

        isFirstIteration = false;
    }

    return true;
}


p.s.

Так же интересует решение с той же оптимальностью но не такое многословное.
  • Вопрос задан
  • 155 просмотров
Подписаться 1 Простой 12 комментариев
Решения вопроса 1
Lynn
@Lynn
nginx, js, css
Disclaimer: Я не пишу на C# так что возможны ошибки, но идея простая, надо использовать foreach.
Эта функция вернёт true если обе коллекции пусты.
public static bool TestForSquares(IEnumerable<int> numbers, IEnumerable<int> squares) {
    var squaresEnumerator = squares.GetEnumerator();

    foreach(int number in numbers) {
        if(!squaresEnumerator.MoveNext()) {
            // в squares закончились элементы, а в numbers ещё нет
            return false;
        }

        if(number * number != squaresEnumerator.Current) {
            return false;
        }
    }

    if(squaresEnumerator.MoveNext()) {
        // в squares ещё остались элементы, а в numbers уже всё закончилось
        return false;
    }

    return true;
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Griboks
@Griboks Куратор тега C#
Если речь про оптимальную длину кода, то можно использовать что-то в этом роде:
bool TestForSquares(IEnumerable<int> numbers, IEnumerable<int> squares) =>  numbers.Count == squares.Count && squares.Select(x=>x*x).All(x=>numbers.Contains(x));


C учётом правок задания и комментариев.
Ответ написан
freeExec
@freeExec
Участник OpenStreetMap
Задача на работу со множествами.
static bool TestSet(IEnumerable<int> numbers, IEnumerable<int> squares)
{
    var ns = new HashSet<int>(numbers.Select(n => (int)Math.Round(Math.Sqrt(n))));
    return ns.IsSupersetOf(squares);
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы