Как найти подмассив в массиве python

How to find all the subarrays of a given array in the fastest possible way?
for eg:a=[1,2,3,4,5]
The purpose of question is to large array input and find all the possible saubarrays

  • python
  • arrays
  • python-3.x
  • arraylist

Willeke's user avatar

Willeke

14.4k4 gold badges19 silver badges47 bronze badges

asked Jun 1, 2018 at 17:31

user103485's user avatar

user103485user103485

131 gold badge2 silver badges4 bronze badges

1

  • Did Google say «zero results found» ?

    Jun 1, 2018 at 17:39

2 Answers

def sub_lists(my_list):
subs = [[]]
for sub in my_list:subs += [i + [sub] for i in subs]
return subs

answered Jun 1, 2018 at 17:34

Nandish Patel's user avatar

1

  • Lets say the input list is [5,7,1]. We don’t get [1,5] subarray in output

    Sep 3, 2021 at 18:00

answered Jun 1, 2018 at 17:34

Shen Huang's user avatar

I thought that in would be good for this but it returns true in places where it shouldn’t. For example:

import numpy as np

a = np.array([])

for i in range(3):
    for j in range(3):
        a = np.append(a,[i,j])
a = np.reshape(a,(9,2))
print(a)

print([[0,40]] in a)

will print true. I cannot understand why it does this… is it because 0 is in the list? I’d like to have something that only prints true if the entire array is in the list.

I want to have my list

[[0,1],
[0,2]]

and only return true if exactly [0,x] (same shape same order) is in it.

akilat90's user avatar

akilat90

5,3367 gold badges28 silver badges42 bronze badges

asked Jun 10, 2018 at 10:24

David's user avatar

2

You can do it this way:

([0, 40] == a).all(1).any()

The first step is to compute a 2D boolean array of where the matches are. Then you find the rows where all elements are true. Then you check if any rows are fully matching.

answered Jun 10, 2018 at 10:50

John Zwinck's user avatar

John ZwinckJohn Zwinck

237k37 gold badges319 silver badges433 bronze badges

This code can help you:

my_list = [0, 40]
print(all(b in a for b in my_list))

answered Jun 10, 2018 at 15:01

Amir Dezhkam's user avatar

You can use np.isin(a_array, b_array) ,it returned a boolean array.
for example:

import numpy as np
a_array =np.array([1,2,3,4])
b_array = np.array([3,4,5])
bool_a_b = np.isin(a_array, b_array)
print(bool_a_b)

Output:

[False False True True]

answered Jan 28, 2020 at 5:28

Katie's user avatar

KatieKatie

92 bronze badges

Добрый день, уважаемые!

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

Есть массив, например:

Arr = numpy.array([[1,2,3,4,5],
                   [5,6,7,8,9],
                   [9,0,0,0,2],
                   [6,5,4,3,2],
                   [3,4,2,3,2]])

Требуется найти, например:

Arr_small = numpy.array([[5,4,3],
                         [4,2,3]])

Пройтись циклом со срезами я могу, но когда массив большой (например 1000×500) — это очень долго
Возможно, есть какой-нибудь способ сделать это средствами numpy?
Нашел один вариант, который по-началу показался нормальным.
Преобразовать Arr в массив “окон” типа:

numpy.array([[[1,2,3],
              [5,6,7]],
             [[2,3,4],
              [6,7,8]],
             [[3,4,5],
              [7,8,9]],
               ...
             [[4,3,2],
              [2,3,2]]])

После этого преобразовать его в список (tolist) и затем найти индекс Arr.index(Arr_small) и дальше уже вычислить позицию. Но, как оказалось, загвоздка в tolist — эта операция оказалась, внезапно, еще медленней, чем поиск обычным циклом.
Возможно, можно реализовать через numpy.where, но я так и не понял как.
Подскажите, пожалуйста, как можно это реализовать.

Отредактировано jor77 (Авг. 7, 2015 10:36:54)

Дан целочисленный массив, выведите все подмассивы с нулевой суммой.

Например,

Input:  { 4, 2, -3, -1, 0, 4 }

 
Subarrays with zero-sum are

 
{ -3, -1, 0, 4 }
{ 0 }

 
 
Input:  { 3, 4, -7, 3, 1, 3, 1, -4, -2, -2 }

 
Subarrays with zero-sum are

 
{ 3, 4, -7 }
{ 4, -7, 3 }
{ -7, 3, 1, 3 }
{ 3, 1, -4 }
{ 3, 1, 3, 1, -4, -2, -2 }
{ 3, 4, -7, 3, 1, 3, 1, -4, -2, -2 }

Обратите внимание, что проблема касается подмассивы которые являются непрерывными, т. е. элементы которых занимают последовательные позиции в массиве.

Потренируйтесь в этой проблеме

Подход 1: Использование грубой силы

Наивное решение состоит в том, чтобы рассмотреть все подмассивы и найти их сумму. Если сумма подмассива равна 0, выведите ее. Временная сложность наивного решения равна O(n3) как есть n2 подмассивы в массиве размером n, и это занимает O(n) времени, чтобы найти сумму его элементов. Мы можем оптимизировать метод для запуска O(n2) время путем вычисления суммы подмассива за постоянное время.

Ниже приведена реализация на C++, Java и Python, основанная на приведенной выше идее:

C++

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

#include <iostream>

#include <unordered_map>

using namespace std;

// Функция для печати всех подмассивов с нулевой суммой

// в заданном массиве

void printAllSubarrays(int nums[], int n)

{

    // учитываем все подмассивы, начиная с `i`

    for (int i = 0; i < n; i++)

    {

        int sum = 0;

        // учитываем все подмассивы, заканчивающиеся на `j`

        for (int j = i; j < n; j++)

        {

            // сумма элементов на данный момент

            sum += nums[j];

            // если сумма была видна раньше, значит, мы нашли подмассив

            // с нулевой суммой

            if (sum == 0) {

                cout << «Subarray [« << i << «…» << j << «]n»;

            }

        }

    }

}

int main()

{

    int nums[] = { 3, 4, 7, 3, 1, 3, 1, 4, 2, 2 };

    int n = sizeof(nums)/sizeof(nums[0]);

    printAllSubarrays(nums, n);

    return 0;

}

Скачать  Выполнить код

результат:

Subarray [0…2]
Subarray [0…9]
Subarray [1…3]
Subarray [2…5]
Subarray [3…9]
Subarray [5…7]

Java

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

class Main

{

    // Функция для печати всех подмассивов с нулевой суммой

    // в заданном массиве

    public static void printAllSubarrays(int[] nums)

    {

        // учитываем все подмассивы, начиная с `i`

        for (int i = 0; i < nums.length; i++)

        {

            int sum = 0;

            // учитываем все подмассивы, заканчивающиеся на `j`

            for (int j = i; j < nums.length; j++)

            {

                // сумма элементов на данный момент

                sum += nums[j];

                // если сумма встречалась раньше, то мы нашли подмассив с нулевой суммой

                if (sum == 0) {

                    System.out.println(«Subarray [« + i + «…» + j + «]»);

                }

            }

        }

    }

    public static void main (String[] args)

    {

        int[] nums = { 3, 4, 7, 3, 1, 3, 1, 4, 2, 2 };

        printAllSubarrays(nums);

    }

}

Скачать  Выполнить код

результат:

Subarray [0…2]
Subarray [0…9]
Subarray [1…3]
Subarray [2…5]
Subarray [3…9]
Subarray [5…7]

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

# Функция для печати всех подсписков с нулевой суммой, присутствующих в данном списке.

def printAllSublists(nums):

    # рассматривает все подсписки, начинающиеся с `i`

    for i in range(len(nums)):

        total = 0

        # рассматривает все подсписки, оканчивающиеся на `j`

        for j in range(i, len(nums)):

            # сумма элементов на данный момент

            total += nums[j]

            #, если сумма видна раньше, мы нашли подсписок с нулевой суммой

            if total == 0:

                print(‘Sublist’, (i, j))

if __name__ == ‘__main__’:

    nums = [3, 4, 7, 3, 1, 3, 1, 4, 2, 2]

    printAllSublists(nums)

Скачать  Выполнить код

результат:

Sublist (0, 2)
Sublist (0, 9)
Sublist (1, 3)
Sublist (2, 5)
Sublist (3, 9)
Sublist (5, 7)

Подход 2: использование multimap для печати всех подмассивов

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

Алгоритм может быть реализован следующим образом на C++, Java и Python:

C++

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

#include <iostream>

#include <unordered_map>

using namespace std;

// Функция для печати всех подмассивов с нулевой суммой в заданном массиве

void printAllSubarrays(int nums[], int n)

{

    // создаем пустую multimap для хранения конечного индекса всех

    // подмассивы, имеющие одинаковую сумму

    unordered_multimap<int, int> map;

    // вставить пару (0, -1) в карту, чтобы обработать случай, когда

    // подмассив с нулевой суммой начинается с индекса 0

    map.insert(pair<int, int>(0, 1));

    int sum = 0;

    // обход заданного массива

    for (int i = 0; i < n; i++)

    {

        // сумма элементов на данный момент

        sum += nums[i];

        // если сумма видна раньше, то существует хотя бы одна

        // подмассив с нулевой суммой

        if (map.find(sum) != map.end())

        {

            auto it = map.find(sum);

            // найти все подмассивы с одинаковой суммой

            while (it != map.end() && it->first == sum)

            {

                cout << «Subarray [« << it->second + 1 << «…» << i << «]n»;

                it++;

            }

        }

        // вставляем пару (на данный момент, текущий индекс) в multimap

        map.insert(pair<int, int>(sum, i));

    }

}

int main()

{

    int nums[] = { 3, 4, 7, 3, 1, 3, 1, 4, 2, 2 };

    int n = sizeof(nums)/sizeof(nums[0]);

    printAllSubarrays(nums, n);

    return 0;

}

Скачать  Выполнить код

результат:

Subarray [0…2]
Subarray [1…3]
Subarray [2…5]
Subarray [5…7]
Subarray [3…9]
Subarray [0…9]

Java

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

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

class Main

{

    // Вспомогательная функция для вставки <key, value> в multimap

    private static<K, V> void insert(Map<K, List<V>> hashMap, K key, V value)

    {

        // если ключ виден в первый раз, инициализируем список

        hashMap.putIfAbsent(key, new ArrayList<>());

        hashMap.get(key).add(value);

    }

    // Функция для печати всех подмассивов с нулевой суммой в заданном массиве

    public static void printAllSubarrays(int[] nums)

    {

        // создаем пустую multimap для хранения конечного индекса всех

        // подмассивы, имеющие одинаковую сумму

        Map<Integer, List<Integer>> hashMap = new HashMap<>();

        // вставить пару (0, -1) в карту, чтобы обработать случай, когда

        // подмассив с нулевой суммой начинается с индекса 0

        insert(hashMap, 0, 1);

        int sum = 0;

        // обход заданного массива

        for (int i = 0; i < nums.length; i++)

        {

            // сумма элементов на данный момент

            sum += nums[i];

            // если сумма видна раньше, то существует хотя бы одна

            // подмассив с нулевой суммой

            if (hashMap.containsKey(sum))

            {

                List<Integer> list = hashMap.get(sum);

                // найти все подмассивы с одинаковой суммой

                for (Integer value: list)

                {

                    System.out.println(«Subarray [« + (value + 1) + «…» +

                                            i + «]»);

                }

            }

            // вставляем пару (на данный момент, текущий индекс) в multimap

            insert(hashMap, sum, i);

        }

    }

    public static void main (String[] args)

    {

        int[] nums = { 3, 4, 7, 3, 1, 3, 1, 4, 2, 2 };

        printAllSubarrays(nums);

    }

}

Скачать  Выполнить код

результат:

Subarray [0…2]
Subarray [1…3]
Subarray [2…5]
Subarray [5…7]
Subarray [3…9]
Subarray [0…9]

Python

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

# Вспомогательная функция для вставки <key, value> в словарь

def insert(d, key, value):

    #, если ключ виден впервые, инициализировать список

    d.setdefault(key, []).append(value)

# Функция для печати всех подсписков с нулевой суммой, присутствующих в данном списке.

def printallSublists(nums):

    # создает пустой словарь для хранения конечного индекса всех

    # Подсписки # с одинаковой суммой

    d = {}

    # вставить пару (0, -1) в словарь, чтобы обработать случай, когда

    # Подсписок # с нулевой суммой начинается с индекса 0

    insert(d, 0, 1)

    total = 0

    # пройти по заданному списку

    for i in range(len(nums)):

        # сумма элементов на данный момент

        total += nums[i]

        #, если сумма видна раньше, существует хотя бы один

        # Подсписок # с нулевой суммой

        if total in d:

            list = d.get(total)

            # найти все подсписки с одинаковой суммой

            for value in list:

                print(‘Sublist is’, (value + 1, i))

        # вставить пару (сумма, текущий индекс) в словарь

        insert(d, total, i)

if __name__ == ‘__main__’:

    nums = [3, 4, 7, 3, 1, 3, 1, 4, 2, 2]

    printallSublists(nums)

Скачать  Выполнить код

результат:

Sublist is (0, 2)
Sublist is (1, 3)
Sublist is (2, 5)
Sublist is (5, 7)
Sublist is (0, 9)
Sublist is (3, 9)

Упражнение: Расширьте решение для ненулевой суммы подмассива

 
Связанный пост:

Проверьте, существует ли подмассив с суммой 0 или нет

Автор оригинала: Olivera Popović.

Вступление

В этой статье мы погрузимся в идею и реализацию Python Binary Search .

Бинарный поиск-это эффективный алгоритм поиска, который работает с отсортированными массивами. Он часто используется как один из первых примеров алгоритмов, работающих в логарифмическом времени ( O(logn) ) из-за его интуитивного поведения и является фундаментальным алгоритмом в информатике.

Бинарный поиск – Пример

Бинарный поиск работает по принципу “разделяй и властвуй” и опирается на то, что массив сортируется так, чтобы исключить половину возможных кандидатов на каждой итерации. Более конкретно, он сравнивает средний элемент отсортированного массива с элементом, который он ищет, чтобы решить, где продолжить поиск.

Если целевой элемент больше среднего элемента – он не может быть расположен в первой половине коллекции, поэтому он отбрасывается. То же самое происходит и наоборот.

Примечание: Если массив имеет четное число элементов, то не имеет значения, с какого из двух “средних” элементов мы начнем.

Давайте быстро рассмотрим пример, прежде чем мы продолжим объяснять, как работает бинарный поиск:

бинарный поиск в визуализации python

Как мы видим, мы точно знаем, что, поскольку массив отсортирован, x не находится в первой половине исходного массива.

Когда мы знаем, в какой половине исходного массива находится x , мы можем повторить этот точный процесс с этой половиной и снова разделить ее на половинки, отбросив половину, которая наверняка не содержит x :

бинарный поиск в визуализации python

Мы повторяем этот процесс до тех пор, пока не получим подмассив, содержащий только один элемент. Мы проверяем, является ли этот элемент x . Если это так – мы нашли x , если это не так – x вообще не существует в массиве.

Если вы присмотритесь к этому поближе, то заметите, что в худшем случае ( x не существует в массиве) нам нужно проверить гораздо меньшее количество элементов , чем в несортированном массиве, что потребует чего-то большего в духе Линейного поиска , что безумно неэффективно.

Если быть более точным, то количество элементов, которые нам нужно проверить в худшем случае, равно log 2 N где N – количество элементов в массиве.

Это оказывает тем большее влияние, чем больше массив:

Если бы наш массив состоял из 10 элементов, нам нужно было бы проверить только 3 элемента, чтобы либо найти x , либо сделать вывод, что его там нет. Это 33,3%.

Однако, если бы в нашем массиве было 10 000 000 элементов, нам нужно было бы проверить только 24 элемента. Это 0,0002%.

Реализация Бинарного Поиска

Двоичный поиск-это естественно рекурсивный алгоритм, поскольку один и тот же процесс повторяется на все меньших и меньших массивах до тех пор, пока не будет найден массив размером 1. Однако, конечно, существует и итеративная реализация, и мы покажем оба подхода.

Рекурсивный

Давайте начнем с рекурсивной реализации, так как это более естественно:

def binary_search_recursive(array, element, start, end):
    if start > end:
        return -1

    mid = (start + end) // 2
    if element == array[mid]:
        return mid

    if element < array[mid]:
        return binary_search_recursive(array, element, start, mid-1)
    else:
        return binary_search_recursive(array, element, mid+1, end)

Давайте подробнее рассмотрим этот код. Мы выходим из рекурсии, если элемент start выше элемента end :

if start > end:
        return -1

Это происходит потому, что такая ситуация возникает только тогда, когда элемент не существует в массиве. В результате мы получаем только один элемент в текущем суб-массиве, и этот элемент не совпадает с тем, который мы ищем.

В этот момент start равно end . Однако, поскольку element не равен array[mid] , мы снова “разбиваем” массив таким образом, что либо уменьшаем end на 1, либо увеличиваем start на единицу, и рекурсия существует при этом условии.

Мы могли бы сделать это, используя другой подход:

if len(array) == 1:
    if element == array[mid]:
        return mid
    else:
        return -1

Остальная часть кода выполняет логику “проверить средний элемент, продолжить поиск в соответствующей половине массива”. Мы находим индекс среднего элемента и проверяем, соответствует ли ему искомый элемент:

mid = (start + end) // 2
if elem == array[mid]:
    return mid

Если это не так, мы проверяем, является ли элемент меньше или больше среднего элемента:

if element < array[mid]:
    # Continue the search in the left half
    return binary_search_recursive(array, element, start, mid-1)
else:
    # Continue the search in the right half
    return binary_search_recursive(array, element, mid+1, end)

Давайте продолжим и запустим этот алгоритм с небольшой модификацией, чтобы он распечатал, над каким подмассивом он работает в данный момент:

element = 18
array = [1, 2, 5, 7, 13, 15, 16, 18, 24, 28, 29]

print("Searching for {}".format(element))
print("Index of {}: {}".format(element, binary_search_recursive(array, element, 0, len(array))))

Запуск этого кода приведет к:

Searching for 18
Subarray in step 0:[1, 2, 5, 7, 13, 15, 16, 18, 24, 28, 29]
Subarray in step 1:[16, 18, 24, 28, 29]
Subarray in step 2:[16, 18]
Subarray in step 3:[18]
Index of 18: 7

Ясно видеть, как он сокращает пространство поиска в каждой итерации, приближаясь все ближе и ближе к искомому элементу. Если бы мы попытались найти элемент, который не существует в массиве, результат был бы следующим:

Searching for 20
Subarray in step 0: [4, 14, 16, 17, 19, 21, 24, 28, 30, 35, 36, 38, 39, 40, 41, 43]
Subarray in step 1: [4, 14, 16, 17, 19, 21, 24, 28]
Subarray in step 2: [19, 21, 24, 28]
Subarray in step 3: [19]
Index of 20: -1

И просто для удовольствия мы можем попробовать поискать некоторые большие массивы и посмотреть, сколько шагов требуется двоичному поиску, чтобы выяснить, существует ли число:

Searching for 421, in an array with 200 elements
Search finished in 6 steps. Index of 421: 169

Searching for 1800, in an array with 1500 elements
Search finished in 11 steps. Index of 1800: -1

Searching for 3101, in an array with 3000 elements
Search finished in 8 steps. Index of 3101: 1551

Повторяющийся

Итеративный подход очень прост и похож на рекурсивный. Здесь мы просто выполняем проверки в цикле while :

def binary_search_iterative(array, element):
    mid = 0
    start = 0
    end = len(array)
    step = 0

    while (start <= end):
        print("Subarray in step {}: {}".format(step, str(array[start:end+1])))
        step = step+1
        mid = (start + end) // 2

        if element == array[mid]:
            return mid

        if element < array[mid]:
            end = mid - 1
        else:
            start = mid + 1
    return -1

Давайте заполняем массив и ищем в нем элемент:

array = [1, 2, 5, 7, 13, 15, 16, 18, 24, 28, 29]       

print("Searching for {} in {}".format(element, array))
print("Index of {}: {}".format(element, binary_search_iterative(array, element)))

Запуск этого кода дает нам результат:

Searching for 18 in [1, 2, 5, 7, 13, 15, 16, 18, 24, 28, 29]
Subarray in step 0: [1, 2, 5, 7, 13, 15, 16, 18, 24, 28, 29]
Subarray in step 1: [16, 18, 24, 28, 29]
Subarray in step 2: [16, 18]
Subarray in step 3: [18]
Index of 18: 7

Вывод

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

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

Если мы сортируем массив и ищем элемент только один раз, то более эффективно просто выполнить линейный поиск по несортированному массиву.

Если вы хотите прочитать об алгоритмах сортировки в Python , мы вас накроем!

Понравилась статья? Поделить с друзьями:
  • Как найти сумму амортизационных отчислений за месяц
  • Как найти кладовщика в сталкер онлайн
  • Ошибка е16 антирадар ibox как исправить
  • Как найти участников в рок группу
  • Как найти трек не зная его названия