Как найти квадрат чисел в массиве

Время чтения 3 мин.

Метод Square() в Numpy возвращает массив элементов, возведенных в квадрат.

Содержание

  1. Что такое функция np.square() в Python?
  2. Синтаксис
  3. Параметры
  4. Возвращаемое значение
  5. Примечание
  6. Пример
  7. Массив с плавающей запятой Numpy Square()
  8. Квадрат Numpy для комплексных чисел
  9. Параболический график квадратичной функции
  10. Передача пустого массива
  11. Указание dtype

Функция np.square() используется в Python для нахождения квадрата каждого элемента в заданном массиве. Метод numpy Square() принимает четыре параметра: arr, out, where и dtype и возвращает новый массив со значением аргумента в виде квадрата элементов исходного массива.

Чтобы найти квадрат массива, вы можете использовать метод numpy Square(). Исходный массив остается неизменным. np Square() — это служебная функция, позволяющая быстро получить квадрат элементов матрицы.

Синтаксис

numpy.square(arr, out=None, where=True, dtype=None)

Параметры

  1. arr: введите array_like, содержащий элементы, которые нужно возвести в квадрат.
  2. out :(ndarray, None или кортеж ndarray) [Необязательный параметр] Указывает альтернативный выходной массив, в который помещается результирующий продукт. Он должен иметь ту же или широковещательную форму, что и ожидаемый результат.
  3. where:(array_like) [Необязательный параметр] Это элементы, которые необходимо включить.
  4. dtype : [Необязательный параметр] Указывает тип возвращаемого массива.

Возвращаемое значение

Квадрат каждого из элементов в переданном массиве имеет форму массива.

Метод np.square в Python

Примечание

  • Если входной массив пуст, метод Square() возвращает пустой массив.
  • Этот метод может показать параболический график квадратичной функции.

Пример

В следующем примере демонстрируется использование метода Square().

import numpy as np

arr1 = [1, 2, 3, 4, 5]

arr2 = np.square(arr1)

print(arr2)

Выход:

Массив с плавающей запятой Numpy Square()

Возьмем массив numpy со значениями с плавающей запятой.

import numpy as np

arr1 = [1.1, 2.1, 1.9, 4.6]

arr2 = np.square(arr1)

print(arr2)

Выход:

Теперь давайте возьмем два целых числа и два значения с плавающей запятой и посмотрим на результат.

import numpy as np

arr1 = [1.1, 21, 19, 4.6]

arr2 = np.square(arr1)

print(arr2)

Выход:

Квадрат Numpy для комплексных чисел

Чтобы найти квадрат полных чисел, используйте метод np.square().

Следующий код демонстрирует случай, когда элемент массива является комплексным числом.

import numpy as np

arr1 = [2 + 4j]

arr2 = np.square(arr1)

print(arr2)

Выход:

Параболический график квадратичной функции

Следующий пример демонстрирует параболический график квадратичной функции. Для этого примера вам необходимо сначала установить библиотеку matplotli.

Теперь посмотрите на следующий код.

import numpy as np

import matplotlib.pyplot as plt

x = np.linspace(start=100, stop=100, num=100, endpoint=True)

plt.title(“Green : Squared valuesnOrange : Linear plot”)

plt.plot(x, np.square(x), color=‘green’)

plt.plot(x, x, color=‘orange’)

plt.show()

Выход:

Пример Numpy square()

Вы можете увидеть параболический график метода Square() в Numpy.

Передача пустого массива

Если мы передадим пустой массив в функцию np.square(), она вернет пустой массив.

В следующем примере демонстрируется случай, когда передается пустой массив.

import numpy as np

arr1 = []

arr2 = np.square(arr1)

print(arr2)

Выход:

В следующем примере показано использование параметра where, чтобы указать, какие элементы возводить в квадрат. Для остальных элементов возвращается значение мусора.

import numpy as np

arr1 = [1, 2, 3, 4, 5]

arr2 = np.square(arr1, where=[True, False, True, False, True])

print(arr2)

Выход:

[                   1 4611677251740556998                    9

      140266991895344                   25]

Из вывода вы можете видеть, что он возвращает мусорные значения для остальных элементов.

Указание dtype

В следующем примере демонстрируется случай, когда dtype указывает тип данных элементов.

import numpy as np

arr1 = [5, 2, 1]

arr2 = np.square(arr1, dtype=np.int8)

print(arr2.dtype == np.int8)

arr1 = np.array([5, 2, 1], dtype=np.int8)

print(np.square(arr1).dtype == np.int)

print(np.square(arr1).dtype == np.int8)

Выход:

В приведенном выше коде мы определили тип данных от arr2 до int8. В следующем примере демонстрируется применение этого метода в простом контексте программирования.

Дана последовательность чисел, найти сумму их квадратов.

import numpy as np

n = int(input(“Count: “))

numbers = []

for i in range(n):

    numbers.append(int(input()))

numbers = np.square(numbers)

res = sum(numbers)

print(res)

Выход:

Test Case 1:

->python3 example7.py

Count: 4

1

2

3

4

30

Test Case 2:

->python3 example7.py

Count: 3

1

2

3

14

В этом примере мы взяли два тестовых примера, чтобы продемонстрировать сумму и квадрат чисел. Мы использовали такие функции, как int(), input(), range(), append(), Square() и sum().

return прерывает выполнение функции и возвращает указанный результат, который можно использовать где-то в другом месте (по умолчанию у всех функций return undefined). В вашем случае – цикл сразу прерывается вместе с функцией, возвращая первое же значение x[0] ** 2 → 4. Нужно сначала посчитать сумму, и только в самом конце вернуть её.

Ну чтобы посчитать сумму – нужна дополнительная переменная, куда все будет добавляться. Самое простое решение будет таким:

let x = [2, 4, 6];
let result = bubu(x);

console.log( result );

function bubu(arr){
  let sum = 0;
  for (let i = 0; i < arr.length; i++) {
    sum = sum + (arr[i] * arr[i]);
  }
  
  return sum;
}

И на эльфийском:

let x = [2, 4, 6];

console.log( x.reduce( (sum, e) => sum += e**2, 0 ) );

См. “Стрелочные функции”, “метод reduce”. Их вначале сложновато понять, так и должно быть)

I have an array of integers, and I need an O(n) algorithm to find if the array contains a number and its square; one pair is sufficient.

I tried to do it myself, but I have only managed to find a solution in O(n2).

I thought about using counting sort, but the memory usage is too big.

Bill the Lizard's user avatar

asked Feb 1, 2010 at 20:11

gillyb's user avatar

6

create a new array twice the length of the input array. O(2N)
copy all of the numbers in O(N)
copy the squares of the numbers in O(N)
radix sort (we can since they are all ints) O(N)
iterate over once to see if there are two numbers the same one after the other O(N)
profit! O(1)

answered Feb 1, 2010 at 20:17

Chris H's user avatar

Chris HChris H

6,3955 gold badges33 silver badges51 bronze badges

12

There are basically two ways to do this.

  1. Sort the array and then perform a binary search for the square of each number. Overall complexity would be O(nlogn), but it would need sorting which would destroy the original ordering (which might be important for your case).

  2. Insert all items of the array into a hashtable (or any fast set data structure). Then iterate over the elements of the array again, checking to see if its square exists in the hashtable. Using a hashtable gives an overall complexity of O(n), but you will need O(n) extra space. You could also use a tree-based set (e.g. std::set in C++ or TreeSet in Java), which would give you a complexity of O(nlogn).

answered Feb 1, 2010 at 20:24

MAK's user avatar

MAKMAK

26k11 gold badges54 silver badges85 bronze badges

If we’re allowed to take that the input can be sorted in O(N) by radix sort, I’d improve a bit on Chris’s solution:

  • radix sort the input.
  • For the first element of the result, linear search forward until we find either its square (in which case stop with true), or else the end (in which case stop with false) or else a value larger than the square (in which case continue searching for the square of the second and subsequent elements of the sorted array).

Each of the two “pointers” is moving strictly forward, so the overall complexity is O(N), assuming that the radix sort is O(N) and that squaring and comparison are O(1). Presumably whoever set the question intended these assumptions to be made.

In response to a comment by the questioner on another answer: if the integers in the input are not bounded, then I don’t think it can be done. Just calculating the square of an integer requires greater than linear time (at least: no linear algorithm for multiplication is known), so consider an input of size n bits, consisting of two integers of size n / 3 bits and 2 * n / 3 bits. Testing whether one is the square of the other cannot be done in O(n). I think. I could be wrong.

answered Feb 1, 2010 at 21:52

Steve Jessop's user avatar

Steve JessopSteve Jessop

272k39 gold badges455 silver badges697 bronze badges

13

While I can’t add to the suggestions above, you can reduce the average run time by first finding the min and max values in your data set (both O(n)) and confining your search to that range. For instance if the maximum value is 620, I know that no integer 25 or over has a square in the list.

answered Feb 1, 2010 at 20:43

Grembo's user avatar

GremboGrembo

1,2237 silver badges6 bronze badges

You may be able to do it with a couple of hashsets helping you out.

While iterating,
If the value is in the squares hashset, you’ve got a pair (value is the square of a previously found value)
If the square is in the values hashset, you’ve got a pair (square of this value was already passed)
else store the value in one and the square in the other.

answered Feb 1, 2010 at 22:02

NG.'s user avatar

NG.NG.

22.5k5 gold badges55 silver badges61 bronze badges

Personally I think that Anon’s answer (the little algorithm with ‘squares’) is more useful than it appears to be: remove the ‘remove all less than e from squares’ line from it, and the algorithm can handle an unsorted input array.

If we assume the typical Homework machine with Sufficient Space, the ‘squares’ datastructure could be modelled as an array of boolean flags, yielding true O(1) lookup time.

answered Feb 1, 2010 at 22:57

Lars's user avatar

LarsLars

1,3776 silver badges6 bronze badges

Without sorting, works with duplicates:

Iterate the array to find the smallest and largest integers. O(n)
Create an array of bits the the size of the difference. O(1) time, O(k) space
(Now each possible integer between the smallest and largest values has a corresponding bit in the array)
Iterate the old-array, setting the bit corresponding to each integer found to 1. O(n)
Iterate the old-array again, checking if the integer’s square has its corresponding bit set. O(n)

(Though I didn’t sort, this algorithm can be very easily modified to create a sorting algorithm which sorts in O(n+k) time and O(k) space)

answered Feb 2, 2010 at 16:26

BlueRaja - Danny Pflughoeft's user avatar

4

If we’re using C/C++ 32 bit unsigned ints the maximum value that can be stored is: 4294967295 =(2<<32)-1. The largest number whose square we can store is (1<<16)-1=65535. Now if create an array of bits and store in the array whether we’ve seen the number and/or its square (2 bits per “slot”) we can get the total storage down to 65535/4 = 16384 bytes.

IMO This is not excessive memory consumption so we should be able to do this without radix sorting. An O(N) algorithm could look like this:

uint32_t index(uint32_t i ) { return i/4; }
unsigned char bit1( uint32_t i ) { return 1<<( (i%4)*2 ); }
unsigned char bit2( uint32_t i ) { return 1<<( (i%4)*2 +1 ); }


bool hasValueAndSquare( std::vector<uint32_t> & v )
{
   const uint32_t max_square=65535;

   unsigned char found[(max_square+1)/4]={0};
   for(unsigned int i=0; i<v.size(); ++i)
   {
      if (v[i]<=max_square)
      {
          found[ index(v[i]) ] |= bit1(v[i]);
          if ((found[ index(v[i])] & bit2(v[i])) == bit2(v[i])) return true;
      }
      uint32_t w = (uint32_t)round(sqrt(v[i]));
      if( w*w == v[i] )
      {
          found[ index(w) ] |= bit2(w);
          if ((found[index(w)] & bit1(w)) == bit1(w)) return true;
      }
    }
    return false;
 }

This is not tested, not very optimized, and a proper integer square-root would be better.
however the compiler should inline all the bit-accessing functions – so they’ll be OK.

Note that if we’re using 64 bit ints the memory consumption becomes much larger, instead of an array of 16Kb we need an array of 1Gb – possible less practical.

Ray Burns's user avatar

Ray Burns

61.9k12 gold badges139 silver badges140 bronze badges

answered Feb 1, 2010 at 23:53

Michael Anderson's user avatar

Michael AndersonMichael Anderson

69.9k7 gold badges134 silver badges184 bronze badges

Optimization notes

Both the hashset and radix sort algorithms can be optimized by noting three facts:

  1. Odd and even values can be handled separately
  2. Calculating an integer square root is a very fast operation (typically consists of 3-5 divides and a few adds)
  3. Cache locality is important for both of these algorithms

The optimized algorithms below will typically perform 5x faster and use less than half the RAM of the unoptimized case. In some cases where the data size is similar to the L2/L3 cache size they may perform 100x faster or more.

Optimized algorithm based on radix sort

Data structure is five lists of integers: IN, Aodd, Bodd, Aeven, Beven
The A and B lists use half the integer size of IN. (eg if IN = 64bits, A & B = 32bits)

  1. Scan list IN to find the largest odd and even numbers MAXodd and MAXeven
  2. Let LIMITodd = floor(sqrt(MAXodd))
  3. Let LIMITeven = floor(sqrt(MAXeven))
  4. For each number in list IN: a. Compute the square root if positive. If exact, add the square root to list Aodd/Aeven. b. If the number is >=0 and <= LIMITodd/LIMITeven, add it to list Bodd/Beven
  5. Radix sort list Aodd and Bodd using just log2(LIMITodd) bits
  6. Linear scan Aodd and Bodd for a match
  7. Radix sort list Aeven and Beven using just log2(LIMITeven) bits
  8. Linear scan Aeven and Beven for a match

If either linear scan finds a match, return that match immediately.

The reason this is much faster than the straightforward radix sort algorithm is that:

  • The arrays being sorted typicaly have less than 1/4 the numbers of values and need only half the number of bits per integer, so a total of less than 1/8 the RAM in use in a given sort which is good for the cache.
  • The radix sort is done on much fewer bits leading to fewer passes, so even if it does exceed your L1 or L2 cache you read RAM fewer times, and you read much less RAM
  • The linear scan is typically much faster because the A list contains only exact square roots and the B list only contains small values

Optimized algorithm based on hashset

Data structure is list of integers IN, plus two hashsets A and B
The A and B sets use half the integer size of IN

  1. Scan list IN to find the largest odd and even numbers MAXodd and MAXeven
  2. Let LIMITodd = floor(sqrt(MAXodd))
  3. Let LIMITeven = floor(sqrt(MAXeven))
  4. For each odd number in list IN: a. Compute the square root if positive. If exact, check if square root exists in B & return if true otherwise add it to A. b. If the number is >=0 and <= LIMITodd/LIMITeven, check if it exists in A & return if true otherwise add it to B.
  5. Clear A and B and repeat step 4 for even numbers

The reason this is faster than the straightforward hashset algorithm is that:

  • The hashset is typically 1/8 the amount of RAM leading to much better cache performance
  • Only exact squares and small numbers have hashset entries, so much less time is spent hashing and adding/removing values

There is an additional small optimization available here: A and B can be a single hashset, which stores bit flag with each entry to say whether the integer is in A or B (it can’t be in both because then the algorithm would have terminated).

answered Feb 18, 2010 at 5:37

Ray Burns's user avatar

Ray BurnsRay Burns

61.9k12 gold badges139 silver badges140 bronze badges

If I correctly understand the problem, you have to check if a specified number is in the array. And not finding all the numbers in the array that have their square in the array too.
Simply maintain two boolean (one to check if the number has been found, another for the square), iterate over the elements in the array and test each element. Return the AND of the two boolean.

In pseudo code :

bool ArrayContainsNumberAndSquare(int number, int[] array):
boolean numberFound, squareFound;
int square = number * number;
foreach int i in array
(
  numberFound = numberFound || i == number;
  squareFound = squareFound || i == square;
)
return numberFound && squareFound;

answered Feb 1, 2010 at 20:36

Sylvestre Equy's user avatar

1

1) With the hashmap you get O(n).

2) If you use std::set on 2 sets: the evens, and the odds, you can get

2*O((n/2)log(n/2))=O(nlog(n/2))

assuming there is roughly as many evens than odds

answered Feb 2, 2010 at 12:18

Bob Yoplait's user avatar

Bob YoplaitBob Yoplait

2,4011 gold badge23 silver badges35 bronze badges

If the array is not sorted, you won’t be able to do O(n).

If it is sorted, you can make use of that property to do it in one pass, like so:

foreach e in array
    if squares contains e
        return true
    remove all less than e from squares
    add e * e to squares
return false

Where squares is, say, a HashSet.

If it’s not sorted, you can sort it in O(n log n) and then use this method to check for squares, which will still be faster than the naive solution on a large enough data set.

answered Feb 1, 2010 at 20:16

Anon.'s user avatar

Anon.Anon.

58.4k8 gold badges81 silver badges86 bronze badges

1

У меня есть массив целых чисел, и мне нужен алгоритм O (n), чтобы найти, содержит ли массив число и его квадрат; достаточно одной пары.

Я попытался сделать это сам, но мне удалось найти решение в O (n 2).

Я думал об использовании сортировки, но использование памяти слишком велико.

4b9b3361

Ответ 1

создать новый массив в два раза больше длины входного массива. O (2N)
скопируйте все числа в O (N)
скопируйте квадраты чисел в O (N)
radix sort (мы можем, так как они все ints) O (N)
повторяйте один раз, чтобы увидеть, есть ли два числа один и тот же один после другого O (N)
прибыль! O (1)

Ответ 2

В основном есть два способа сделать это.

  • Сортируйте массив и затем выполните двоичный поиск квадрата каждого числа. Общая сложность была бы O (nlogn), но для этого потребовалась бы сортировка, которая бы уничтожила первоначальный порядок (что может быть важно для вашего случая).

  • Вставьте все элементы массива в хэш-таблицу (или любую быструю структуру данных set). Затем снова перебираем элементы массива, проверяя, существует ли его квадрат в хэш-таблице. Использование хэш-таблицы дает общую сложность O (n), но вам понадобится дополнительное пространство O (n). Вы также можете использовать древовидный set (например, std::set в С++ или TreeSet в Java), что даст вам сложность O (nlogn).

Ответ 3

Если нам разрешено считать, что вход может быть отсортирован в O (N) по методу radix, я бы немного улучшил решение Chris:

  • radix сортировать входные данные.
  • Для первого элемента результата линейный поиск вперед, пока мы не найдем либо его квадрат (в этом случае stop with true), либо конец (в этом случае stop with false), либо значение больше квадрата ( в этом случае продолжить поиск квадрата второго и последующих элементов отсортированного массива).

Каждый из двух “указателей” движется строго вперед, поэтому общая сложность – это O (N), предполагая, что радиальная сортировка – это O (N), а квадратура и сравнение – O (1). Предположительно, тот, кто задал вопрос, предполагал, что эти предположения будут сделаны.

В ответ на комментарий эксперта по другому ответу: если целые числа на входе не ограничены, то я не думаю, что это можно сделать. Простое вычисление квадрата целого требует больше, чем линейного времени (по крайней мере: нет линейного алгоритма для умножения), поэтому рассмотрим входные биты размера n, состоящие из двух целых чисел размером n / 3 bits и 2 * n / 3 бит. Проверка того, является ли один квадрат другого, не может быть выполнена в O (n). Я думаю. Я мог ошибаться.

Ответ 4

Пока я не могу добавить к приведенным выше предложениям, вы можете уменьшить среднее время выполнения, сначала найдя минимальные и максимальные значения в своем наборе данных (как O (n)), так и ограничив свой поиск в этом диапазоне. Например, если максимальное значение равно 620, я знаю, что целое число 25 или более не имеет квадрата в списке.

Ответ 5

Вы можете сделать это с помощью нескольких хешсет, которые помогут вам.

Во время итерации,
Если значение находится в квадрате hashset, у вас есть пара (значение представляет собой квадрат ранее найденного значения)
Если квадрат находится в значениях hashset, у вас есть пара (квадрат этого значения уже был пройден)
иначе сохраните значение в одном и в квадрате в другом.

Ответ 6

Лично я думаю, что ответ Анона (маленький алгоритм с “квадратами” ) более полезен, чем кажется: удалите из него строку “удалить все меньше, чем е из квадратов”, и алгоритм может обрабатывать несортированный вход массив.

Если мы предположим, что типичная машина Homework с достаточным пространством, структура данных квадратов может быть смоделирована как массив булевых флагов, что дает истинное время поиска O (1).

Ответ 7

Если мы используем 32-битные unsigned ints C/С++, максимальное значение, которое может быть сохранено: 4294967295 = (2 < 32) -1. Наибольшее число, квадрат которого мы можем сохранить, равен (1 < 16) -1 = 65535. Теперь, если создать массив бит и сохранить в массиве, видели ли мы число и/или его квадрат (2 бит на “слот” ), мы можем получить общее хранилище до 65535/4 = 16384 байт.

IMO. Это не чрезмерное потребление памяти, поэтому мы должны иметь возможность сделать это без сортировки по основанию. Алгоритм O (N) может выглядеть следующим образом:

uint32_t index(uint32_t i ) { return i/4; }
unsigned char bit1( uint32_t i ) { return 1<<( (i%4)*2 ); }
unsigned char bit2( uint32_t i ) { return 1<<( (i%4)*2 +1 ); }


bool hasValueAndSquare( std::vector<uint32_t> & v )
{
   const uint32_t max_square=65535;

   unsigned char found[(max_square+1)/4]={0};
   for(unsigned int i=0; i<v.size(); ++i)
   {
      if (v[i]<=max_square)
      {
          found[ index(v[i]) ] |= bit1(v[i]);
          if ((found[ index(v[i])] & bit2(v[i])) == bit2(v[i])) return true;
      }
      uint32_t w = (uint32_t)round(sqrt(v[i]));
      if( w*w == v[i] )
      {
          found[ index(w) ] |= bit2(w);
          if ((found[index(w)] & bit1(w)) == bit1(w)) return true;
      }
    }
    return false;
 }

Это не проверено, не очень оптимизировано, и правильный целочисленный квадратный корень будет лучше.
однако компилятор должен встроить все функции доступа к битам – так что все будет в порядке.

Обратите внимание, что если мы используем 64-битные ints, потребление памяти становится намного больше, вместо массива 16Kb нам нужен массив 1Gb – возможно менее практичный.

Ответ 8

Без сортировки работает с дубликатами:

Итерируйте массив, чтобы найти наименьшие и наибольшие целые числа. О (п)
Создайте массив бит, размер разницы. O (1) время, O (k) пространство
(Теперь каждое возможное целое число между наименьшим и самым большим значением имеет соответствующий бит в массиве)
Итерируйте старый массив, установив бит, соответствующий каждому целому числу, найденному в 1. O (n)
Итерируйте старый массив снова, проверяя, имеет ли целочисленный квадрат соответствующий бит. О (п)

(Хотя я не сортировал, этот алгоритм может быть очень легко модифицирован, чтобы создать алгоритм сортировки, который сортирует в O (n + k) время и O (k) пробел)

Ответ 9

Примечания по оптимизации

Оба алгоритма сортировки hashset и radix можно оптимизировать, отметив три факта:

  • Нечетные и четные значения могут обрабатываться отдельно
  • Вычисление целочисленного квадратного корня – очень быстрая операция (обычно состоит из 3-5 разделов и нескольких добавлений).
  • Локальность кэша важна для обоих этих алгоритмов.

Оптимизированные алгоритмы ниже обычно выполняются в 5 раз быстрее и используют менее половины ОЗУ неоптимизированного случая. В некоторых случаях, когда размер данных аналогичен размеру кеша L2/L3, он может выполнять 100 раз быстрее или более.

Оптимизированный алгоритм, основанный на сортировке счисления

Структура данных – это пять списков целых чисел: IN, Aodd, Bodd, Aeven, Beven
В списках A и B используется половина целочисленного размера IN. (например, если IN = 64 бит, A и B = 32 бит)

  • Список сканирования IN, чтобы найти самые большие нечетные и четные числа MAXodd и MAXeven
  • Пусть LIMITodd = floor (sqrt (MAXodd))
  • Пусть LIMITeven = floor (sqrt (MAXeven))
  • Для каждого номера в списке IN: a. Вычислите квадратный корень, если положительный. Если это так, добавьте квадратный корень в список Aodd/Aeven. б. Если число >= 0 и <= LIMITodd/LIMITeven, добавьте его в список Bodd/Beven
  • Список сортировки Radix Aodd и Bodd, используя только биты log2 (LIMITodd)
  • Линейное сканирование Aodd и Bodd для соответствия
  • Список сортировки Radix Aeven и Beven, используя только бит log2 (LIMITeven)
  • Линейное сканирование Aeven и Beven для соответствия

Если любое линейное сканирование находит совпадение, немедленно возвращайте его.

Причина, по которой это происходит намного быстрее, чем простой алгоритм сортировки оснований, заключается в следующем:

  • Сортированные массивы типично имеют менее 1/4 числа значений и нуждаются только в половине числа бит на целое число, поэтому в общей сложности менее 1/8 используемая оперативная память в данном типе, которая хороша для кэш.
  • Сортировка radix выполняется на гораздо меньшем количестве бит, что приводит к меньшему количеству проходов, поэтому даже если оно превышает ваш кеш L1 или L2, вы читаете RAM меньше раз, и вы читаете гораздо меньше RAM
  • Линейное сканирование обычно происходит намного быстрее, поскольку список A содержит только точные квадратные корни, а список B содержит только небольшие значения

Оптимизированный алгоритм на основе hashset

Структура данных – это список целых чисел IN, плюс два хэш-набора A и B
Множества A и B используют половину целочисленного размера IN

  • Список сканирования IN, чтобы найти самые большие нечетные и четные числа MAXodd и MAXeven
  • Пусть LIMITodd = floor (sqrt (MAXodd))
  • Пусть LIMITeven = floor (sqrt (MAXeven))
  • Для каждого нечетного числа в списке IN: a. Вычислите квадратный корень, если положительный. Если это так, проверьте, существует ли в B квадратный корень и возвращается, если true, иначе добавьте его в A. b. Если число >= 0 и <= LIMITodd/LIMITeven, проверьте, существует ли он в и возвращает, если true в противном случае добавляет его в B.
  • Очистите A и B и повторите шаг 4 для четных чисел

Причина, по которой это быстрее, чем простой алгоритм хэширования, заключается в следующем:

  • Хешсет обычно составляет 1/8 объема оперативной памяти, что приводит к значительно лучшей производительности кеша
  • Только точные квадраты и маленькие числа имеют записи hashset, поэтому гораздо меньше времени тратится на хэширование и добавление/удаление значений

Существует небольшая небольшая оптимизация, доступная здесь: A и B могут быть одним хэш-множеством, который хранит бит-флаг с каждой записью, чтобы сказать, является ли целое число в или B (оно не может быть в обоих, потому что тогда алгоритм было бы прекращено).

Ответ 10

Если я правильно понимаю проблему, вам нужно проверить, указано ли указанное число в массиве. И не найти все числа в массиве, которые также имеют свой квадрат в массиве.
Просто поддерживайте два логических значения (один, чтобы проверить, было ли найдено число, другое для квадрата), итерации по элементам в массиве и проверка каждого элемента. Верните AND из двух булевых.

В псевдокоде:

bool ArrayContainsNumberAndSquare(int number, int[] array):
boolean numberFound, squareFound;
int square = number * number;
foreach int i in array
(
  numberFound = numberFound || i == number;
  squareFound = squareFound || i == square;
)
return numberFound && squareFound;

Ответ 11

1) С помощью hashmap вы получаете O (n).

2) Если вы используете std:: set на 2 наборах: evens и коэффициенты, вы можете получить

2 * О ((N/2) журнал (п/2)) = O (Nlog (п/2))

предполагая, что существует примерно столько же, сколько коэффициентов

Ответ 12

Если массив не отсортирован, вы не сможете выполнить O (n).

Если он отсортирован, вы можете использовать это свойство, чтобы сделать это за один проход, например:

foreach e in array
    if squares contains e
        return true
    remove all less than e from squares
    add e * e to squares
return false

Где squares есть, скажем, HashSet.

Если он не отсортирован, вы можете отсортировать его в O (n log n), а затем использовать этот метод для проверки квадратов, которые будут по-прежнему быстрее, чем наивное решение на достаточно большом наборе данных.

numpy

Square(arr, out = None, ufunc ‘square’): Эта математическая функция помогает пользователю вычислить квадратное значение каждого элемента в массиве. Параметры: arr: [array_like] Входной массив или объект, элементы которого нам нужно возвести в квадрат.

Вы можете получить квадратный корень из одного элемента массива с помощью функции numpy.sqrt().Вы также можете получить квадратные значения массива NumPy с помощью numpy.square().

Чтобы вернуть квадрат входного массива по элементам,используйте метод numpy.square()в Python.Метод возвращает квадрат x*x,имеющий ту же форму и dtype,что и x.

Добавить комментарий