<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=108.90.89.36&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=108.90.89.36&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/108.90.89.36"/>
		<updated>2026-05-21T00:18:21Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%B2_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D0%B5&amp;diff=75101</id>
		<title>Поиск в матрице</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%B2_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D0%B5&amp;diff=75101"/>
				<updated>2020-10-27T21:16:04Z</updated>
		
		<summary type="html">&lt;p&gt;108.90.89.36: /* Код */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Задана отсортированная двумерная матрица (матрица, для которой выполнено следующее условие: &amp;lt;tex&amp;gt; a[row][col] \leqslant a[row + 1][col], a[row][col] \leqslant a[row][col + 1] &amp;lt;/tex&amp;gt; ), состоящая из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; строк и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; столбцов. Необходимо найти расположение указанного элемента в матрице или определить, что данный элемент в матрице отсутствует. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:sorted_matrix_example.png|320px|thumb|right|Пример отсортированной матрицы]]&lt;br /&gt;
&lt;br /&gt;
== Решение за O(n&amp;lt;tex&amp;gt;\cdot&amp;lt;/tex&amp;gt;m) ==&lt;br /&gt;
Для начала рассмотрим наивный алгоритм поиска элемента. В каждой строке исходной матрицы запускаем линейный поиск, если находим элемент, то возвращаем его координаты &amp;lt;tex&amp;gt;(row, col)&amp;lt;/tex&amp;gt;. Время работы — &amp;lt;tex&amp;gt;O(n \cdot m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Решение за O(n&amp;lt;tex&amp;gt;\cdot&amp;lt;/tex&amp;gt;log(m)) ==&lt;br /&gt;
Данный способ решения использует наивное решение за &amp;lt;math&amp;gt;n \cdot m&amp;lt;/math&amp;gt;, улучшенное с помощью [[Целочисленный двоичный поиск|двоичного поиска]]. Для этого в каждой строке запускается двоичный поиск. Время работы — &amp;lt;tex&amp;gt;O(n \cdot \log(m))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Замечание'''&lt;br /&gt;
&lt;br /&gt;
Время работы может быть улучшено до &amp;lt;tex&amp;gt;O(\min(n, m) \cdot \log(\max(n \cdot m))&amp;lt;/tex&amp;gt;. Для этого необходимо модифицировать алгоритм так, чтобы в том случае, если столбцов больше чем строк, он бы запускал двоичный поиск по строкам, если строк больше — наоборот.&lt;br /&gt;
&lt;br /&gt;
Существует еще один способ оптимизации. Рассмотрим случай, когда используется двоичный поиск по строке. Достаточно очевидно, что искомое число может находится только в тех строках, где первый элемент меньше искомого, а последний — больше. Перед началом поиска можно исключить два прямоугольных участка матрицы: первый состоит из строк, у которых последний элемент меньше искомого; второй состоит из строк, у которых первый элемент больше искомого. Используя двоичный поиск, можно найти границы этих участков за &amp;lt;tex&amp;gt;O(\log(n))&amp;lt;/tex&amp;gt; для столбцов и за &amp;lt;tex&amp;gt;O(\log(m))&amp;lt;/tex&amp;gt; строк.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Файл:find13.png|320px|thumb|right|Пример поиска числа 13 в матрице]]&lt;br /&gt;
&lt;br /&gt;
== Решение за O(n + m) ==&lt;br /&gt;
В данном решении мы начинаем поиск из правого верхнего угла и движемся к искомому элементу. Идея алгоритма в том, что если текущий элемент меньше необходимого, то мы сдвигаемся на одну строку вниз. Если он больше, то мы сдвигаемся на одну колонку влево.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
Докажем, что каждый ход в соседнюю ячейку отсекает только те столбцы или строки, которые точно не содержат искомый элемент. Назовем ход корректным, если он отсекает только те строки или колонки, в которых точно нет искомого элемента. Пусть первый ход (в правую верхнюю ячейку) корректный (он не отсек ни одной строки или столбца). &lt;br /&gt;
&lt;br /&gt;
Пусть предыдущий ход был корректным. Докажем, что следующий ход, выполненный по правилам, будет корректным.&lt;br /&gt;
Если текущий элемент меньше искомого, то все ячейки левее и выше меньше, чем искомый (по определению отсортированной матрицы, все элементы левее в строке меньше текущего, а текущий меньше искомого).&lt;br /&gt;
Если текущий элемент больше искомого, то очевидно, что все ячейки правее и ниже больше, чем искомый (по определению отсортированной матрицы, все элементы ниже в столбце больше текущего, а текущий больше искомого). Значит, их можно отсечь.&lt;br /&gt;
&lt;br /&gt;
В определенный момент времени алгоритм либо найдет ячейку с искомым элементом (значит, элемент найден), либо в матрице не останется тех элементов, которые не были отсечены (значит, элемента в матрице нет).&lt;br /&gt;
&lt;br /&gt;
=== Код ===&lt;br /&gt;
  '''Pair'''&amp;lt;'''int''', '''int'''&amp;gt; matrixFind('''int'''[N][M] a, '''int''' target):&lt;br /&gt;
    '''if''' (target &amp;lt; a[0][0] '''or''' target &amp;gt; a[N-1][M-1]) &lt;br /&gt;
      '''return''' (-1, -1)&lt;br /&gt;
    row = 0&lt;br /&gt;
    col = M - 1&lt;br /&gt;
    '''while''' (row &amp;lt;= N-1 '''and''' col &amp;gt;= 0) &lt;br /&gt;
      '''if''' (a[row][col] &amp;lt; target) &lt;br /&gt;
        row++&lt;br /&gt;
      '''else if''' (a[row][col] &amp;gt; target)&lt;br /&gt;
        col--&lt;br /&gt;
      '''else'''&lt;br /&gt;
        '''return''' (row, col)&lt;br /&gt;
    '''return''' (-1, -1)&lt;br /&gt;
&lt;br /&gt;
===Оценка времени работы===&lt;br /&gt;
&lt;br /&gt;
Очевидно, что во время работы указатель сдвигается максимум на &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; строк и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; столбцов. В этом случае время работы составляет &amp;lt;tex&amp;gt;O(n + m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Целочисленный_двоичный_поиск|Целочисленный двоичный поиск]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://articles.leetcode.com/2010/10/searching-2d-sorted-matrix.html| Searching a 2D Sorted Matrix часть 1 на Leetcode]&lt;br /&gt;
* [http://articles.leetcode.com/2010/10/searching-2d-sorted-matrix-part-ii.html| Searching a 2D Sorted Matrix часть 2 на Leetcode]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Алгоритмы поиска]]&lt;/div&gt;</summary>
		<author><name>108.90.89.36</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%B2_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D0%B5&amp;diff=75100</id>
		<title>Поиск в матрице</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%B2_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D0%B5&amp;diff=75100"/>
				<updated>2020-10-27T21:14:24Z</updated>
		
		<summary type="html">&lt;p&gt;108.90.89.36: /* Код */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Задана отсортированная двумерная матрица (матрица, для которой выполнено следующее условие: &amp;lt;tex&amp;gt; a[row][col] \leqslant a[row + 1][col], a[row][col] \leqslant a[row][col + 1] &amp;lt;/tex&amp;gt; ), состоящая из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; строк и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; столбцов. Необходимо найти расположение указанного элемента в матрице или определить, что данный элемент в матрице отсутствует. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:sorted_matrix_example.png|320px|thumb|right|Пример отсортированной матрицы]]&lt;br /&gt;
&lt;br /&gt;
== Решение за O(n&amp;lt;tex&amp;gt;\cdot&amp;lt;/tex&amp;gt;m) ==&lt;br /&gt;
Для начала рассмотрим наивный алгоритм поиска элемента. В каждой строке исходной матрицы запускаем линейный поиск, если находим элемент, то возвращаем его координаты &amp;lt;tex&amp;gt;(row, col)&amp;lt;/tex&amp;gt;. Время работы — &amp;lt;tex&amp;gt;O(n \cdot m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Решение за O(n&amp;lt;tex&amp;gt;\cdot&amp;lt;/tex&amp;gt;log(m)) ==&lt;br /&gt;
Данный способ решения использует наивное решение за &amp;lt;math&amp;gt;n \cdot m&amp;lt;/math&amp;gt;, улучшенное с помощью [[Целочисленный двоичный поиск|двоичного поиска]]. Для этого в каждой строке запускается двоичный поиск. Время работы — &amp;lt;tex&amp;gt;O(n \cdot \log(m))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Замечание'''&lt;br /&gt;
&lt;br /&gt;
Время работы может быть улучшено до &amp;lt;tex&amp;gt;O(\min(n, m) \cdot \log(\max(n \cdot m))&amp;lt;/tex&amp;gt;. Для этого необходимо модифицировать алгоритм так, чтобы в том случае, если столбцов больше чем строк, он бы запускал двоичный поиск по строкам, если строк больше — наоборот.&lt;br /&gt;
&lt;br /&gt;
Существует еще один способ оптимизации. Рассмотрим случай, когда используется двоичный поиск по строке. Достаточно очевидно, что искомое число может находится только в тех строках, где первый элемент меньше искомого, а последний — больше. Перед началом поиска можно исключить два прямоугольных участка матрицы: первый состоит из строк, у которых последний элемент меньше искомого; второй состоит из строк, у которых первый элемент больше искомого. Используя двоичный поиск, можно найти границы этих участков за &amp;lt;tex&amp;gt;O(\log(n))&amp;lt;/tex&amp;gt; для столбцов и за &amp;lt;tex&amp;gt;O(\log(m))&amp;lt;/tex&amp;gt; строк.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Файл:find13.png|320px|thumb|right|Пример поиска числа 13 в матрице]]&lt;br /&gt;
&lt;br /&gt;
== Решение за O(n + m) ==&lt;br /&gt;
В данном решении мы начинаем поиск из правого верхнего угла и движемся к искомому элементу. Идея алгоритма в том, что если текущий элемент меньше необходимого, то мы сдвигаемся на одну строку вниз. Если он больше, то мы сдвигаемся на одну колонку влево.&lt;br /&gt;
&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
&lt;br /&gt;
Докажем, что каждый ход в соседнюю ячейку отсекает только те столбцы или строки, которые точно не содержат искомый элемент. Назовем ход корректным, если он отсекает только те строки или колонки, в которых точно нет искомого элемента. Пусть первый ход (в правую верхнюю ячейку) корректный (он не отсек ни одной строки или столбца). &lt;br /&gt;
&lt;br /&gt;
Пусть предыдущий ход был корректным. Докажем, что следующий ход, выполненный по правилам, будет корректным.&lt;br /&gt;
Если текущий элемент меньше искомого, то все ячейки левее и выше меньше, чем искомый (по определению отсортированной матрицы, все элементы левее в строке меньше текущего, а текущий меньше искомого).&lt;br /&gt;
Если текущий элемент больше искомого, то очевидно, что все ячейки правее и ниже больше, чем искомый (по определению отсортированной матрицы, все элементы ниже в столбце больше текущего, а текущий больше искомого). Значит, их можно отсечь.&lt;br /&gt;
&lt;br /&gt;
В определенный момент времени алгоритм либо найдет ячейку с искомым элементом (значит, элемент найден), либо в матрице не останется тех элементов, которые не были отсечены (значит, элемента в матрице нет).&lt;br /&gt;
&lt;br /&gt;
=== Код ===&lt;br /&gt;
  '''Pair'''&amp;lt;'''int''', '''int'''&amp;gt; matrixFind('''int'''[N][M] a, '''int''' target):&lt;br /&gt;
    '''if''' (target &amp;lt; a[0][0] '''or''' target &amp;gt; a[N-1][M-1]) &lt;br /&gt;
      '''return''' (-1, -1)&lt;br /&gt;
    row = 0&lt;br /&gt;
    col = N - 1&lt;br /&gt;
    '''while''' (row &amp;lt;= N-1 '''and''' col &amp;gt;= 0) &lt;br /&gt;
      '''if''' (a[row][col] &amp;lt; target) &lt;br /&gt;
        row++&lt;br /&gt;
      '''else if''' (a[row][col] &amp;gt; target)&lt;br /&gt;
        col--&lt;br /&gt;
      '''else'''&lt;br /&gt;
        '''return''' (row, col)&lt;br /&gt;
    '''return''' (-1, -1)&lt;br /&gt;
&lt;br /&gt;
===Оценка времени работы===&lt;br /&gt;
&lt;br /&gt;
Очевидно, что во время работы указатель сдвигается максимум на &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; строк и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; столбцов. В этом случае время работы составляет &amp;lt;tex&amp;gt;O(n + m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Целочисленный_двоичный_поиск|Целочисленный двоичный поиск]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://articles.leetcode.com/2010/10/searching-2d-sorted-matrix.html| Searching a 2D Sorted Matrix часть 1 на Leetcode]&lt;br /&gt;
* [http://articles.leetcode.com/2010/10/searching-2d-sorted-matrix-part-ii.html| Searching a 2D Sorted Matrix часть 2 на Leetcode]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Алгоритмы поиска]]&lt;/div&gt;</summary>
		<author><name>108.90.89.36</name></author>	</entry>

	</feed>