Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 15:45
Оценка: :))) :))
Условие задачи:
Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
число в этом массиве повторяется два раза. Найти это число за время O(N).

Реализация:
private static string separator = ";";
        static void Main(string[] args)
        {
            int[] result = GetIntArray(InputArray());
            PrintArray(result);
            Console.WriteLine(ff(result));
            Console.ReadLine();
        }
        private static string InputArray()
        {
            Console.WriteLine("Введите массив, содержащий только целые числа.");
            Console.WriteLine("После каждого числа ставьте разделитель '{0}'", separator);
            Console.WriteLine("Введите массив: ");
            return Console.In.ReadLine();
        }
        private static int[] GetIntArray(string insert)
        {
            string pattern = String.Format("{0}(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))", separator);
            string[] bufResult = Regex.Split(insert, pattern);
            int[] result = new int[bufResult.Length];
            for (int i = 0; i < bufResult.Length; i++)
            {
                result[i] = Int32.Parse(bufResult[i]);
            }
            return result;
        }
        private static void PrintArray(int[] array)
        {
            foreach(int i in array)
            {
                Console.WriteLine(i);
            }
        }
        private static int ff(int[] array)
        {
            int m = 1;
            int buf = 0;
            // общее количество сравнений (n-1)^2, где n - длина массива
            for (int i = 0; i < (array.Length - 1) * (array.Length - 1); i++)
            {
                // количество перестановок (n-1) = количеству сравнений array[0] и array[k], где k - числа от 1 до n (n - длина массива)
                for (int j = 1; j < array.Length; j++)
                {
                    if (array[0] == array[j])
                    {
                        buf = array[0];
                        goto result;
                    }
                }
                Swap(array, m);
                m++;
            }
        result:
        return buf;
        }
        private static void Swap(int[] array, int index)
        {
            int temp = array[index];
            array[index] = array[0];
            array[0] = temp;
        }


Есть ли какие-либо другие пути решения задачи? Без goto не вижу решения задачи, если использовать break, там где buf = array[0] , останавливается только цикл:

for (int j = 1; j < array.Length - 1; j++)


при этом работа цикла

for (int i = 0; i < (array.Length - 1) * (array.Length - 1); i++)


не прерывается

Заранее спасибо!

01.04.10 22:00: Перенесено из '.NET'
С уважением!
Re: Поиск повторяющегося числа в массиве
От: nerozero  
Дата: 01.04.10 16:02
Оценка: 1 (1)
Здравствуйте, Xobotik, Вы писали:
goto result; заменить на return buf; ?
Re[2]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 16:12
Оценка:
Здравствуйте, nerozero, Вы писали:

N>Здравствуйте, Xobotik, Вы писали:

N>goto result; заменить на return buf; ?

блин точно) а есть ли какой-нибудь другой подход не по такой логике.
С уважением!
Re[3]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 16:15
Оценка: 1 (1)
Здравствуйте, Xobotik, Вы писали:

X>блин точно) а есть ли какой-нибудь другой подход не по такой логике.


Есть.
А самому не интересно найти?
Re[4]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 16:17
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>блин точно) а есть ли какой-нибудь другой подход не по такой логике.


S>Есть.

S>А самому не интересно найти?

Интересно=)
С уважением!
Re[4]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 16:26
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>блин точно) а есть ли какой-нибудь другой подход не по такой логике.


S>Есть.

S>А самому не интересно найти?

Есть лучше?)
С уважением!
Re: Поиск повторяющегося числа в массиве
От: Pavel Dvorkin Россия  
Дата: 01.04.10 16:29
Оценка: 1 (1)
Здравствуйте, Xobotik, Вы писали:

X>Найти это число за время O(N).


X> // общее количество сравнений (n-1)^2, где n — длина массива
With best regards
Pavel Dvorkin
Re[2]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 16:30
Оценка: :)
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Xobotik, Вы писали:


X>>Найти это число за время O(N).


X>> // общее количество сравнений (n-1)^2, где n — длина массива


А разве O((n-1)^2) ~ O(n)?
С уважением!
Re[4]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 16:31
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>блин точно) а есть ли какой-нибудь другой подход не по такой логике.


S>Есть.

S>А самому не интересно найти?

Можете сказать хоть куда копать? Голова забита только этим методом.
С уважением!
Re[5]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 16:32
Оценка: 2 (2) +1
Здравствуйте, Xobotik, Вы писали:

X>Можете сказать хоть куда копать? Голова забита только этим методом.


Нужно копать в сторону удовлетворения требования O(N)

Если скажу больше, то будет неинтересно
Re[3]: Поиск повторяющегося числа в массиве
От: Pavel Dvorkin Россия  
Дата: 01.04.10 16:33
Оценка: 5 (2) +1
Здравствуйте, Xobotik, Вы писали:

X>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Здравствуйте, Xobotik, Вы писали:


X>>>Найти это число за время O(N).


X>>> // общее количество сравнений (n-1)^2, где n — длина массива


X>А разве O((n-1)^2) ~ O(n)?


Нет

O((n-1)^2) ~ O(n^2)
With best regards
Pavel Dvorkin
Re: Поиск повторяющегося числа в массиве
От: elmal  
Дата: 01.04.10 16:42
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Есть ли какие-либо другие пути решения задачи?

Эээ, а что, итерация по массиву, занесение результата в HashSet (не знаю как аналог в .NET называется) и выход, если результат уже заносили — не прокатит за решение? Обязательно извращаться?
Re[6]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 16:43
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>Можете сказать хоть куда копать? Голова забита только этим методом.


S>Нужно копать в сторону удовлетворения требования O(N)


S>Если скажу больше, то будет неинтересно



        private static int fff(int[] array)
        {
            int buf = 0;
            for (int i = 0; i < array.Length; i++)
            {
                if (array[i] == array[i+1])
                {
                    continue;
                }
                else
                {
                    buf = array[i];
                    return buf;
                }
            }
            return buf;
        }


Удовлетворяет условию O(N)?
С уважением!
Re: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 16:44
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

X>Реализация:

X>
X>private static string separator = ";";
X>        static void Main(string[] args)
X>        {
X>            int[] result = GetIntArray(InputArray());
X>            PrintArray(result);
X>            Console.WriteLine(ff(result));
X>            Console.ReadLine();
X>        }
X>        private static string InputArray()
X>        {
X>            Console.WriteLine("Введите массив, содержащий только целые числа.");
X>            Console.WriteLine("После каждого числа ставьте разделитель '{0}'", separator);
X>            Console.WriteLine("Введите массив: ");
X>            return Console.In.ReadLine();
X>        }
X>        private static int[] GetIntArray(string insert)
X>        {
X>            string pattern = String.Format("{0}(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))", separator);
X>            string[] bufResult = Regex.Split(insert, pattern);
X>            int[] result = new int[bufResult.Length];
X>            for (int i = 0; i < bufResult.Length; i++)
X>            {
X>                result[i] = Int32.Parse(bufResult[i]);
X>            }
X>            return result;
X>        }
X>        private static void PrintArray(int[] array)
X>        {
X>            foreach(int i in array)
X>            {
X>                Console.WriteLine(i);
X>            }
X>        }
X>        private static int ff(int[] array)
X>        {
X>            int m = 1;
X>            int buf = 0;
X>            // общее количество сравнений (n-1)^2, где n - длина массива
X>            for (int i = 0; i < (array.Length - 1) * (array.Length - 1); i++)
X>            {
X>                // количество перестановок (n-1) = количеству сравнений array[0] и array[k], где k - числа от 1 до n (n - длина массива)
X>                for (int j = 1; j < array.Length; j++)
X>                {
X>                    if (array[0] == array[j])
X>                    {
X>                        buf = array[0];
X>                        goto result;
X>                    }
X>                }
X>                Swap(array, m);
X>                m++;
X>            }
X>        result:
X>        return buf;
X>        }
X>        private static void Swap(int[] array, int index)
X>        {
X>            int temp = array[index];
X>            array[index] = array[0];
X>            array[0] = temp;
X>        }
X>


X>Есть ли какие-либо другие пути решения задачи? Без goto не вижу решения задачи, если использовать break, там где buf = array[0] , останавливается только цикл:


X>
X>for (int j = 1; j < array.Length - 1; j++)
X>


X>при этом работа цикла


X>
X>for (int i = 0; i < (array.Length - 1) * (array.Length - 1); i++)
X>


X>не прерывается


X>Заранее спасибо!



        private static int fff(int[] array)
        {
            int buf = 0;
            for (int i = 0; i < array.Length; i++)
            {
                if (array[i] == array[i+1])
                {
                    continue;
                }
                else
                {
                    buf = array[i];
                    return buf;
                }
            }
            return buf;
        }


Так наверно правильнее
С уважением!
Re[2]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 16:45
Оценка:
Здравствуйте, elmal, Вы писали:

E>Здравствуйте, Xobotik, Вы писали:


X>>Есть ли какие-либо другие пути решения задачи?

E>Эээ, а что, итерация по массиву, занесение результата в HashSet (не знаю как аналог в .NET называется) и выход, если результат уже заносили — не прокатит за решение? Обязательно извращаться?

А это не O(N^2)?
С уважением!
Re[7]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 17:12
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>
X>        private static int fff(int[] array)
X>        {
X>            int buf = 0;
X>            for (int i = 0; i < array.Length; i++)
X>            {
X>                if (array[i] == array[i+1])
X>                {
X>                    continue;
X>                }
X>                else
X>                {
X>                    buf = array[i];
X>                    return buf;
X>                }
X>            }
X>            return buf;
X>        }
X>


X>Удовлетворяет условию O(N)?


Удовлетворяет O(N) но не решает задачу. Вернет первый элемент массива, который не дублируется следующим элементом массива. До конца массива не дойдет, вылетит по IndexOutOfRangeException.
Re[2]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 17:14
Оценка:
Здравствуйте, elmal, Вы писали:

E>Эээ, а что, итерация по массиву, занесение результата в HashSet (не знаю как аналог в .NET называется) и выход, если результат уже заносили — не прокатит за решение? Обязательно извращаться?


Полагаю, что автор задачи вряд ли рассчитывал увидеть в решении задачи по теме массивов HashSet.
Re[8]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 17:20
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>
X>>        private static int fff(int[] array)
X>>        {
X>>            int buf = 0;
X>>            for (int i = 0; i < array.Length; i++)
X>>            {
X>>                if (array[i] == array[i+1])
X>>                {
X>>                    continue;
X>>                }
X>>                else
X>>                {
X>>                    buf = array[i];
X>>                    return buf;
X>>                }
X>>            }
X>>            return buf;
X>>        }
X>>


X>>Удовлетворяет условию O(N)?


S>Удовлетворяет O(N) но не решает задачу. Вернет первый элемент массива, который не дублируется следующим элементом массива. До конца массива не дойдет, вылетит по IndexOutOfRangeException.


Ну то есть получается надо решить задачу используя только один цикл.
С уважением!
Re[9]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 17:31
Оценка: 8 (2)
Здравствуйте, Xobotik, Вы писали:

X>Ну то есть получается надо решить задачу используя только один цикл.


Не совсем верно. O(N) допускает кол-во операций, пропорциональное N. Т.е. это может быть один цикл по N, два цикла по N, три и более, но главное чтобы число циклов не зависело от N и чтобы циклы не были вложенными.
На самом деле вложенные тоже можно, но число итераций вложенных циклов не должно зависеть от N.

примеры, удовлетворяющие оценке O(N):
for(int i = 0; i < N-1; i++)
{
   ...
}

for(int k = N-1; k >=0; k--)
{
   ...
}


for(int i = 0; i < N-1; i++)
{
   for(int k = 0; k < 100; k++)
   {
       ...
   }
}


Это об оценке кол-ва операций O(N).
А возвращаясь к задаче — да, эта задача решается с помощью одного цикла.
Re[3]: Поиск повторяющегося числа в массиве
От: elmal  
Дата: 01.04.10 17:31
Оценка:
Здравствуйте, samius, Вы писали:

S>Полагаю, что автор задачи вряд ли рассчитывал увидеть в решении задачи по теме массивов HashSet.

Лично я бы, если бы дал такую задачу, именно такое решение бы и ожидал увидеть. Так как такие задачи довольно часты на практике, и по крайней мере я их всегда через HashSet делаю. Конечно есть решение и без HashSet, именно оно и ожидается скорее всего (где то я в этюдах решение видел, насколько я понимаю, основная идея тогда — построить такую контрольную сумму, чтобы можно было вычислить дубликат), но сходу я б ее не решил быстро, как и не ожидал бы такого решения от кандидата. Да и не очень будет это решение, при всей своей мегаоптимальности и красивости универсальным, ни разу у меня не было случая, когда постановка задачи была именно такая (именно 2 раза встречается, и именно от 1 до М).

PS Пока писал — вспомнил решение . А топикстартуру — пусть гуглит, где то здесь проскакивало, наводку я дал
Re[4]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 17:39
Оценка:
Здравствуйте, elmal, Вы писали:

E>Конечно есть решение и без HashSet, именно оно и ожидается скорее всего (где то я в этюдах решение видел, насколько я понимаю, основная идея тогда — построить такую контрольную сумму, чтобы можно было вычислить дубликат), но сходу я б ее не решил быстро, как и не ожидал бы такого решения от кандидата.


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

E>PS Пока писал — вспомнил решение . А топикстартуру — пусть гуглит, где то здесь проскакивало, наводку я дал


Не надо ничего гуглить. Надо немного сосредоточиться, знаний достаточно. Дорюхать самому гораздо полезнее, чем нагуглить. Прорастут кое-какие нейронные связи в голове, потом ими можно будет пользоваться.
Re[3]: Поиск повторяющегося числа в массиве
От: andy1618 Россия  
Дата: 01.04.10 17:49
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>>>Есть ли какие-либо другие пути решения задачи?

E>>Эээ, а что, итерация по массиву, занесение результата в HashSet (не знаю как аналог в .NET называется) и выход, если результат уже заносили — не прокатит за решение? Обязательно извращаться?

X>А это не O(N^2)?


В C# это называется Dictionary<T>. Если правильно указать ёмкость словарика при инициализации (M), то алгоритм будет работать за время O(N). Но есть один нюанс — отожрётся памяти O(M), что в подобных задачах обычно считается неприемлемым (ибо тогда это эквивалентно заведению простого вспомогательного массива из M элементов, после чего задача становится тривиальной).
Re[10]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 17:58
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>Ну то есть получается надо решить задачу используя только один цикл.


S>Не совсем верно. O(N) допускает кол-во операций, пропорциональное N. Т.е. это может быть один цикл по N, два цикла по N, три и более, но главное чтобы число циклов не зависело от N и чтобы циклы не были вложенными.

S>На самом деле вложенные тоже можно, но число итераций вложенных циклов не должно зависеть от N.

S>примеры, удовлетворяющие оценке O(N):

S>
S>for(int i = 0; i < N-1; i++)
S>{
S>   ...
S>}

S>for(int k = N-1; k >=0; k--)
S>{
S>   ...
S>}
S>


S>
S>for(int i = 0; i < N-1; i++)
S>{
S>   for(int k = 0; k < 100; k++)
S>   {
S>       ...
S>   }
S>}
S>


S>Это об оценке кол-ва операций O(N).

S>А возвращаясь к задаче — да, эта задача решается с помощью одного цикла.

Не понимаю как одним циклом можно сделать. Ну на примере в логике понимаю как нужно сравнивать

Дан массив 1,2,3,4,5

Первая итерация сравниваем следующие комбинации цифр:
1=2;1=3;1=4;1=5.
Следующая итерация:
2=3;2=4;2=5. Мы не сравниваем 2=1 потому что сравнивали эту комбинацию в предыдущей итерации
Следующая итерация:
3=4;3=5.
4=5. последняя итерация

Подход хотя бы такой нужен или логика схожа правильного пути решения?
С уважением!
Re[5]: Поиск повторяющегося числа в массиве
От: elmal  
Дата: 01.04.10 18:05
Оценка: +2
Здравствуйте, samius, Вы писали:

S>Судя по всему речь о другой задаче, в которой все числа кроме одного встречаются четное число раз.

Принцип тот же самый, там только решение более очевидно, да и тут неглубоко зарыто. Эх... было время, когда такие задачи сходу, и ни про какие хешсеты и не подумал бы, так как не знал о них .
Re[10]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 18:36
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>Ну то есть получается надо решить задачу используя только один цикл.


S>Не совсем верно. O(N) допускает кол-во операций, пропорциональное N. Т.е. это может быть один цикл по N, два цикла по N, три и более, но главное чтобы число циклов не зависело от N и чтобы циклы не были вложенными.

S>На самом деле вложенные тоже можно, но число итераций вложенных циклов не должно зависеть от N.

S>примеры, удовлетворяющие оценке O(N):

S>
S>for(int i = 0; i < N-1; i++)
S>{
S>   ...
S>}

S>for(int k = N-1; k >=0; k--)
S>{
S>   ...
S>}
S>


S>
S>for(int i = 0; i < N-1; i++)
S>{
S>   for(int k = 0; k < 100; k++)
S>   {
S>       ...
S>   }
S>}
S>


S>Это об оценке кол-ва операций O(N).

S>А возвращаясь к задаче — да, эта задача решается с помощью одного цикла.

       private static int fff(int[] a)
        {
            int buf = 0;
            int n = 1;
            start:
            for (int i = 0, j = n ; j <= a.Length - 1; i++, j++)
            {
                if (a[i] == a[j])
                {
                    buf = a[i];
                    return buf;
                }
            }
            if (buf == 0)
            {
                n++;
                goto start;
            }
            return buf;
        }


Если это неверно, то я не знаю как еще.
С уважением!
Re[11]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 18:48
Оценка: 2 (1)
Здравствуйте, Xobotik, Вы писали:

X>
X>       private static int fff(int[] a)
X>        {
X>            int buf = 0;
X>            int n = 1;
X>            start:
X>            for (int i = 0, j = n ; j <= a.Length - 1; i++, j++)
X>            {
X>                if (a[i] == a[j])
X>                {
X>                    buf = a[i];
X>                    return buf;
X>                }
X>            }
X>            if (buf == 0)
X>            {
X>                n++;
X>                goto start;
X>            }
X>            return buf;
X>        }
X>


X>Если это неверно, то я не знаю как еще.


Это то же самое сравнение каждого элемента с каждым. Сложность квадратичная O(N^2). Хоть цикл и один, но с помощью goto он прокручивается в худшем случае N-1 раз.
Re[12]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 18:54
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>
X>>       private static int fff(int[] a)
X>>        {
X>>            int buf = 0;
X>>            int n = 1;
X>>            start:
X>>            for (int i = 0, j = n ; j <= a.Length - 1; i++, j++)
X>>            {
X>>                if (a[i] == a[j])
X>>                {
X>>                    buf = a[i];
X>>                    return buf;
X>>                }
X>>            }
X>>            if (buf == 0)
X>>            {
X>>                n++;
X>>                goto start;
X>>            }
X>>            return buf;
X>>        }
X>>


X>>Если это неверно, то я не знаю как еще.


S>Это то же самое сравнение каждого элемента с каждым. Сложность квадратичная O(N^2). Хоть цикл и один, но с помощью goto он прокручивается в худшем случае N-1 раз.


Ну это алгоритм не сравнивает 2=1 , когда сравнили 1=2:

Без goto:

private static int fff(int[] a)
        {
            int buf = 0;
            for (int n = 1; n <= a.Length - 1; n++)
            {
                for (int i = 0, j = n; j <= a.Length - 1; i++, j++)
                {
                    if (a[i] == a[j])
                    {
                        buf = a[i];
                        return buf;
                    }
                }
            }
            return buf;
        }


А как можно без сравнения каждого элемента с каждым я не понимаю.
С уважением!
Re[13]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 19:01
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>А как можно без сравнения каждого элемента с каждым я не понимаю.


Задача заключается не в том чтобы сравнить каждый с каждым, а в том чтобы понять встречался ли уже такой элемент при просмотре массива или нет. Для этого пройденные элементы надо запоминать где-то вовне массива, чтобы без перебора можно было ответить встречали ли мы элемент K уже или нет.
Re[14]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 19:08
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>А как можно без сравнения каждого элемента с каждым я не понимаю.


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



Ну а как мы определим встречался элемент или нет без сравнения? Понятно, что с начало запоминаем первый элемент сравниваем с последующими до конца, запоминаем до предпоследнего элемента.
С уважением!
Re[15]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 19:10
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Ну а как мы определим встречался элемент или нет без сравнения? Понятно, что с начало запоминаем первый элемент сравниваем с последующими до конца, запоминаем до предпоследнего элемента.


Без сравнения не определить. Но сравнивать каждый с каждым не нужно. В этом ключ.
Re[14]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 19:11
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>А как можно без сравнения каждого элемента с каждым я не понимаю.


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


То есть мы проходим от первого до последнего элемента. Текущий элемент, добавляем в вспомогательный массив с проверкой нет ли такого же элемента в массиве, если есть то вернем добавляемый элемент. Вот так?
С уважением!
Re[15]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 19:13
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>То есть мы проходим от первого до последнего элемента. Текущий элемент, добавляем в вспомогательный массив с проверкой нет ли такого же элемента в массиве, если есть то вернем добавляемый элемент. Вот так?


Близко, но нужно избавиться от поиска перебором во вспомогательном массиве.
Re[16]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 19:16
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>Ну а как мы определим встречался элемент или нет без сравнения? Понятно, что с начало запоминаем первый элемент сравниваем с последующими до конца, запоминаем до предпоследнего элемента.


S>Без сравнения не определить. Но сравнивать каждый с каждым не нужно. В этом ключ.


Блин не алгоритм же не сравнивает каждый с каждым:

Он сравнивает точно так:


Так чем же лучше добавление с проверкой нет ли такого же.
С уважением!
Re[17]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 19:20
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Здравствуйте, samius, Вы писали:


S>>Без сравнения не определить. Но сравнивать каждый с каждым не нужно. В этом ключ.


X>Блин не алгоритм же не сравнивает каждый с каждым:


X>Он сравнивает точно так:

X>

Это и называется каждый с каждым.

X>Так чем же лучше добавление с проверкой нет ли такого же.

Числом шагов алгоритма, если организовать правильную проверку.
Re[16]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 19:52
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>То есть мы проходим от первого до последнего элемента. Текущий элемент, добавляем в вспомогательный массив с проверкой нет ли такого же элемента в массиве, если есть то вернем добавляемый элемент. Вот так?


S>Близко, но нужно избавиться от поиска перебором во вспомогательном массиве.


Я честное слово не знаю как без поиска перебором, да и вообще без поиска, можно каким-либо другим поиском бинарным например, но при этом сортировать массив, но это уже точно не O(N)
С уважением!
Re[17]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 20:13
Оценка:
Здравствуйте, Xobotik, Вы писали:

S>>Близко, но нужно избавиться от поиска перебором во вспомогательном массиве.


X>Я честное слово не знаю как без поиска перебором, да и вообще без поиска, можно каким-либо другим поиском бинарным например, но при этом сортировать массив, но это уже точно не O(N)


Переформулирую исходную задачу:
Дан массив размера N из целых чисел, принимающих значения от 1 до M. Для каждого числа в массиве найти число его повторений в массиве за O(N) операций.

Если эту решишь, с исходной справишься.
Re[18]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 20:34
Оценка:
Здравствуйте, samius, Вы писали:

S>Переформулирую исходную задачу:

S>Дан массив размера N из целых чисел, принимающих значения от 1 до M. Для каждого числа в массиве найти число его повторений в массиве за O(N) операций.

S>Если эту решишь, с исходной справишься.


       private static int ffff(int[] a)
        {
            Array.Sort(a); //  O(n log n)
            int buf = 0;
            for (int i = 0; i <= a.Length - 1; i++) // O(n)
            {
                if(Array.BinarySearch(b,a[i]) == -1) // O(log n)
                {
                    continue;
                }
                else
                {
                    return a[i];
                }
            }
            return buf;
        }


По поводу той задачи.
Это наверно получше будет, чем сравнение каждый с каждым. Сейчас попытаюсь решить с количеством повторений.
С уважением!
Re[19]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 20:36
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Здравствуйте, samius, Вы писали:


S>>Переформулирую исходную задачу:

S>>Дан массив размера N из целых чисел, принимающих значения от 1 до M. Для каждого числа в массиве найти число его повторений в массиве за O(N) операций.

S>>Если эту решишь, с исходной справишься.


X>
X>       private static int ffff(int[] a)
X>        {
X>            Array.Sort(a); //  O(n log n)
X>            int buf = 0;
X>            for (int i = 0; i <= a.Length - 1; i++) // O(n)
X>            {
X>                if(Array.BinarySearch(b,a[i]) == -1) // O(log n)
X>                {
X>                    continue;
X>                }
X>                else
X>                {
X>                    return a[i];
X>                }
X>            }
X>            return buf;
X>        }
X>


X>По поводу той задачи.

X>Это наверно получше будет, чем сравнение каждый с каждым.

Похуже. BinarySearch работает только с упорядоченными массивами.
Re[20]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 20:39
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>Здравствуйте, samius, Вы писали:


S>>>Переформулирую исходную задачу:

S>>>Дан массив размера N из целых чисел, принимающих значения от 1 до M. Для каждого числа в массиве найти число его повторений в массиве за O(N) операций.

S>>>Если эту решишь, с исходной справишься.


X>>
X>>       private static int ffff(int[] a)
X>>        {
X>>            Array.Sort(a); //  O(n log n)
X>>            int buf = 0;
X>>            for (int i = 0; i <= a.Length - 1; i++) // O(n)
X>>            {
X>>                if(Array.BinarySearch(b,a[i]) == -1) // O(log n)
X>>                {
X>>                    continue;
X>>                }
X>>                else
X>>                {
X>>                    return a[i];
X>>                }
X>>            }
X>>            return buf;
X>>        }
X>>


X>>По поводу той задачи.

X>>Это наверно получше будет, чем сравнение каждый с каждым.

S>Похуже. BinarySearch работает только с упорядоченными массивами.


ну мы же отсортировали массив.
С уважением!
Re[20]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 01.04.10 20:41
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>Здравствуйте, samius, Вы писали:


S>>>Переформулирую исходную задачу:

S>>>Дан массив размера N из целых чисел, принимающих значения от 1 до M. Для каждого числа в массиве найти число его повторений в массиве за O(N) операций.

S>>>Если эту решишь, с исходной справишься.


X>>
X>>       private static int ffff(int[] a)
X>>        {
X>>            Array.Sort(a); //  O(n log n)
X>>            int buf = 0;
X>>            for (int i = 0; i <= a.Length - 1; i++) // O(n)
X>>            {
X>>                if(Array.BinarySearch(b,a[i]) == -1) // O(log n)
X>>                {
X>>                    continue;
X>>                }
X>>                else
X>>                {
X>>                    return a[i];
X>>                }
X>>            }
X>>            return buf;
X>>        }
X>>


X>>По поводу той задачи.

X>>Это наверно получше будет, чем сравнение каждый с каждым.

S>Похуже. BinarySearch работает только с упорядоченными массивами.


Огромное спасибо за помощь. Еще один вопрос, не знаю достаточно хорошо правила форума и договоренности между пользователями этого форума, как ставить оценки — то в качестве благодарности поставить за все сообщения в этой ветке тройки или не надо?
С уважением!
Re[21]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 20:42
Оценка:
Здравствуйте, Xobotik, Вы писали:

S>>Похуже. BinarySearch работает только с упорядоченными массивами.


X>ну мы же отсортировали массив.


Прошу прощения, поздно уже...
Re[21]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.04.10 20:43
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Огромное спасибо за помощь. Еще один вопрос, не знаю достаточно хорошо правила форума и договоренности между пользователями этого форума, как ставить оценки — то в качестве благодарности поставить за все сообщения в этой ветке тройки или не надо?


Нет, не стоит
Re[16]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 02.04.10 01:11
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


X>>То есть мы проходим от первого до последнего элемента. Текущий элемент, добавляем в вспомогательный массив с проверкой нет ли такого же элемента в массиве, если есть то вернем добавляемый элемент. Вот так?


S>Близко, но нужно избавиться от поиска перебором во вспомогательном массиве.


Сделал. Метод под номером 4.

// Метод №1.
      private static int f(int[] array)
        {
            int m = 1;
            int buf = 0;
            // количество сравнений (n-1)^2, где n - длина массива
            for (int i = 0; i <= (array.Length - 1) * (array.Length - 1); i++)
            {
                // количество перестановок (n-1), где n - длина массива
                for (int j = 1; j < array.Length; j++)
                {
                    if (array[0] == array[j])
                    {
                        buf = array[0];
                        return buf;
                    }
                }
                int temp = array[m];
                array[m] = array[0];
                array[0] = temp;
                m++;
            }
            return buf;
        }

// Метод №2.
        private static int ff(int[] a)
        {
            int buf = 0;
            for (int n = 1; n <= a.Length - 1; n++)
            {
                for (int i = 0, j = n; j <= a.Length - 1; i++, j++)
                {
                    if (a[i] == a[j])
                    {
                        buf = a[i];
                        return buf;
                    }
                }
            }
            return buf;
        }

// Метод №3.
        private static int fff(int[] a)
        {
            Array.Sort(a);
            int buf = 0;
            for (int i = 0; i <= a.Length - 1; i++)
            {
                if(Array.BinarySearch(a,a[i]) == -1)
                {
                    continue;
                }
                else
                {
                    buf = a[i];
                    return buf;
                }
            }
            return buf;
        }

// Метод №4.
        private static int ffff(int[] a)
        {
            int buf = 0;
            int[] b = new int[a.Length - 1];
            b[0] = a[0];
            int n = 0;
            for (int i = 1; i <= a.Length - 1; i++)
            {
                if (b.Contains(a[i]))
                {
                    buf = a[i];
                    return buf;
                }
                else
                {
                    n++;
                    b[n] = a[i];
                }
            }
            return buf;
        }


Вот четвертый метод со вспомогательным массивов и без поиска перебором (наверно здесь имелось ввиду без линейного поиска). LINQ — выручил однако. Но по производительности для 7 элементов 4-ый метод наихудший.

Рассматривал вот такие массивы:
            int[] a = new int[] { 1, 2, 3, 4, 5, 1, 8 };
            int[] b = new int[] { 3, 1, 2, 4, 1, 6, 8 };
            int[] c = new int[] { 3, 2, 1, 1, 5, 6, 8 };
            int[] d = new int[] { 1, 2, 3, 4, 1, 6, 8 };
            int[] e = new int[] { 3, 2, 5, 4, 1, 1, 8 };
            int[] f = new int[] { 3, 2, 1, 4, 6, 1, 8 };
            int[] j = new int[] { 3, 2, 1, 4, 6, 8, 1 };


Общий рейтинг:
1) Метод №2;
2) Метод №1;
3) Метод №3;
4) Метод №4.
С уважением!
Re[17]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 02.04.10 04:43
Оценка:
Здравствуйте, Xobotik, Вы писали:

S>>Близко, но нужно избавиться от поиска перебором во вспомогательном массиве.


X>Сделал. Метод под номером 4.


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

Мой вариант задачи не делал, где нужно посчитать кол-ва упоминаний элементов массива?
Re[18]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 02.04.10 07:07
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


S>>>Близко, но нужно избавиться от поиска перебором во вспомогательном массиве.


X>>Сделал. Метод под номером 4.


S>4-ый метод хоть сам не перебирает элементы вспомогательного массива, зато это делает LINQ в методе Contains. Сложность этого решения квадратичная.


S>Мой вариант задачи не делал, где нужно посчитать кол-ва упоминаний элементов массива?


Нет еще не делал, но мысли есть по поводу этой задачки.
С уважением!
Re: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 02.04.10 10:37
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

Массив для анализа AA
резервируем массив Ar длиной M с нулями

For I=0 To N-1
IF AR[AA[I]] <> 0 Then EXIT С НАЙДЕНЫМ ЗНАЧЕНИЕМ
Else AR[AA[I]]+=1
end For

В среднем O(3N/2) что явно лучше чем O(N)
Если M велико можно по разрядам в байте фиксировать факт наличия данного значения.
Re[18]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 03.04.10 11:30
Оценка: 1 (1)
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Xobotik, Вы писали:


S>>>Близко, но нужно избавиться от поиска перебором во вспомогательном массиве.


X>>Сделал. Метод под номером 4.


S>4-ый метод хоть сам не перебирает элементы вспомогательного массива, зато это делает LINQ в методе Contains. Сложность этого решения квадратичная.


S>Мой вариант задачи не делал, где нужно посчитать кол-ва упоминаний элементов массива?


Решил все таки:

P.S. на комментарий batu не смотрел

        private static int foo(int[] a)
        {
            int buf = 0;
            int[] b = new int[a.Length];
            for (int i = 0; i < a.Length; i++)
            {
                if (b[a[i]] == 0)
                {
                    b[a[i]] = a[i];
                }
                else
                {
                    buf = a[i];
                    return buf;
                }
            }
            return buf;
        }
С уважением!
Re[2]: Поиск повторяющегося числа в массиве
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 03.04.10 11:52
Оценка:
Здравствуйте, batu, Вы писали:

B>В среднем O(3N/2) что явно лучше чем O(N)


Несколько замечаний:

1. 3N/2 > N
2. O(3N/2) = O(N)
3. Сложность алгоритма не О(N), а O(M), что может быть гораздо хуже.
Ce n'est que pour vous dire ce que je vous dis.
Re[3]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 03.04.10 12:14
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Здравствуйте, batu, Вы писали:


B>>В среднем O(3N/2) что явно лучше чем O(N)


DR>Несколько замечаний:


DR>1. 3N/2 > N

DR>2. O(3N/2) = O(N)
DR>3. Сложность алгоритма не О(N), а O(M), что может быть гораздо хуже.

Отлично, ну а как тогда реализовывать поставленную задача, если алгоритм должен быть без сравнения и перебора элементов во вспомогательном массиве (так же без сравнения во входном массиве) за время O(N). Может быть в задаче, то и имелось ввиду за O(M).
С уважением!
Re[3]: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 03.04.10 18:09
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Здравствуйте, batu, Вы писали:


B>>В среднем O(3N/2) что явно лучше чем O(N)


DR>Несколько замечаний:


DR>1. 3N/2 > N

DR>2. O(3N/2) = O(N)
DR>3. Сложность алгоритма не О(N), а O(M), что может быть гораздо хуже.
Согласен. Я не правильно записал Я имел ввиду, что алгоритм в среднем требует половины цикла. Как-то надо было разделить пополамПотому имелось в виду значение O как фиксированое значение для обработки одного тела цикла, в общем случае именно это подразумевается как коэффициент. Это тот случай когда и ты прав и я прав
А сложность таки N. Цикл по N. M может затребовать памяти если будет велико.
Re[4]: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 03.04.10 18:24
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Здравствуйте, Don Reba, Вы писали:


DR>>Здравствуйте, batu, Вы писали:


B>>>В среднем O(3N/2) что явно лучше чем O(N)


DR>>Несколько замечаний:


DR>>1. 3N/2 > N

DR>>2. O(3N/2) = O(N)
DR>>3. Сложность алгоритма не О(N), а O(M), что может быть гораздо хуже.

X>Отлично, ну а как тогда реализовывать поставленную задача, если алгоритм должен быть без сравнения и перебора элементов во вспомогательном массиве (так же без сравнения во входном массиве) за время O(N). Может быть в задаче, то и имелось ввиду за O(M).

Видимо алгоритм не понят.
Мы резервируем массив размером с диапазон значений, и в цикле заносим единицу по индексу значения этого числа. Понятное дело что перед выбором следующего числа анализируемого массива, мы проверяем не было ли единицы по данному индексу, если есть, то это число уже встречалось. Можно выходить из цикла. Поставленая задача решена. Без сравнения никак нельзя. Что-то по любому надо проверять. А перебора вспомогательного массива нет. Так что я не пойму откуда возникла сложность O(M). В среднем достаточно половины циклов массива размером N для нахожения повторяющегося числа.
Re[5]: Поиск повторяющегося числа в массиве
От: Буравчик Россия  
Дата: 03.04.10 18:53
Оценка: 1 (1) +1
Здравствуйте, batu, Вы писали:

B>А перебора вспомогательного массива нет. Так что я не пойму откуда возникла сложность O(M).


Есть — инициализация нулями вспомогательного массива (размера M).
... << RSDN@Home 1.2.0 alpha 4 rev. 1302>>
Best regards, Буравчик
Re[5]: Поиск повторяющегося числа в массиве
От: dilmah США  
Дата: 03.04.10 18:55
Оценка:
B>Видимо алгоритм не понят.
B>Мы резервируем массив размером с диапазон значений, и в цикле заносим единицу по индексу значения этого числа. Понятное дело что перед выбором следующего числа анализируемого массива, мы проверяем не было ли единицы по данному индексу, если есть, то это число уже встречалось. Можно выходить из цикла. Поставленая задача решена. Без сравнения никак нельзя. Что-то по любому надо проверять. А перебора вспомогательного массива нет. Так что я не пойму откуда возникла сложность O(M). В среднем достаточно половины циклов массива размером N для нахожения повторяющегося числа.

тебе нужно проинициализировать нулями массив размером M. Формально это O(M), если забыть о трюках с paged memory management
Re[4]: Поиск повторяющегося числа в массиве
От: Буравчик Россия  
Дата: 03.04.10 19:01
Оценка: 6 (1) -1
Здравствуйте, Xobotik, Вы писали:

X>Отлично, ну а как тогда реализовывать поставленную задача, если алгоритм должен быть без сравнения и перебора элементов во вспомогательном массиве (так же без сравнения во входном массиве) за время O(N).


Лучше всего — HashSet. Удовлетворяет условию полностью.

X>Может быть в задаче, то и имелось ввиду за O(M).


А может все числа встречаются по два раза, а одно число только один раз?
А может массив содержит все числа от 1 до M и плюс еще одно повторение, т.е. длина массива равна M+1?
С учетом таких вариантов задача будет занимательной

А так... Ну возьмем M = 2^64. Из работающих алгоритмов остаются только хэши да деревья.
Можно использовать готовые, можно сделать самому. Может это и требуется?
... << RSDN@Home 1.2.0 alpha 4 rev. 1302>>
Best regards, Буравчик
Re[5]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 03.04.10 23:21
Оценка:
Здравствуйте, batu, Вы писали:

B>Здравствуйте, Xobotik, Вы писали:


X>>Здравствуйте, Don Reba, Вы писали:


DR>>>Здравствуйте, batu, Вы писали:


B>>>>В среднем O(3N/2) что явно лучше чем O(N)


DR>>>Несколько замечаний:


DR>>>1. 3N/2 > N

DR>>>2. O(3N/2) = O(N)
DR>>>3. Сложность алгоритма не О(N), а O(M), что может быть гораздо хуже.

X>>Отлично, ну а как тогда реализовывать поставленную задача, если алгоритм должен быть без сравнения и перебора элементов во вспомогательном массиве (так же без сравнения во входном массиве) за время O(N). Может быть в задаче, то и имелось ввиду за O(M).

B>Видимо алгоритм не понят.
B>Мы резервируем массив размером с диапазон значений, и в цикле заносим единицу по индексу значения этого числа. Понятное дело что перед выбором следующего числа анализируемого массива, мы проверяем не было ли единицы по данному индексу, если есть, то это число уже встречалось. Можно выходить из цикла. Поставленая задача решена. Без сравнения никак нельзя. Что-то по любому надо проверять. А перебора вспомогательного массива нет. Так что я не пойму откуда возникла сложность O(M). В среднем достаточно половины циклов массива размером N для нахожения повторяющегося числа.

Да все я понял, под сравнениями я имел ввиду >, <, <=, >=. Я просто решил задачу в пятницу, захожу сюда, чтобы отписаться вчера, а тут вы решение уже сказали, обидно блин. Такое ощущение, что не сам догадался.
С уважением!
Re[5]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 03.04.10 23:27
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Здравствуйте, Xobotik, Вы писали:


X>>Отлично, ну а как тогда реализовывать поставленную задача, если алгоритм должен быть без сравнения и перебора элементов во вспомогательном массиве (так же без сравнения во входном массиве) за время O(N).


Б>Лучше всего — HashSet. Удовлетворяет условию полностью.


X>>Может быть в задаче, то и имелось ввиду за O(M).


Б>А может все числа встречаются по два раза, а одно число только один раз?

Б>А может массив содержит все числа от 1 до M и плюс еще одно повторение, т.е. длина массива равна M+1?
Б>С учетом таких вариантов задача будет занимательной

Задача поставлена четко в начале темы, никаких там если бы, да как бы нет

Б>А так... Ну возьмем M = 2^64. Из работающих алгоритмов остаются только хэши да деревья.

Б>Можно использовать готовые, можно сделать самому. Может это и требуется?

нет не требуется
С уважением!
Re[5]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 03.04.10 23:36
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Здравствуйте, Xobotik, Вы писали:


X>>Отлично, ну а как тогда реализовывать поставленную задача, если алгоритм должен быть без сравнения и перебора элементов во вспомогательном массиве (так же без сравнения во входном массиве) за время O(N).


Б>Лучше всего — HashSet. Удовлетворяет условию полностью.


X>>Может быть в задаче, то и имелось ввиду за O(M).


Б>А может все числа встречаются по два раза, а одно число только один раз?

Б>А может массив содержит все числа от 1 до M и плюс еще одно повторение, т.е. длина массива равна M+1?
Б>С учетом таких вариантов задача будет занимательной

На счет занимательности, небольшое еще добавление, за время O(log n) сделать)

Б>А так... Ну возьмем M = 2^64. Из работающих алгоритмов остаются только хэши да деревья.

Б>Можно использовать готовые, можно сделать самому. Может это и требуется?
С уважением!
Re[6]: Поиск повторяющегося числа в массиве
От: Буравчик Россия  
Дата: 03.04.10 23:46
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>На счет занимательности, небольшое еще добавление, за время O(log n) сделать)


Лучше, чем за O(n) не сделать — массив необходимо просмотреть как минимум один раз.
... << RSDN@Home 1.2.0 alpha 4 rev. 1302>>
Best regards, Буравчик
Re[7]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 03.04.10 23:55
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Здравствуйте, Xobotik, Вы писали:


X>>На счет занимательности, небольшое еще добавление, за время O(log n) сделать)


Б>Лучше, чем за O(n) не сделать — массив необходимо просмотреть как минимум один раз.


Да это понятно=)
С уважением!
Re[4]: Решение за O(N) и доп. память O(N)
От: andy1618 Россия  
Дата: 04.04.10 08:28
Оценка:
Здравствуйте, andy1618, Вы писали:

A>В C# это называется Dictionary<T>. Если правильно указать ёмкость словарика при инициализации (M), то алгоритм будет работать за время O(N). Но есть один нюанс — отожрётся памяти O(M), что в подобных задачах обычно считается неприемлемым (ибо тогда это эквивалентно заведению простого вспомогательного массива из M элементов, после чего задача становится тривиальной).


Упс, ошибся! Ведь M может быть очень велико и существенно превышать N (например, M=2^64, N=1000), а для шустрой работы хешированного словарика вполне достаточно памяти порядка O(N).
Резюме: использование хешированного списка (например, Dictionary в C#) является решением задачи за время O(N) и доп. память O(N).
Re[5]: Решение за O(N) и доп. память O(N)
От: dilmah США  
Дата: 04.04.10 09:06
Оценка:
A>Резюме: использование хешированного списка (например, Dictionary в C#) является решением задачи за время O(N) и доп. память O(N).

не понимаю. Если сделать хэш размером N, то коллизии хэшей убьют O(1) доступ, и реально будет тот же логарифм.
Чтобы сохранить O(1) (в среднем) доступ нужен хэш размером N*lgN, опять таки вылазит логарифм.
Re[6]: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 04.04.10 14:00
Оценка:
Здравствуйте, Xobotik, Вы писали:


X>Да все я понял, под сравнениями я имел ввиду >, <, <=, >=. Я просто решил задачу в пятницу, захожу сюда, чтобы отписаться вчера, а тут вы решение уже сказали, обидно блин. Такое ощущение, что не сам догадался.

Та ладно.. Фигня все это. Развлекаемся.
Re[6]: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 04.04.10 14:12
Оценка:
Здравствуйте, dilmah, Вы писали:

D>тебе нужно проинициализировать нулями массив размером M. Формально это O(M), если забыть о трюках с paged memory management

Формально да. Есть языки, которые не требуют инициализации.. А так ты прав
Re: Поиск повторяющегося числа в массиве
От: frogkiller Россия  
Дата: 04.04.10 14:19
Оценка: +1
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

Странно, что никто не предложил такой вариант: lexical sort (=O(N*log(M))) + ещё один проход для сравнения соседних элементов (=O(N)).
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[2]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 04.04.10 14:31
Оценка:
Здравствуйте, frogkiller, Вы писали:

F>Здравствуйте, Xobotik, Вы писали:


F>Странно, что никто не предложил такой вариант: lexical sort (=O(N*log(M))) + ещё один проход для сравнения соседних элементов (=O(N)).


Что-то я не понял откуда в lexical sort оценка O(N*log(M))

radix sort для Int32 займет O(4*N). Т.е. формально за O(N) с дополнительной памятью O(C).
Re[3]: Поиск повторяющегося числа в массиве
От: dilmah США  
Дата: 04.04.10 16:13
Оценка: 1 (1)
S>Что-то я не понял откуда в lexical sort оценка O(N*log(M))

S>radix sort для Int32 займет O(4*N). Т.е. формально за O(N) с дополнительной памятью O(C).


ну вот эта четверка это и есть log(M) -- другими словами -- количество бит в сортируемых числах
Re[5]: Решение за O(N) и доп. память O(N)
От: Xobotik Россия  
Дата: 04.04.10 20:17
Оценка: 3 (1)
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, andy1618, Вы писали:


A>>В C# это называется Dictionary<T>. Если правильно указать ёмкость словарика при инициализации (M), то алгоритм будет работать за время O(N). Но есть один нюанс — отожрётся памяти O(M), что в подобных задачах обычно считается неприемлемым (ибо тогда это эквивалентно заведению простого вспомогательного массива из M элементов, после чего задача становится тривиальной).


A>Упс, ошибся! Ведь M может быть очень велико и существенно превышать N (например, M=2^64, N=1000), а для шустрой работы хешированного словарика вполне достаточно памяти порядка O(N).

A>Резюме: использование хешированного списка (например, Dictionary в C#) является решением задачи за время O(N) и доп. память O(N).

Да вы правы Словари решают задачу за O(N)

            public int GetDuplicateNumber(int[] array)
            {
                Dictionary<int, int> dictionary = new Dictionary<int, int>(array.Length);
                foreach (int i in array) // O(N)
                {
                    if (dictionary.ContainsKey(i)) // Этот метод является операцией порядка сложности O(1)
                    {
                        return i;
                    }
                    else
                    {
                        dictionary.Add(i, 0); // O(1) размер словаря, равен размеру массива, размер не увеличивается
                    }
                }
                return 0;
                // результат: O(N*1*1) = O(N) 
            }
С уважением!
Re[6]: Решение за O(N) и доп. память O(N)
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 04.04.10 20:28
Оценка: 3 (1)
Здравствуйте, dilmah, Вы писали:

D>не понимаю. Если сделать хэш размером N, то коллизии хэшей убьют O(1) доступ, и реально будет тот же логарифм.


Не будет, посчитай. К тому же, хэш можно сделать размером kN для любого положительного k.
Ce n'est que pour vous dire ce que je vous dis.
Re[6]: Решение за O(N) и доп. память O(N)
От: Xobotik Россия  
Дата: 04.04.10 20:34
Оценка:
Здравствуйте, dilmah, Вы писали:

A>>Резюме: использование хешированного списка (например, Dictionary в C#) является решением задачи за время O(N) и доп. память O(N).


D>не понимаю. Если сделать хэш размером N, то коллизии хэшей убьют O(1) доступ, и реально будет тот же логарифм.

D>Чтобы сохранить O(1) (в среднем) доступ нужен хэш размером N*lgN, опять таки вылазит логарифм.

Я так долго копил баллы, за что -1 то? Я метод делал строго по документации MSDN.

О методе ContainsKey:
здесь]

В заметках написано: Этот метод является операцией порядка сложности O(1).

О вставки в словарь:
здесь

В заметках написано о сложности вставки.
С уважением!
Re[7]: Решение за O(N) и доп. память O(N)
От: dilmah США  
Дата: 04.04.10 21:01
Оценка: +2
D>>не понимаю. Если сделать хэш размером N, то коллизии хэшей убьют O(1) доступ, и реально будет тот же логарифм.

DR>Не будет, посчитай. К тому же, хэш можно сделать размером kN для любого положительного k.


ок, согласен, посчитал количество коллизий стремится к распределению пуассона, так что в среднем константный оверхед.
Но все равно, зависимость от M спрятана неявно -- в вычислении хэша.
Re[6]: Решение за O(N) и доп. память O(N)
От: Xobotik Россия  
Дата: 04.04.10 22:36
Оценка:
Здравствуйте, Xobotik, Вы писали:

Только не так:
X>
X>            public int GetDuplicateNumber(int[] array)
X>            {
X>                Dictionary<int, int> dictionary = new Dictionary<int, int>(array.Length);
X>                foreach (int i in array) // O(N)
X>                {
X>                    if (dictionary.ContainsKey(i)) // Этот метод является операцией порядка сложности O(1)
X>                    {
X>                        return i;
X>                    }
X>                    else
X>                    {
X>                        dictionary.Add(i, 0); // O(1) размер словаря, равен размеру массива, размер не увеличивается
X>                    }
X>                }
X>                return 0;
X>                // результат: O(N*1*1) = O(N) 
X>            }
X>


а вот так:
        public int GetDuplicateNumber(int[] array)
        {
            Dictionary<int, int> dictionary = new Dictionary<int, int>(array.Length);
            for (int i = 0; i < array.Length; i++)
            {
                if (dictionary.ContainsKey(array[i]))
                {
                    return array[i];
                }
                else
                {
                    dictionary.Add(array[i], i); // ключи словаря - это значения массива, а значения словаря - это шаг цикла for
                }
            }
            return 0;
        }
С уважением!
Re[8]: Решение за O(N) и доп. память O(N)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 05.04.10 03:15
Оценка:
Здравствуйте, dilmah, Вы писали:

D>Но все равно, зависимость от M спрятана неявно -- в вычислении хэша.


Можно развернуть мысль?
Re[9]: Решение за O(N) и доп. память O(N)
От: dilmah США  
Дата: 05.04.10 07:14
Оценка: 1 (1) +2
D>>Но все равно, зависимость от M спрятана неявно -- в вычислении хэша.

S>Можно развернуть мысль?


ну в исходной задаче было озвучено 2 параметра: N и M.
Решение с хэшом имеет сложность O(N) только в предположении, что M не превышает некого фиксированного числа, скажем UINT64_MAX
Но так как M тоже является параметром, то формально сложность равна O(N*log(M)), потому что чем больше M, тем больше бит в числах.
Re[7]: Решение за O(N) и доп. память O(N)
От: Буравчик Россия  
Дата: 05.04.10 08:57
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>
X>        public int GetDuplicateNumber(int[] array)
X>        {       ...
X>                    dictionary.Add(array[i], i); // ключи словаря - это значения массива, а значения словаря - это 
X>                ...
X>        }
X>


Раз уж начали использовать готовые контейнеры, осталось понять, зачем запоминать в словарь помимо ключа еще и значение (в данном случае i), которое в дальнейшем не используется.

Ведь это:
1. Запутывает код.
2. Увеличивает требования к памяти.
Best regards, Буравчик
Re[8]: Решение за O(N) и доп. память O(N)
От: andy1618 Россия  
Дата: 06.04.10 00:41
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Раз уж начали использовать готовые контейнеры, осталось понять, зачем запоминать в словарь помимо ключа еще и значение (в данном случае i), которое в дальнейшем не используется.


Это да. Вообще говоря, решение через стандартные хеш-словари не очень интересное, любопытно было бы найти какой-то изящный алгоритм. Например, если бы задача звучала "Все числа повторяются по 2 раза, кроме искомого", то обычный побитовый XOR решал бы задачу за O(N) вообще без дополнительной памяти.
Re[8]: Решение за O(N) и доп. память O(N)
От: Xobotik Россия  
Дата: 06.04.10 09:59
Оценка: -1
Здравствуйте, Буравчик, Вы писали:

Б>Здравствуйте, Xobotik, Вы писали:


X>>
X>>        public int GetDuplicateNumber(int[] array)
X>>        {       ...
X>>                    dictionary.Add(array[i], i); // ключи словаря - это значения массива, а значения словаря - это 
X>>                ...
X>>        }
X>>


Б>Раз уж начали использовать готовые контейнеры, осталось понять, зачем запоминать в словарь помимо ключа еще и значение (в данном случае i), которое в дальнейшем не используется.


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

Б>Ведь это:

Б>1. Запутывает код.

Отнюдь.

Б>2. Увеличивает требования к памяти.


Увеличивает на парочку бит
С уважением!
Re[9]: Решение за O(N) и доп. память O(N)
От: Xobotik Россия  
Дата: 06.04.10 10:02
Оценка:
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, Буравчик, Вы писали:


Б>>Раз уж начали использовать готовые контейнеры, осталось понять, зачем запоминать в словарь помимо ключа еще и значение (в данном случае i), которое в дальнейшем не используется.


A>Это да. Вообще говоря, решение через стандартные хеш-словари не очень интересное, любопытно было бы найти какой-то изящный алгоритм. Например, если бы задача звучала "Все числа повторяются по 2 раза, кроме искомого", то обычный побитовый XOR решал бы задачу за O(N) вообще без дополнительной памяти.


Да задачу (стартовую) решили уже без применения каких-то сложных структур:

здесь
Автор: Xobotik
Дата: 03.04.10

private static int foo(int[] a)
        {
            int buf = 0;
            int[] b = new int[a.Length];
            for (int i = 0; i < a.Length; i++)
            {
                if (b[a[i]] == 0)
                {
                    b[a[i]] = a[i];
                }
                else
                {
                    buf = a[i];
                    return buf;
                }
            }
            return buf;
        }


Теперь просто пытаемся найти еще другие методы решения задачи.
С уважением!
Re: Поиск повторяющегося числа в массиве
От: _FRED_ Черногория
Дата: 06.04.10 10:16
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

Весь топик не читал, боясь встретить подсказки, а связи нейронные наростить надо бы, ибо вчера была кушал водку

Правиьно ли я понимаю, что только указанного условия достаточно для решения? То есть
?
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Решение за O(N) и доп. память O(N)
От: Xobotik Россия  
Дата: 06.04.10 10:16
Оценка:
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, Буравчик, Вы писали:


Б>>Раз уж начали использовать готовые контейнеры, осталось понять, зачем запоминать в словарь помимо ключа еще и значение (в данном случае i), которое в дальнейшем не используется.


A>Это да. Вообще говоря, решение через стандартные хеш-словари не очень интересное, любопытно было бы найти какой-то изящный алгоритм. Например, если бы задача звучала "Все числа повторяются по 2 раза, кроме искомого", то обычный побитовый XOR решал бы задачу за O(N) вообще без дополнительной памяти.


Да задачу (стартовую) решили уже без применения каких-то сложных структур:

здесь
Автор: Xobotik
Дата: 03.04.10


        private static int foo(int[] a)
        {
            int[] b = new int[a.Length];
            for (int i = 0; i < a.Length; i++)
            {
                if (b[a[i]] == 0)
                {
                    b[a[i]] = a[i];
                }
                else
                {
                    return a[i];
                }
            }
            return 0;
        }


Теперь просто пытаемся найти еще другие методы решения задачи.
С уважением!
Re[2]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 06.04.10 10:19
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, Xobotik, Вы писали:


X>>Условие задачи:

X>>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>>число в этом массиве повторяется два раза. Найти это число за время O(N).

_FR>Весь топик не читал, боясь встретить подсказки, а связи нейронные наростить надо бы, ибо вчера была кушал водку


_FR>Правиьно ли я понимаю, что только указанного условия достаточно для решения? То есть

_FR> _FR>?

Да.
С уважением!
Re[2]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 06.04.10 10:24
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Весь топик не читал, боясь встретить подсказки, а связи нейронные наростить надо бы, ибо вчера была кушал водку


Вчера какой-то бум был, все кушали водку, даже с утра на "МГАД'е" свободно было)
С уважением!
Re[9]: Решение за O(N) и доп. память O(N)
От: Буравчик Россия  
Дата: 06.04.10 10:44
Оценка: 3 (1)
Здравствуйте, Xobotik, Вы писали:

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


Словарь хранит пары (ключ -> значение). Его основная цель — быстро находить "значение" по его "ключу". В данном контейнере поиск пары (ключ -> значение) осуществляется по хэшу "ключа", а хэш "значения" в поиске не участвует. Поэтому на коллизии влияет только хэш ключа.

Нужна другая структура данных, от которой требуется:
— быстро проверять наличие элемента (на основе хэша)
— быстро добавлять новый элемент

Б>>1. Запутывает код.

X>Отнюдь.

Запутывает, потому что словарь используется не по назначению.

Б>>2. Увеличивает требования к памяти.

X>Увеличивает на парочку бит

Можно обойтись и без этого.
Best regards, Буравчик
Re[10]: Решение за O(N) и доп. память O(N)
От: _FRED_ Черногория
Дата: 06.04.10 10:48
Оценка: 2 (1)
Здравствуйте, Xobotik, Вы писали:

X>Да задачу (стартовую) решили уже без применения каких-то сложных структур:


X>здесь
Автор: Xobotik
Дата: 03.04.10

X>            int[] b = new int[a.Length];


Не, так неинтересно: я про большие числа потому и спросил, что бы узнать, можно ли выделять память, пропорциональную N или M.

Есть известная задачка на поиск цикла в однонаправленном списке. Многие задают ей, не говоря об имеющихся ограничениях. А самое простейшее решение в таких случаях — тот же HashSet — запоминание того, что прошли в нём. Всяко быстрее догонялок будет :о))
Help will always be given at Hogwarts to those who ask for it.
Re[10]: Решение за O(N) и доп. память O(N)
От: Xobotik Россия  
Дата: 06.04.10 11:06
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Здравствуйте, Xobotik, Вы писали:


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


Б>Словарь хранит пары (ключ -> значение). Его основная цель — быстро находить "значение" по его "ключу". В данном контейнере поиск пары (ключ -> значение) осуществляется по хэшу "ключа", а хэш "значения" в поиске не участвует. Поэтому на коллизии влияет только хэш ключа.


Точно, перепутал.

Б>Нужна другая структура данных, от которой требуется:

Б>- быстро проверять наличие элемента (на основе хэша)
Б>- быстро добавлять новый элемент

здесь было предложение использовать фильтр Блума.

Б>>>1. Запутывает код.

X>>Отнюдь.
Б>Запутывает, потому что словарь используется не по назначению.

Ну извините мы же не решаем задачу о нахождения оптимального стиля программирования, а решаем конкретную постановку. Да и 10 строк мало кого запутают.

Б>>>2. Увеличивает требования к памяти.

X>>Увеличивает на парочку бит
Б>Можно обойтись и без этого.

ну а вообще объясняю еще раз причину добавления в ключи значений из массива построчно исходя из кода.

            public int GetDuplicateNumber(int[] array)
            {
                Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>(array.Length);
                for (int i = 0; i < array.Length; i++)
                {
                    if (dictionary.ContainsKey(array[i])) // операция ContainsKey равна O(1) 
                    {
                        return array[i];
                    }
                    else
                    {
// операция Add() - O(1) при фиксированном значении размера словаря
                        dictionary.Add(array[i], 0); // добавляем в ключи значения из массива не найденные методом ContainsKey(). Так как мы ищем методом ContainsKey() не в значения же словаря 
//добавлять значения массива
                    }
                }
                return 0;
            }


На счет ContainsKey(): здесь см. заметки
На счет Add(): здесь см. заметки
С уважением!
Re[11]: Решение за O(N) и доп. память O(N)
От: Xobotik Россия  
Дата: 06.04.10 11:08
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, Xobotik, Вы писали:


X>>Да задачу (стартовую) решили уже без применения каких-то сложных структур:


X>>здесь
Автор: Xobotik
Дата: 03.04.10

_FR>
X>>            int[] b = new int[a.Length];
_FR>


_FR>Не, так неинтересно: я про большие числа потому и спросил, что бы узнать, можно ли выделять память, пропорциональную N или M.


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

_FR>Есть известная задачка на поиск цикла в однонаправленном списке. Многие задают ей, не говоря об имеющихся ограничениях. А самое простейшее решение в таких случаях — тот же HashSet — запоминание того, что прошли в нём. Всяко быстрее догонялок будет :о))


Так уже решили, надо как-нибудь по другому.
С уважением!
Re[10]: Решение за O(N) и доп. память O(N)
От: andy1618 Россия  
Дата: 07.04.10 19:16
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Нужна другая структура данных, от которой требуется:

Б>- быстро проверять наличие элемента (на основе хэша)
Б>- быстро добавлять новый элемент

Б>>>1. Запутывает код.

X>>Отнюдь.

Б>Запутывает, потому что словарь используется не по назначению.


Да, конечно, в терминах C# надо вместо Dictionary использовать свежепоявившийся HashSet, совсем про него забыл
Re[4]: Поиск повторяющегося числа в массиве
От: andy1618 Россия  
Дата: 07.04.10 19:22
Оценка:
Здравствуйте, andy1618, Вы писали:


E>>>Эээ, а что, итерация по массиву, занесение результата в HashSet (не знаю как аналог в .NET называется)


A>В C# это называется Dictionary<T>.


Упс, совсем забыл, что в последних дот.нетах появился и чистый HashSet<K>, который, в отличие от Dictionary<K, V>, работает только с ключами.
Re[2]: Поиск повторяющегося числа в массиве
От: andy1618 Россия  
Дата: 07.04.10 19:32
Оценка: -1 :)
Здравствуйте, _FRED_, Вы писали:

_FR> неизвестно, что больше — N или M


Судя по условию задачи, N ограничено сверху значением M+1, т.к. иначе будет более одного дубликата.
Кстати, если бы было соблюдено равенство N = M + 1 (т.е. присутствовали бы все без исключения числа от 1 до M с одним дубликатом), то задача бы решалась обычным XOR-ом за O(N) без доп. памяти.
Re: Поиск повторяющегося числа в массиве
От: andy1618 Россия  
Дата: 07.04.10 19:37
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

Кстати, интересно, а откуда эта задачка?
Re: Поиск повторяющегося числа в массиве
От: Pro100Oleh Украина  
Дата: 08.04.10 06:20
Оценка: -2
Я сомневаюсь, что существует решение лутче чем через хеш (в дотнете — HashSet). Если такое решение существует, то оно должно использовать либо меньше памяти, либо меньшую временную сложность. Само существование такое алгоритма означает, что его можно использовать для стандартного хеша, у которого отсутсвует операция удаления — некий AddOnlyHashSet. А это, согласитесь, довольно таки полезный класс. То есть, если б существовал такой алгоритм — в бибилиотеках был бы специальный класс AddOnlyHashSet.
Pro
Re[3]: Поиск повторяющегося числа в массиве
От: _FRED_ Черногория
Дата: 08.04.10 06:57
Оценка: 1 (1) -1
Здравствуйте, andy1618, Вы писали:

_FR>> неизвестно, что больше — N или M


A>Судя по условию задачи, N ограничено сверху значением M+1, т.к. иначе будет более одного дубликата.


Вовсе не обязательно: в первоначальной формулировке не сказано, что какое-либо числе не может повторяться в массиве три и большее количество раз.

A>Кстати, если бы было соблюдено равенство N = M + 1 (т.е. присутствовали бы все без исключения числа от 1 до M с одним дубликатом), то задача бы решалась обычным XOR-ом за O(N) без доп. памяти.


Тогда xor был бы не нужен: достаточно получить сумму всех чисел в массиве и вычесть из неё сумму всех чисел диапазона 1..M — получим аккурат значение числа, которое встречается дважды.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Поиск повторяющегося числа в массиве
От: dilmah США  
Дата: 08.04.10 07:02
Оценка:
Здравствуйте, Pro100Oleh, Вы писали:

PO>некий AddOnlyHashSet. А это, согласитесь, довольно таки полезный класс. То есть, если б существовал такой алгоритм — в бибилиотеках был бы специальный класс AddOnlyHashSet.


Ну, вышеупомянутые фильтры Блума это и есть что типа AddOnlyHashSet
Re[4]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 09.04.10 01:57
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Тогда xor был бы не нужен: достаточно получить сумму всех чисел в массиве и вычесть из неё сумму всех чисел диапазона 1..M — получим аккурат значение числа, которое встречается дважды.


Только больно медленный этот метод.
С уважением!
Re[5]: Поиск повторяющегося числа в массиве
От: andy1618 Россия  
Дата: 09.04.10 02:52
Оценка: -1
Здравствуйте, Xobotik, Вы писали:

_FR>>Тогда xor был бы не нужен: достаточно получить сумму всех чисел в массиве и вычесть из неё сумму всех чисел диапазона 1..M — получим аккурат значение числа, которое встречается дважды.


X>Только больно медленный этот метод.


Да ладно, это как раз практически идеальный метод — требуется только один проход с суммированием плюс несколько арифметических действий. Быстрее на стандартных компьютерных архитектурах вряд ли получится!
Но, как написано выше, этот алгоритм относится к частному случаю N=M+1 (т.е. в исходном массиве есть ВСЕ числа от 1 до M плюс какое-то число встречается дважды).
Re[5]: Поиск повторяющегося числа в массиве
От: _FRED_ Черногория
Дата: 09.04.10 03:49
Оценка:
Здравствуйте, Xobotik, Вы писали:

_FR>>Тогда xor был бы не нужен: достаточно получить сумму всех чисел в массиве и вычесть из неё сумму всех чисел диапазона 1..M — получим аккурат значение числа, которое встречается дважды.


X>Только больно медленный этот метод.


Какой именно? Это так же один проход по массиву.
Help will always be given at Hogwarts to those who ask for it.
Re: Поиск повторяющегося числа в массиве
От: Аноним  
Дата: 09.04.10 15:47
Оценка: 11 (2)
Для обхода проблемы с O(M) инициализацией можно посмотреть в сторону http://research.swtch.com/2008/03/using-uninitialized-memory-for-fun-and.html
Re: Поиск повторяющегося числа в массиве
От: -VladK-  
Дата: 09.04.10 16:11
Оценка: -1
Народ, да вы че?
сколько уже прочитал вариантов и некто не догадался просто просуммировать массив и сравнить с суммой арифметической прогрессии ?!
й
Re[2]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.04.10 16:23
Оценка:
Здравствуйте, -VladK-, Вы писали:

VK>Народ, да вы че?

VK>сколько уже прочитал вариантов и некто не догадался просто просуммировать массив и сравнить с суммой арифметической прогрессии ?!

Разве в условии сказано что N = M + 1?
N = 10, M = 1000. Куда приложить прогрессию?
Re[3]: Поиск повторяющегося числа в массиве
От: Аноним  
Дата: 10.04.10 05:42
Оценка: -1 :)
Здравствуйте, samius, Вы писали:

S>Здравствуйте, -VladK-, Вы писали:


VK>>Народ, да вы че?

VK>>сколько уже прочитал вариантов и некто не догадался просто просуммировать массив и сравнить с суммой арифметической прогрессии ?!

S>Разве в условии сказано что N = M + 1?

S>N = 10, M = 1000. Куда приложить прогрессию?

"Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
число в этом массиве повторяется два раза." Раз повторяется одно число, значит N = M + 1.
Re[2]: Поиск повторяющегося числа в массиве
От: andy1618 Россия  
Дата: 10.04.10 06:35
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Для обхода проблемы с O(M) инициализацией можно посмотреть в сторону http://research.swtch.com/2008/03/using-uninitialized-memory-for-fun-and.html


Да, круто!
Но для обсуждаемой задачки при больших M (например, 2^64) этот подход будет неприменим из-за необходимости аллоцировать O(M) памяти (пусть и грязной) под массив sparse.
Re[4]: Поиск повторяющегося числа в массиве
От: andy1618 Россия  
Дата: 10.04.10 06:40
Оценка: +1
Здравствуйте, Аноним, Вы писали:

S>>Разве в условии сказано что N = M + 1?

S>>N = 10, M = 1000. Куда приложить прогрессию?

А>"Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно

А>число в этом массиве повторяется два раза." Раз повторяется одно число, значит N = M + 1.

У меня сначала тоже такая мысль была. Но я решил, что тогда бы не стали парить мозги и написали бы, что дан массив из M+1 чисел.
А вообще, интересно, откуда эта задачка взялась: если из института с лабораторной работы — это одно, если с крутой олимпиады по информатике — это другое
Re[5]: Поиск повторяющегося числа в массиве
От: Аноним  
Дата: 10.04.10 08:57
Оценка: :))
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, Аноним, Вы писали:


S>>>Разве в условии сказано что N = M + 1?

S>>>N = 10, M = 1000. Куда приложить прогрессию?

А>>"Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно

А>>число в этом массиве повторяется два раза." Раз повторяется одно число, значит N = M + 1.

A>У меня сначала тоже такая мысль была. Но я решил, что тогда бы не стали парить мозги и написали бы, что дан массив из M+1 чисел.

A>А вообще, интересно, откуда эта задачка взялась: если из института с лабораторной работы — это одно, если с крутой олимпиады по информатике — это другое

Парят специально — ты должен догадаться что N = M + 1.
Да нет задачка на сообразительность, на олипмиадную не тянет, максимум на школьную олимпиаду.
Меня спросили на собеседовании эту задачу — мое решение было как раз с прогрессией, они свой вариант не сказали, но я думаю что лучше ничего не придумаешь тут.
Re[4]: Поиск повторяющегося числа в массиве
От: IROV..  
Дата: 10.04.10 10:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, samius, Вы писали:


S>>Здравствуйте, -VladK-, Вы писали:


VK>>>Народ, да вы че?

VK>>>сколько уже прочитал вариантов и некто не догадался просто просуммировать массив и сравнить с суммой арифметической прогрессии ?!

S>>Разве в условии сказано что N = M + 1?

S>>N = 10, M = 1000. Куда приложить прогрессию?

А>"Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно

А>число в этом массиве повторяется два раза." Раз повторяется одно число, значит N = M + 1.

N <= M + 1

1,3,101

M = 101
N = 3

все довольны, так что не катит
я не волшебник, я только учусь!
Re: Поиск повторяющегося числа в массиве
От: IROV..  
Дата: 10.04.10 10:31
Оценка: +1
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

Самое простое выделить второй масив из M элементов
пройтись по по первому масиву N и в масиве M возвести флаг по значению, если флаг есть — то вот и оно

for( n in N ):
 if ++M[n] == 2:
  return n


а если без памяти порядка M нужно думать, ушел думать
я не волшебник, я только учусь!
Re[2]: Поиск повторяющегося числа в массиве
От: VEAPUK  
Дата: 10.04.10 10:57
Оценка:
Здравствуйте, IROV.., Вы писали:

Специально для Dufrenite.

IRO>
IRO>for( n in N ):
IRO> if ++M[n] == 2:
IRO>  return n
IRO>


Сколько стоит операция (n in N)?
Re[5]: Поиск повторяющегося числа в массиве
От: Аноним  
Дата: 10.04.10 11:45
Оценка: -1
Здравствуйте, IROV.., Вы писали:

IRO>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, samius, Вы писали:


S>>>Здравствуйте, -VladK-, Вы писали:


VK>>>>Народ, да вы че?

VK>>>>сколько уже прочитал вариантов и некто не догадался просто просуммировать массив и сравнить с суммой арифметической прогрессии ?!

S>>>Разве в условии сказано что N = M + 1?

S>>>N = 10, M = 1000. Куда приложить прогрессию?

А>>"Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно

А>>число в этом массиве повторяется два раза." Раз повторяется одно число, значит N = M + 1.

IRO>N <= M + 1


IRO>1,3,101


IRO>M = 101

IRO>N = 3

IRO>все довольны, так что не катит


Тогда нужно уточнение условия.
Каюсь, не посмотрел внимательно, в моем варианте это звучало именно как не отсортированный массив элементов без пробелов + один лишний.
Re[2]: Поиск повторяющегося числа в массиве
От: -VladK-  
Дата: 10.04.10 11:52
Оценка:
Здравствуйте, IROV.., Вы писали:

IRO> Здравствуйте, Xobotik, Вы писали:


X>>Условие задачи:

X>>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>>число в этом массиве повторяется два раза. Найти это число за время O(N).

IRO>Самое простое выделить второй масив из M элементов

IRO>пройтись по по первому масиву N и в масиве M возвести флаг по значению, если флаг есть — то вот и оно

IRO>
IRO>for( n in N ):
IRO> if ++M[n] == 2:
IRO>  return n
IRO>


IRO>а если без памяти порядка M нужно думать, ушел думать



Если M большое то нехорошо выйдет, как более щадящий вариант можно массив флагов, но использовать как битовую маску — хотя тоже размер такого массива пропорционален M, хоть и меньше.
Re[3]: Поиск повторяющегося числа в массиве
От: VEAPUK  
Дата: 10.04.10 16:00
Оценка:
Здравствуйте, -VladK-, Вы писали:

VK>Если M большое то нехорошо выйдет, как более щадящий вариант можно массив флагов, но использовать как битовую маску — хотя тоже размер такого массива пропорционален M, хоть и меньше.


Специально для Dufrenite.

Остальные не могут встречаться 3 и более раза?
Re[11]: Решение за O(N) и доп. память O(N)
От: batu Украина  
Дата: 11.04.10 07:11
Оценка:
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, Буравчик, Вы писали:


Б>>Нужна другая структура данных, от которой требуется:

Б>>- быстро проверять наличие элемента (на основе хэша)
Б>>- быстро добавлять новый элемент

Б>>>>1. Запутывает код.

X>>>Отнюдь.

Б>>Запутывает, потому что словарь используется не по назначению.


A>Да, конечно, в терминах C# надо вместо Dictionary использовать свежепоявившийся HashSet, совсем про него забыл

Чего мучаетесь? Хэш-функцию можно самому придумать в зависимости от задачи. Типа сумма битов, или младшие биты выделить. В зависимости от конкретного значения M и N.
Re[3]: Поиск повторяющегося числа в массиве
От: IROV..  
Дата: 12.04.10 12:38
Оценка:
Здравствуйте, VEAPUK, Вы писали:

VEA>Здравствуйте, IROV.., Вы писали:


VEA>Специально для Dufrenite.


IRO>>
IRO>>for( n in N ):
IRO>> if ++M[n] == 2:
IRO>>  return n
IRO>>


VEA>Сколько стоит операция (n in N)?

это цыкл перебор всех элементов N
я не волшебник, я только учусь!
Re[4]: Поиск повторяющегося числа в массиве
От: VEAPUK  
Дата: 13.04.10 15:31
Оценка:
Здравствуйте, IROV.., Вы писали:

IRO>Здравствуйте, VEAPUK, Вы писали:


VEA>>Здравствуйте, IROV.., Вы писали:


VEA>>Специально для Dufrenite.


IRO>>>
IRO>>>for( n in N ):
IRO>>> if ++M[n] == 2:
IRO>>>  return n
IRO>>>


VEA>>Сколько стоит операция (n in N)?

IRO>это цыкл перебор всех элементов N

Не узнал for each

А если какое-либо число встречается более 2-х раз?
Re[6]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 13.04.10 18:06
Оценка: -1
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, Xobotik, Вы писали:


_FR>>>Тогда xor был бы не нужен: достаточно получить сумму всех чисел в массиве и вычесть из неё сумму всех чисел диапазона 1..M — получим аккурат значение числа, которое встречается дважды.


X>>Только больно медленный этот метод.


_FR>Какой именно? Это так же один проход по массиву.


Я просто вас не правильно понял. Просто при реализации данного метода я инициализировал массив суммы диапазона, потом додумался до этого:

        public Int64 GetDuplicateNumber6(int[] array)
        {
            return array.Sum() - array.Distinct().Sum();
        }


Правда от переполнения не застрахованы, но можно как то наверно застраховаться используя частичные суммы.
С уважением!
Re[6]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 13.04.10 18:28
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Тогда нужно уточнение условия.

А>Каюсь, не посмотрел внимательно, в моем варианте это звучало именно как не отсортированный массив элементов без пробелов + один лишний.

Задача дана точно.
С уважением!
Re[3]: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 13.04.10 19:04
Оценка:
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, Аноним, Вы писали:


А>>Для обхода проблемы с O(M) инициализацией можно посмотреть в сторону http://research.swtch.com/2008/03/using-uninitialized-memory-for-fun-and.html


A>Да, круто!

A>Но для обсуждаемой задачки при больших M (например, 2^64) этот подход будет неприменим из-за необходимости аллоцировать O(M) памяти (пусть и грязной) под массив sparse.
Да уже писал.. Хэш фукцию сделайте.. Например, по модулю N. Можно просто по модулю ближайшего большего числа степени 2. Что б не делить, а использовать логическую операцию И.
Re[7]: Поиск повторяющегося числа в массиве
От: _FRED_ Черногория
Дата: 13.04.10 19:51
Оценка:
Здравствуйте, Xobotik, Вы писали:

_FR>>>>Тогда xor был бы не нужен: достаточно получить сумму всех чисел в массиве и вычесть из неё сумму всех чисел диапазона 1..M — получим аккурат значение числа, которое встречается дважды.


X>>>Только больно медленный этот метод.

_FR>>Какой именно? Это так же один проход по массиву.

X>Я просто вас не правильно понял. Просто при реализации данного метода я инициализировал массив суммы диапазона, потом додумался до этого:

X>        public Int64 GetDuplicateNumber6(int[] array)
X>        {
X>            return array.Sum() - array.Distinct().Sum();
X>        }

X>Правда от переполнения не застрахованы, но можно как то наверно застраховаться используя частичные суммы.

Посчитай, сколько здесь проходов по массиву и линейная ли сложность. Удивишся Задача же решается одним лишь вызовом array.Sum() и несколькими математическими операциями, никак не связанными с массивом. Другими словами, то, как в данной задаче вычислить "array.Distinct().Sum()" объяснялось в пятом классе средней школы и я выше даже приводил ссылку на решение.
Help will always be given at Hogwarts to those who ask for it.
Re[8]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 14.04.10 19:55
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Посчитай, сколько здесь проходов по массиву и линейная ли сложность. Удивишся Задача же решается одним лишь вызовом array.Sum() и несколькими математическими операциями, никак не связанными с массивом. Другими словами, то, как в данной задаче вычислить "array.Distinct().Sum()" объяснялось в пятом классе средней школы и я выше даже приводил ссылку на решение.


Да это то понятно, дело в том, что если на входе массив { 1, 500, 600, 1 }, то данный метод недействителен.
С уважением!
Re[5]: Поиск повторяющегося числа в массиве
От: IROV..  
Дата: 15.04.10 12:44
Оценка:
Здравствуйте, VEAPUK, Вы писали:

VEA>А если какое-либо число встречается более 2-х раз?

Я думаю тут стоит уточнить задание, как мне показалось речь идет о масиве в котором все числа встречаются 1 раз, и только одно два раза.
если же нет

нужен будет еще один проход по M для того что бы найти число которое встречается именно 2 раза.

тоесть O(N + M) + M памяти.

я не волшебник, я только учусь!
Re[6]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 20.04.10 17:33
Оценка:
Здравствуйте, IROV.., Вы писали:

IRO>Здравствуйте, VEAPUK, Вы писали:


VEA>>А если какое-либо число встречается более 2-х раз?

IRO>Я думаю тут стоит уточнить задание, как мне показалось речь идет о масиве в котором все числа встречаются 1 раз, и только одно два раза.
IRO>если же нет

IRO>нужен будет еще один проход по M для того что бы найти число которое встречается именно 2 раза.


IRO>тоесть O(N + M) + M памяти.


IRO>


Ну а зачем уточнять, если точно написано, что дан массив из целых чисел, принимающих значений от 1 до М и один повтор. Подчеркиваю связку "...целых чисел, принимающих значения"
С уважением!
Re[10]: Решение за O(N) и доп. память O(N)
От: OlegMax  
Дата: 26.04.10 15:09
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Да задачу (стартовую) решили уже без применения каких-то сложных структур:


X>
X>        private static int foo(int[] a)
X>        {
X>            int[] b = new int[a.Length];
X>            for (int i = 0; i < a.Length; i++)
X>            {
X>                if (b[a[i]] == 0)
X>                {
X>                    b[a[i]] = a[i];
X>                }
X>                else
X>                {
X>                    return a[i];
X>                }
X>            }
X>            return 0;
X>        }
X>


X>Теперь просто пытаемся найти еще другие методы решения задачи.


Попробуем мысленно прогнать на последовательности {3,3}. Получим "index out of bounds".
Re[7]: Поиск повторяющегося числа в массиве
От: IROV..  
Дата: 29.04.10 14:52
Оценка: 2 (1)
Здравствуйте, Xobotik, Вы писали:

X>Здравствуйте, IROV.., Вы писали:


IRO>>Здравствуйте, VEAPUK, Вы писали:


VEA>>>А если какое-либо число встречается более 2-х раз?

IRO>>Я думаю тут стоит уточнить задание, как мне показалось речь идет о масиве в котором все числа встречаются 1 раз, и только одно два раза.
IRO>>если же нет

IRO>>нужен будет еще один проход по M для того что бы найти число которое встречается именно 2 раза.


IRO>>тоесть O(N + M) + M памяти.


IRO>>


X>Ну а зачем уточнять, если точно написано, что дан массив из целых чисел, принимающих значений от 1 до М и один повтор. Подчеркиваю связку "...целых чисел, принимающих значения"


1 вариант, когда количество чисел N = M + 1 — [1,2,3,4,5,5]
2 вариант, когда количество чисел N <= M + 1 — [1,3,5,5]
3 вариант, когда количество чисел N != M [1,1,1,2,2,2,3,3,3,4,4,4,5,5]

и __ВСЕ__ эти варианты удовлетворяют условию.
я не волшебник, я только учусь!
Re: Поиск повторяющегося числа в массиве
От: lxa http://aliakseis.livejournal.com
Дата: 04.05.10 08:53
Оценка: 9 (2)
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

X>...


X>Есть ли какие-либо другие пути решения задачи?


Вот нагуглилось что-то вроде интересное:
http://aperiodic.net/phil/archives/Geekery/find-duplicate-elements.html
Re[2]: Поиск повторяющегося числа в массиве
От: andy1618 Россия  
Дата: 04.05.10 22:48
Оценка:
Здравствуйте, lxa, Вы писали:

lxa>Вот нагуглилось что-то вроде интересное:

lxa>http://aperiodic.net/phil/archives/Geekery/find-duplicate-elements.html

Классная ссылка! Последний подход (с обнаружением цикла у графа методом "догонялок") красивый, но он не будет работать для той трактовки задачи, когда N < M+1 (например, на упомянутом выше массиве: { 1, 500, 600, 1 } ).
Т.е. пока что все решения для такой трактовки требуют доп. память.
Re[8]: Поиск повторяющегося числа в массиве
От: Xobotik Россия  
Дата: 10.05.10 22:41
Оценка:
Здравствуйте, IROV.., Вы писали:

IRO>1 вариант, когда количество чисел N = M + 1 — [1,2,3,4,5,5]

IRO>2 вариант, когда количество чисел N <= M + 1 — [1,3,5,5]

Это все понятно.

IRO>3 вариант, когда количество чисел N != M [1,1,1,2,2,2,3,3,3,4,4,4,5,5]


Давайте еще раз повторим условие задачи:

Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
число в этом массиве повторяется два раза. Найти это число за время O(N).

"Найти это число за время O(N)." — говорит нам о том, что в массиве один повтор ищется за время O(N), ну а остальные, если они есть, ищутся тоже за это же самое время (Хотя об этом не слова, что в массиве может быть какое-либо K повторов).

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

P.S. я мог ошибиться в размышлениях, заранее сорри.
С уважением!
Re[11]: Решение за O(N) и доп. память O(N)
От: Xobotik Россия  
Дата: 12.05.10 07:44
Оценка:
Здравствуйте, OlegMax, Вы писали:

OM>Попробуем мысленно прогнать на последовательности {3,3}. Получим "index out of bounds".


Ну тогда буферный массив будет выглядеть следующим образом:
int[] buf = new int[array.Max() + 1];
С уважением!
Re[10]: Решение за O(N) и доп. память O(N)
От: Dufrenite Дания  
Дата: 20.08.10 14:37
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Да задачу (стартовую) решили уже без применения каких-то сложных структур:


X>здесь
Автор: Xobotik
Дата: 03.04.10


X>
X>        private static int foo(int[] a)
X>        {
X>            int[] b = new int[a.Length];
X>            for (int i = 0; i < a.Length; i++)
X>            {
X>                if (b[a[i]]== 0)
X>                {
X>                    b[a[i]] = a[i];
X>                }
X>                else
X>                {
X>                    return a[i];
X>                }
X>            }
X>            return 0;
X>        }
X>


X>Теперь просто пытаемся найти еще другие методы решения задачи.


Ошибка в программе. Тебе на неё указали, ты проигнорировал.

Напиши и запусти:


void Main()
{
  foo(new int[] { 1000, 1000 });
}
Re: Поиск повторяющегося числа в массиве
От: Аноним  
Дата: 09.09.10 12:46
Оценка: -1 :)
Здравствуйте, Xobotik, Вы писали:

оверквотинг — зло.

Пройит в цикле по массиву и отXORить числа, повт. дадут нуль
Re[2]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.09.10 17:35
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Xobotik, Вы писали:


А>Пройит в цикле по массиву и отXORить числа, повт. дадут нуль


Каждое с каждым ксорить что ли?

а другие варианты какие? Подряд все ксорить?

xor(1, 2, 3) даст 0.
Re: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 09.09.10 20:28
Оценка: -1
Здравствуйте, Xobotik, Вы писали:


X>Заранее спасибо!

баян..
Резервируем массив ar [m] инициируем его нулями

И каждое новое значение аi
Записываем единичку в ar[ai] перед этим проверяя не равно ли оно 1.
Если равно 1 то это значение уже встречалось.
Один цикл по N, да и то не полностью с надеждой что повторяющееся встретится раньше.
fOR I=0 TO N
IF AR[AI]<>1 THEN AR[AI]=1 ELSE EXIT FOR
NEXT I
Re[2]: Поиск повторяющегося числа в массиве
От: blackhearted Украина  
Дата: 10.09.10 15:01
Оценка:
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, Xobotik, Вы писали:


X>>Условие задачи:

X>>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>>число в этом массиве повторяется два раза. Найти это число за время O(N).

A>Кстати, интересно, а откуда эта задачка?


Похоже на гуглособеседование по телефону.
Re: Поиск повторяющегося числа в массиве
От: Hamlet Армения  
Дата: 11.09.10 19:29
Оценка: -1 :))
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

Решение тривиально. Заводим массив бит ММ с размером M инициализируя нульями.
Пробегая через массив с размером N усатавливаем соответствующий бит (тоесть n-ный бит, где n текущий элемент из N)
в массиве ММ если неустановлен, иначе текущий элемент искомый.
Re[2]: Поиск повторяющегося числа в массиве
От: dilmah США  
Дата: 11.09.10 19:50
Оценка:
слушай, ты настоящий Кэп, не могу подобрать точный титул
Re: Поиск повторяющегося числа в массиве
От: zdv Россия  
Дата: 11.05.11 07:01
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

X>Реализация:

X>
X>private static string separator = ";";
X>        static void Main(string[] args)
X>        {
X>            int[] result = GetIntArray(InputArray());
X>            PrintArray(result);
X>            Console.WriteLine(ff(result));
X>            Console.ReadLine();
X>        }
X>        private static string InputArray()
X>        {
X>            Console.WriteLine("Введите массив, содержащий только целые числа.");
X>            Console.WriteLine("После каждого числа ставьте разделитель '{0}'", separator);
X>            Console.WriteLine("Введите массив: ");
X>            return Console.In.ReadLine();
X>        }
X>        private static int[] GetIntArray(string insert)
X>        {
X>            string pattern = String.Format("{0}(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))", separator);
X>            string[] bufResult = Regex.Split(insert, pattern);
X>            int[] result = new int[bufResult.Length];
X>            for (int i = 0; i < bufResult.Length; i++)
X>            {
X>                result[i] = Int32.Parse(bufResult[i]);
X>            }
X>            return result;
X>        }
X>        private static void PrintArray(int[] array)
X>        {
X>            foreach(int i in array)
X>            {
X>                Console.WriteLine(i);
X>            }
X>        }
X>        private static int ff(int[] array)
X>        {
X>            int m = 1;
X>            int buf = 0;
X>            // общее количество сравнений (n-1)^2, где n - длина массива
X>            for (int i = 0; i < (array.Length - 1) * (array.Length - 1); i++)
X>            {
X>                // количество перестановок (n-1) = количеству сравнений array[0] и array[k], где k - числа от 1 до n (n - длина массива)
X>                for (int j = 1; j < array.Length; j++)
X>                {
X>                    if (array[0] == array[j])
X>                    {
X>                        buf = array[0];
X>                        goto result;
X>                    }
X>                }
X>                Swap(array, m);
X>                m++;
X>            }
X>        result:
X>        return buf;
X>        }
X>        private static void Swap(int[] array, int index)
X>        {
X>            int temp = array[index];
X>            array[index] = array[0];
X>            array[0] = temp;
X>        }
X>


X>Есть ли какие-либо другие пути решения задачи? Без goto не вижу решения задачи, если использовать break, там где buf = array[0] , останавливается только цикл:


X>
X>for (int j = 1; j < array.Length - 1; j++)
X>


X>при этом работа цикла


X>
X>for (int i = 0; i < (array.Length - 1) * (array.Length - 1); i++)
X>


X>не прерывается


X>Заранее спасибо!


В подобных случаях, мне кажется, goto вполне оправдано
С уважением, Дмитрий
Re: Поиск повторяющегося числа в массиве
От: LaptevVV Россия  
Дата: 11.05.11 07:05
Оценка: 20 (3) +1
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

Народ, чего-то много наворотили. Теорию не читаем?
Целые числа сортируются за время O(N) поразрядной сортировкой. И все.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.05.11 07:29
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Здравствуйте, Xobotik, Вы писали:


X>>Условие задачи:

X>>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>>число в этом массиве повторяется два раза. Найти это число за время O(N).

LVV>Народ, чего-то много наворотили. Теорию не читаем?

LVV>Целые числа сортируются за время O(N) поразрядной сортировкой. И все.
для поиска повторов не важно, целые ли числа.
Re[3]: Поиск повторяющегося числа в массиве
От: B0FEE664  
Дата: 11.05.11 11:03
Оценка:
Здравствуйте, dilmah, Вы писали:

D>слушай, ты настоящий Кэп, не могу подобрать точный титул


Кэп подсказывает, что если:
"число в этом массиве повторяется два раза"
то встречается оно трижды
так?
И каждый день — без права на ошибку...
Re[3]: Поиск повторяющегося числа в массиве
От: LaptevVV Россия  
Дата: 11.05.11 12:08
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, LaptevVV, Вы писали:


LVV>>Здравствуйте, Xobotik, Вы писали:


X>>>Условие задачи:

X>>>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>>>число в этом массиве повторяется два раза. Найти это число за время O(N).

LVV>>Народ, чего-то много наворотили. Теорию не читаем?

LVV>>Целые числа сортируются за время O(N) поразрядной сортировкой. И все.
S>для поиска повторов не важно, целые ли числа.
Это принципиально. В постановке явно указано о целых именно поэтому.
Кроме того, можно за 1 проход исходного массива, имея массив размером М, найти это число.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Поиск повторяющегося числа в массиве
От: LaptevVV Россия  
Дата: 11.05.11 12:20
Оценка: +2
Здравствуйте, samius, Вы писали:

S>Здравствуйте, LaptevVV, Вы писали:


LVV>>Здравствуйте, Xobotik, Вы писали:


X>>>Условие задачи:

X>>>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>>>число в этом массиве повторяется два раза. Найти это число за время O(N).

LVV>>Народ, чего-то много наворотили. Теорию не читаем?

LVV>>Целые числа сортируются за время O(N) поразрядной сортировкой. И все.
S>для поиска повторов не важно, целые ли числа.
А, понял! Ты имеешь ввиду, что два одинаковых вещественных все равно встанут рядом, если применить поразрядную сортировку к битовому представлению вещественных. Да, логично...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Поиск повторяющегося числа в массиве
От: vsb Казахстан  
Дата: 13.05.11 06:22
Оценка: -1 :)
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

Если M < N, то вот решение. Не выделяет лишней памяти, не изменяет исходный массив. Печатает одно из чисел, которые повторяются 2 или более раз.

        int[] a = {2, 2, 2, 2};
        int i, j;
        
        i = j = a.length - 1;
        do {
            i = a[i];
            j = a[a[j]];
        } while (i != j);
        
        j = a.length - 1;
        do {
            i = a[i];
            j = a[j];
        } while (i != j);
        
        System.out.println(i);
Re[2]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 13.05.11 06:36
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Здравствуйте, Xobotik, Вы писали:


vsb>Если M < N, то вот решение. Не выделяет лишней памяти, не изменяет исходный массив. Печатает одно из чисел, которые повторяются 2 или более раз.

int[] a = { 1, 3, 2, 1, 4 };
выдает 4
Re[3]: Поиск повторяющегося числа в массиве
От: vsb Казахстан  
Дата: 13.05.11 06:41
Оценка: -1 :)
Здравствуйте, samius, Вы писали:

S>Здравствуйте, vsb, Вы писали:


vsb>>Здравствуйте, Xobotik, Вы писали:


vsb>>Если M < N, то вот решение. Не выделяет лишней памяти, не изменяет исходный массив. Печатает одно из чисел, которые повторяются 2 или более раз.

S>int[] a = { 1, 3, 2, 1, 4 };
S>выдает 4

N = 5, M = 5, условие не удовлетворено. В общем цифры надо считать с нуля. Если каждое число в вашем примере уменьшить на единицу, то всё работает.
Re[4]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 13.05.11 06:43
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Здравствуйте, samius, Вы писали:


S>>Здравствуйте, vsb, Вы писали:


vsb>>>Здравствуйте, Xobotik, Вы писали:


vsb>>>Если M < N, то вот решение. Не выделяет лишней памяти, не изменяет исходный массив. Печатает одно из чисел, которые повторяются 2 или более раз.

S>>int[] a = { 1, 3, 2, 1, 4 };
S>>выдает 4

vsb>N = 5, M = 5, условие не удовлетворено. В общем цифры надо считать с нуля. Если каждое число в вашем примере уменьшить на единицу, то всё работает.


Вы условие задачи читали? Числа от 1-го до M!
Re[5]: Поиск повторяющегося числа в массиве
От: vsb Казахстан  
Дата: 13.05.11 06:50
Оценка: -1 :)
Здравствуйте, samius, Вы писали:

S>Здравствуйте, vsb, Вы писали:


vsb>>Здравствуйте, samius, Вы писали:


S>>>Здравствуйте, vsb, Вы писали:


vsb>>>>Здравствуйте, Xobotik, Вы писали:


vsb>>>>Если M < N, то вот решение. Не выделяет лишней памяти, не изменяет исходный массив. Печатает одно из чисел, которые повторяются 2 или более раз.

S>>>int[] a = { 1, 3, 2, 1, 4 };
S>>>выдает 4

vsb>>N = 5, M = 5, условие не удовлетворено. В общем цифры надо считать с нуля. Если каждое число в вашем примере уменьшить на единицу, то всё работает.


S>Вы условие задачи читали? Числа от 1-го до M!


Не придирайтесь Пусть будут от 0 до M-1, это ничего не изменит, если надо для исходной задачи — просто -1 написать в некоторых местах.


        int[] a = { 1, 5, 1, 4, 3 };
        int i, j;
        
        i = j = a.length - 1;
        do {
            i = a[i] - 1;
            j = a[a[j] - 1] - 1;
        } while (i != j);
        
        j = a.length - 1;
        do {
            i = a[i] - 1;
            j = a[j] - 1;
        } while (i != j);
        
        System.out.println(i + 1);

Вот вариант, для исходного условия.
Re: Поиск повторяющегося числа в массиве
От: Sabrian  
Дата: 22.05.11 15:10
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

Как то так.
        static int M = int.MaxValue;
        static int BITS = (int)Math.Ceiling(Math.Log(M) / Math.Log(2));

        static void Sort(ref int[] array)
        {
            int[] buffer = new int[array.Length];
            for (int k = 0; k < BITS; ++k)
            {
                int mask = 1 << k;
                int count = 0;
                for (int i = 0; i < array.Length; ++i)
                {
                    if ((array[i] & mask) == 0) ++count;
                }

                int min = 0;
                
                for (int i = 0; i < array.Length; ++i)
                {
                    if ((array[i] & mask) == 0)
                    {
                        buffer[min++] = array[i];
                    }
                    else buffer[count++] = array[i];
                }
                
                int[] temp = array;
                array = buffer;
                buffer = temp;
            }
        }


        static void Main(string[] args)
        {
            int[] arr = new int[] { 5, 7, 2, 111, 4235, 0, 3, 11, 5251254, 9, 7 };
            Sort(ref arr);

            for(int i = 1; i < arr.Length; ++i)
            {
                if (arr[i - 1] == arr[i]) Console.WriteLine(arr[i]);
            }
        }

Требует O(N) дополнительной памяти и вообще говоря выполняется за время O(N * log M). Но в условии не сказано, что log M нельзя считать константой, и решение никак не должно зависеть от M. Полагаю это и не возможно.
Re[2]: Поиск повторяющегося числа в массиве
От: ArtDenis Россия  
Дата: 25.05.11 03:16
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Здравствуйте, Xobotik, Вы писали:


LVV>Целые числа сортируются за время O(N) поразрядной сортировкой. И все.


Спасибо! Не знал, что есть такая сортировка для целых чисел.
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: Поиск повторяющегося числа в массиве
От: uxio  
Дата: 30.06.11 12:27
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).


using System;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            var array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 15, 16, 17, 18, 19, 20 };
            var duplicate = array.Sum(i => i) - GetProgressionSum(array.Length - 1, 1);

            Console.WriteLine(duplicate);
        }

        static int GetProgressionSum(int length, int step)
        {
            var result = 0;

            for (var i = 1; i <= length; i+=step)
            {
                result += i;
            }

            return result;
        }
    }
}
Re[2]: Поиск повторяющегося числа в массиве
От: Аноним  
Дата: 01.07.11 13:32
Оценка:
Здравствуйте, uxio, Вы писали:

U>Здравствуйте, Xobotik, Вы писали:


X>>Условие задачи:

X>>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>>число в этом массиве повторяется два раза. Найти это число за время O(N).

могу на VB

DIM S(M) AS byte
DIM data(N) AS long
' заполняем data
.
.
FOR I = 1 TO N
if S( data(i) ) = 0 then
S( data(i) ) = 1
else
' повтор — ура нашли!
exit for
endif
next
msgbox S( data(i) )
Re: Поиск повторяющегося числа в массиве
От: lastcross  
Дата: 04.07.11 15:16
Оценка: -1 :)
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

Как то лениво искать по всей ветке. Наверное вариант с xor уже звучал, да?
Re[2]: Поиск повторяющегося числа в массиве
От: IROV..  
Дата: 18.07.11 14:55
Оценка:
Здравствуйте, lastcross, Вы писали:

L>Здравствуйте, Xobotik, Вы писали:


X>>Условие задачи:

X>>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>>число в этом массиве повторяется два раза. Найти это число за время O(N).

L>Как то лениво искать по всей ветке. Наверное вариант с xor уже звучал, да?

"Слышал звон, да не знает где он"(с)

XOR ищет из повторяющих — одно не повторяющееся, тут задача наоборот
я не волшебник, я только учусь!
Re[6]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 19.07.11 00:15
Оценка:
Здравствуйте, elmal, Вы писали:

E>Здравствуйте, samius, Вы писали:


S>>Судя по всему речь о другой задаче, в которой все числа кроме одного встречаются четное число раз.

E>Принцип тот же самый .

Принцип тот же самый?
И ты сходу такое решаешь? Да не гони.
Решал когда-то такую задачку на тестовое задание, но я принцип решения нагуглил.
Вот мой код:

#include "stdafx.h"
#include <algorithm>

using namespace std;
typedef unsigned char BYTE;


//
// Random test array, containing 2 the same numbers.
//

static unsigned test_array[] = 
{
    198, 258, 511, 173, 896, 415, 355, 71, 9012, 8, 15, 174, 886,
    357, 422, 86, 114, 20, 544, 300, 2221, 41, 205, 278, 877, 66,
    431, 30, 5002, 10, 54, 12, 82, 7019, 377, 4, 15906, 511, 123,
    2233, 8018, 11, 20501, 911, 6034, 1111, 4448, 9876, 35461, 9,
    8192,
};

const unsigned NumElementsInTestArray = sizeof( test_array ) / sizeof( unsigned int );


/*
 ******************************************************************************
 *
 * Function Name:           CreateCounters()
 *
 * Function Purpose:        Creates counter arrays.
 *
 * Function Description:    Fill counter arrays with the amount of the numbers 
 *                          in the sorting array (data) with the given byte 
 *                          value for the each byte position.
 * Arguments:
 *      unsigned * data     - [in] Data that are going to be sorted.
 *      unsigned * counters - [out] Counters arrays.
 *      unsigned const N    - [in] Number of elements in the data array.
 *      
 *
 * Return value:            None.
 *
 * Revision History:
 *
 *      03/02/2009:         Created.
 *
 ******************************************************************************
*/
static void CreateCounters( unsigned * data, unsigned * counters, unsigned const N )
{
    //
    // Counters array number i is placed at address ( counters + 256 * i )
    //
    
    memset(
        counters, 
        0, 
        256 * sizeof( unsigned ) * sizeof( long )
        ); 
    
    BYTE * pb    = ( BYTE* ) data;
    BYTE * pbEnd = ( BYTE* )( data + N );

    while( pb != pbEnd )
    {
        for( int i = 0; i < sizeof( unsigned ); i++, pb++ )
        {
            counters[ 256 * i + *pb ] ++ ;
        }
    }
}


/*
 ******************************************************************************
 *
 * Function Name:           RadixPass()
 *
 * Function Purpose:        One pass and sort for the given key position.
 *
 * Function Description:    
 *
 * Arguments:
 *      int          offset  - [in]  Key (byte) position (0..3);
 *      const long   N       - [in]  Size of sorting array .
 *      unsigned *   inArr   - [in]  Sorting array.
 *      unsigned *   outArr  - [out] Resulting array.
 *      unsigned *   cntrArr - [in]  Array of counters.
 *      
 *
 * Return value:            None.
 *
 * Revision History:
 *
 *      03/02/2009:         Created.
 *
 ******************************************************************************
*/
static void RadixPass( int          offset, 
                       const long   N, 
                       unsigned *   inArr, 
                       unsigned *   outArr, 
                       unsigned *   cntrArr )
{
    unsigned long sum = 0;
    unsigned long tmp;
    
    unsigned * pCntrArr             = cntrArr;
    const unsigned * const cntrEnd  = cntrArr + 256;

    for( ; pCntrArr != cntrEnd; pCntrArr++ )
    {
        tmp         = *pCntrArr;
        *pCntrArr   = sum;
        sum        += tmp;
    }
    
    BYTE * pb = ( BYTE* )inArr + offset;
    unsigned * pInArr = inArr;
    
    for( int i = 0; i < N; i++, pb += sizeof( unsigned ), pInArr++ )
    {
        unsigned * pc = cntrArr + *pb;
        outArr[ *pc ] = *pInArr;
        ( *pc )++;
    }
}


/*
 ******************************************************************************
 *
 * Function Name:           RadixSort()
 *
 * Function Purpose:        Sorts array of unsigned integers. 
 *
 * Function Description:    Sort array of unsigned number by Radix Sort method.
 *                          Bytes of the number are used as sorting keys.
 *
 * Arguments:               unsigned * &inArr [in out] - 
 *                          Reference to pointer to source array.
 *
 *                          const long N [in] - Array size.
 *      
 *
 * Return value:            None.
 *
 * Revision History:
 *
 *      03/02/2009:         Created.
 *
 ******************************************************************************
*/
void RadixSort( unsigned * &inArr, const long N )
{
    //
    // One-dimension array is used for counters. 
    // Byte values is used as counter array index. Each element of counter 
    // array contains total amount of numbers with the given value of the byte.
    // For each byte position (0,1,2,3) exists separate counters array.
    // 
    // Placement counters in memory:
    // -----------------------------------------------------------------------------
    //  0s counters array  |  1st cntrs. arr.  |  2nd cntrs. arr. |  3rd cntrs. arr.
    // -----------------------------------------------------------------------------
    //   [0]                [256]               [512]              [768]
    //
    
    unsigned counters[ sizeof( unsigned ) * 256 ];
    unsigned * outArr = new unsigned[ N ];
    
    CreateCounters( 
        inArr, 
        counters, 
        N 
        );
    
    int swapCounter = 0;    // need due to optimization

    for( int i = 0; i < sizeof( unsigned ); i++ )
    {
        unsigned * cntrsArr = counters + 256 * i;
        
        //
        // A little optimization: if all bytes in the current position are the same
        // (equal to zero), sorting by this position is not required.
        //

        if( N == counters[ 0 ] )
        {
            continue;
        }

        RadixPass(
            i, 
            N, 
            inArr, 
            outArr, 
            cntrsArr
            );

        swap( 
            inArr, 
            outArr 
            );

        swapCounter ++ ;
    }
    
    //
    // Do not forget restore pointer to the incoming array if the number of swaps were odd !
    //

    if( swapCounter & 1 )
    {
        swap( 
            inArr, 
            outArr 
            );
    }

    delete [] outArr;
}


//
// Application entry point.
//

int main( int argc, char * argv[] )
{
    unsigned * pArr = test_array;
    unsigned dupNum = 0;
    
    printf( "Original array:\n" );

    for( int i = 1; i < NumElementsInTestArray; i++ )
    {
        printf( "%6d ", test_array[ i ] );
        
        if( !( i % 10 ))
        {
            printf( "\n" );
        }
    }

    RadixSort( 
        pArr, 
        NumElementsInTestArray 
        );
    
    printf( "\n\nSorted array:\n" );

    for( int i = 1; i < NumElementsInTestArray; i++ )
    {
        printf( "%6d ", test_array[ i ] );
        
        if( !( i % 10 ))
        {
            printf( "\n" );
        }

        if( test_array[ i - 1 ] == test_array[ i ] )
        {
            dupNum = test_array[ i ];
        }
    }
    
    printf(
        "\n\n"
        "Dublicate number found: %d\n",
        dupNum
        );

    _getch();

    return 0;
}
Re[5]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 19.07.11 00:18
Оценка:
Здравствуйте, batu, Вы писали:

B>Здравствуйте, Xobotik, Вы писали:


X>>Здравствуйте, Don Reba, Вы писали:


DR>>>Здравствуйте, batu, Вы писали:


B>>>>В среднем O(3N/2) что явно лучше чем O(N)


DR>>>Несколько замечаний:


DR>>>1. 3N/2 > N

DR>>>2. O(3N/2) = O(N)
DR>>>3. Сложность алгоритма не О(N), а O(M), что может быть гораздо хуже.

X>>Отлично, ну а как тогда реализовывать поставленную задача, если алгоритм должен быть без сравнения и перебора элементов во вспомогательном массиве (так же без сравнения во входном массиве) за время O(N). Может быть в задаче, то и имелось ввиду за O(M).

B>Видимо алгоритм не понят.
B>Мы резервируем массив размером с диапазон значений, и в цикле заносим единицу по индексу значения этого числа.

Зачем ребенка неправильно учишь?
Ну зарезервируй массив с диапазоном значений 4 миллиарда. "Офигенное" решение.

ЗЫ. А еще в условии не сказано, что числа положительные.
Re[4]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 19.07.11 00:24
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, samius, Вы писали:


S>>Здравствуйте, -VladK-, Вы писали:


VK>>>Народ, да вы че?

VK>>>сколько уже прочитал вариантов и некто не догадался просто просуммировать массив и сравнить с суммой арифметической прогрессии ?!

S>>Разве в условии сказано что N = M + 1?

S>>N = 10, M = 1000. Куда приложить прогрессию?

А>"Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно

А>число в этом массиве повторяется два раза." Раз повторяется одно число, значит N = M + 1.

N в общем случае не равняется M + 1, не? Намекаю другими словами, что в условии не сказано, что в массиве встечается каждое число от 1 до М.
Пример:

int a[] = { 1, 100000, 1, 3 };
Re[6]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 19.07.11 00:25
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Тогда нужно уточнение условия.


Не нужно.
Re[6]: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 19.07.11 13:48
Оценка:
Здравствуйте, opener, Вы писали:

B>>Мы резервируем массив размером с диапазон значений, и в цикле заносим единицу по индексу значения этого числа.


O>Зачем ребенка неправильно учишь?

O>Ну зарезервируй массив с диапазоном значений 4 миллиарда. "Офигенное" решение.

O>ЗЫ. А еще в условии не сказано, что числа положительные.

Так ребенок должен малость соображать, что это не для такого случая
Re[7]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 19.07.11 16:31
Оценка:
Здравствуйте, batu, Вы писали:

B>Здравствуйте, opener, Вы писали:


B>>>Мы резервируем массив размером с диапазон значений, и в цикле заносим единицу по индексу значения этого числа.


O>>Зачем ребенка неправильно учишь?

O>>Ну зарезервируй массив с диапазоном значений 4 миллиарда. "Офигенное" решение.

O>>ЗЫ. А еще в условии не сказано, что числа положительные.

B>Так ребенок должен малость соображать, что это не для такого случая

Дык ты ж ему изначально советуешь неправильно. Ты же для него гуру, твое мнение изначально авторитетное.
Re[8]: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 19.07.11 19:14
Оценка:
Здравствуйте, opener, Вы писали:

O>Дык ты ж ему изначально советуешь неправильно. Ты же для него гуру, твое мнение изначально авторитетное.

Насчет гуру и авторитетов то лестно.. но херня.. А насчет правильно-не правильно.. это зависит от реальной задачи..
Re[9]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 19.07.11 23:50
Оценка: -1
Здравствуйте, batu, Вы писали:

B>Здравствуйте, opener, Вы писали:


O>>Дык ты ж ему изначально советуешь неправильно. Ты же для него гуру, твое мнение изначально авторитетное.

B>Насчет гуру и авторитетов то лестно.. но херня.. А насчет правильно-не правильно.. это зависит от реальной задачи..

B>Мы резервируем массив размером с диапазон значений, и в цикле заносим единицу по индексу значения этого числа.


Твой совет? )
А теперь выполни его для такого массива:

unsigned arr[] = { 1, 2, 3, 0xFFFFFFFF };
Re[10]: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 20.07.11 04:27
Оценка:
Здравствуйте, opener, Вы писали:

O>Здравствуйте, batu, Вы писали:


B>>Здравствуйте, opener, Вы писали:


O>>>Дык ты ж ему изначально советуешь неправильно. Ты же для него гуру, твое мнение изначально авторитетное.

B>>Насчет гуру и авторитетов то лестно.. но херня.. А насчет правильно-не правильно.. это зависит от реальной задачи..

B>>Мы резервируем массив размером с диапазон значений, и в цикле заносим единицу по индексу значения этого числа.


O>Твой совет? )

O>А теперь выполни его для такого массива:

O>
O>unsigned arr[] = { 1, 2, 3, 0xFFFFFFFF };
O>



Та запросто. Сначала пронумеровать, и выполнить тоже самое с номерами.
Re[11]: Поиск повторяющегося числа в массиве
От: samius Япония http://sams-tricks.blogspot.com
Дата: 20.07.11 04:41
Оценка:
Здравствуйте, batu, Вы писали:

B>Здравствуйте, opener, Вы писали:


O>>
O>>unsigned arr[] = { 1, 2, 3, 0xFFFFFFFF };
O>>



B>Та запросто. Сначала пронумеровать, и выполнить тоже самое с номерами.

Зачем выполнять то же самое, если в процессе нумерации решение уже будет найдено?
Re[12]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 20.07.11 06:04
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, batu, Вы писали:


B>>Здравствуйте, opener, Вы писали:


O>>>
O>>>unsigned arr[] = { 1, 2, 3, 0xFFFFFFFF };
O>>>



B>>Та запросто. Сначала пронумеровать, и выполнить тоже самое с номерами.

S>Зачем выполнять то же самое, если в процессе нумерации решение уже будет найдено?

Еще один зачетный совет от гуру.
Re[12]: Поиск повторяющегося числа в массиве
От: batu Украина  
Дата: 20.07.11 14:51
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, batu, Вы писали:


B>>Здравствуйте, opener, Вы писали:


O>>>
O>>>unsigned arr[] = { 1, 2, 3, 0xFFFFFFFF };
O>>>



B>>Та запросто. Сначала пронумеровать, и выполнить тоже самое с номерами.

S>Зачем выполнять то же самое, если в процессе нумерации решение уже будет найдено?
Есть и такой вариант. Смотря как задача поставлена
Re[12]: Решение за O(N) и доп. память O(N)
От: Аноним  
Дата: 22.07.11 10:44
Оценка:
Здравствуйте, Xobotik, Вы писали:

X>Здравствуйте, OlegMax, Вы писали:


OM>>Попробуем мысленно прогнать на последовательности {3,3}. Получим "index out of bounds".


X>Ну тогда буферный массив будет выглядеть следующим образом:

X>
X>int[] buf = new int[array.Max() + 1];
X>


Что за чушь? Пусть array.Max() == 0xFFFFFFFF
Дальше что?
Re: Поиск повторяющегося числа в массиве
От: SergeySymbol Россия  
Дата: 29.07.11 10:19
Оценка: -1
Здравствуйте, Xobotik, Вы писали:

X>Условие задачи:

X>Дан массив размера N из целых чисел, принимающих значения от 1 до M, при этом одно
X>число в этом массиве повторяется два раза. Найти это число за время O(N).

X>Реализация:

X>
X>private static string separator = ";";
X>        static void Main(string[] args)
X>        {
X>            int[] result = GetIntArray(InputArray());
X>            PrintArray(result);
X>            Console.WriteLine(ff(result));
X>            Console.ReadLine();
X>        }
X>        private static string InputArray()
X>        {
X>            Console.WriteLine("Введите массив, содержащий только целые числа.");
X>            Console.WriteLine("После каждого числа ставьте разделитель '{0}'", separator);
X>            Console.WriteLine("Введите массив: ");
X>            return Console.In.ReadLine();
X>        }
X>        private static int[] GetIntArray(string insert)
X>        {
X>            string pattern = String.Format("{0}(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))", separator);
X>            string[] bufResult = Regex.Split(insert, pattern);
X>            int[] result = new int[bufResult.Length];
X>            for (int i = 0; i < bufResult.Length; i++)
X>            {
X>                result[i] = Int32.Parse(bufResult[i]);
X>            }
X>            return result;
X>        }
X>        private static void PrintArray(int[] array)
X>        {
X>            foreach(int i in array)
X>            {
X>                Console.WriteLine(i);
X>            }
X>        }
X>        private static int ff(int[] array)
X>        {
X>            int m = 1;
X>            int buf = 0;
X>            // общее количество сравнений (n-1)^2, где n - длина массива
X>            for (int i = 0; i < (array.Length - 1) * (array.Length - 1); i++)
X>            {
X>                // количество перестановок (n-1) = количеству сравнений array[0] и array[k], где k - числа от 1 до n (n - длина массива)
X>                for (int j = 1; j < array.Length; j++)
X>                {
X>                    if (array[0] == array[j])
X>                    {
X>                        buf = array[0];
X>                        goto result;
X>                    }
X>                }
X>                Swap(array, m);
X>                m++;
X>            }
X>        result:
X>        return buf;
X>        }
X>        private static void Swap(int[] array, int index)
X>        {
X>            int temp = array[index];
X>            array[index] = array[0];
X>            array[0] = temp;
X>        }
X>


X>Есть ли какие-либо другие пути решения задачи? Без goto не вижу решения задачи, если использовать break, там где buf = array[0] , останавливается только цикл:


X>
X>for (int j = 1; j < array.Length - 1; j++)
X>


X>при этом работа цикла


X>
X>for (int i = 0; i < (array.Length - 1) * (array.Length - 1); i++)
X>


X>не прерывается


X>Заранее спасибо!


Реализация на с
int Find(int * Array,int N, int M)
{
    int *AsPresent = new int[M];
    memset(AsPresent,0,sizeof(int)*M);
    for(int i=0;i<N;i++)
        if(AsPresent[Array[i]])
        {
            delete[] AsPresent;
            return Array[i];
        }
        else
            AsPresent[Array[i]] = 1;
        delete[] AsPresent;
    return -1;
}
Re[2]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 30.07.11 21:31
Оценка:
Здравствуйте, SergeySymbol, Вы писали:


SS>Реализация на с

SS>
SS>int Find(int * Array,int N, int M)
SS>{
SS>    int *AsPresent = new int[M];
SS>    memset(AsPresent,0,sizeof(int)*M);
SS>    for(int i=0;i<N;i++)
SS>        if(AsPresent[Array[i]])
SS>        {
SS>            delete[] AsPresent;
SS>            return Array[i];
SS>        }
SS>        else
SS>            AsPresent[Array[i]] = 1;
SS>        delete[] AsPresent;
SS>    return -1;
SS>}
SS>


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

int Array[] = { 1, 1, 0xFFFFFFFF };
Re[6]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 31.07.11 07:27
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Здравствуйте, samius, Вы писали:


S>>Здравствуйте, vsb, Вы писали:


vsb>>>Здравствуйте, samius, Вы писали:


S>>>>Здравствуйте, vsb, Вы писали:


vsb>>>>>Здравствуйте, Xobotik, Вы писали:


vsb>>>>>Если M < N, то вот решение. Не выделяет лишней памяти, не изменяет исходный массив. Печатает одно из чисел, которые повторяются 2 или более раз.

S>>>>int[] a = { 1, 3, 2, 1, 4 };
S>>>>выдает 4

vsb>>>N = 5, M = 5, условие не удовлетворено. В общем цифры надо считать с нуля. Если каждое число в вашем примере уменьшить на единицу, то всё работает.


S>>Вы условие задачи читали? Числа от 1-го до M!


vsb>Не придирайтесь Пусть будут от 0 до M-1, это ничего не изменит, если надо для исходной задачи — просто -1 написать в некоторых местах.


Никто и не придирается. Просто твое решение неправильное, вот и все.
Re[7]: Поиск повторяющегося числа в массиве
От: vsb Казахстан  
Дата: 31.07.11 15:40
Оценка:
Здравствуйте, opener, Вы писали:

O>Здравствуйте, vsb, Вы писали:


vsb>>Здравствуйте, samius, Вы писали:


S>>>Здравствуйте, vsb, Вы писали:


vsb>>>>Здравствуйте, samius, Вы писали:


S>>>>>Здравствуйте, vsb, Вы писали:


vsb>>>>>>Здравствуйте, Xobotik, Вы писали:


vsb>>>>>>Если M < N, то вот решение. Не выделяет лишней памяти, не изменяет исходный массив. Печатает одно из чисел, которые повторяются 2 или более раз.

S>>>>>int[] a = { 1, 3, 2, 1, 4 };
S>>>>>выдает 4

vsb>>>>N = 5, M = 5, условие не удовлетворено. В общем цифры надо считать с нуля. Если каждое число в вашем примере уменьшить на единицу, то всё работает.


S>>>Вы условие задачи читали? Числа от 1-го до M!


vsb>>Не придирайтесь Пусть будут от 0 до M-1, это ничего не изменит, если надо для исходной задачи — просто -1 написать в некоторых местах.


O>Никто и не придирается. Просто твое решение неправильное, вот и все.


На каких входных данных моё решение даёт неверный ответ?
Re[3]: Поиск повторяющегося числа в массиве
От: SergeySymbol Россия  
Дата: 01.08.11 08:01
Оценка:
Здравствуйте, opener, Вы писали:

O>Здравствуйте, SergeySymbol, Вы писали:



SS>>Реализация на с

SS>>
SS>>int Find(int * Array,int N, int M)
SS>>{
SS>>    int *AsPresent = new int[M];
SS>>    memset(AsPresent,0,sizeof(int)*M);
SS>>    for(int i=0;i<N;i++)
SS>>        if(AsPresent[Array[i]])
SS>>        {
SS>>            delete[] AsPresent;
SS>>            return Array[i];
SS>>        }
SS>>        else
SS>>            AsPresent[Array[i]] = 1;
SS>>        delete[] AsPresent;
SS>>    return -1;
SS>>}
SS>>


O>Клево.

O>Особенно умиляет количество памяти, которое необходимо выделить, для такого, к примеру, массива:

O>
O>int Array[] = { 1, 1, 0xFFFFFFFF };
O>

Приведенный массив не соответствует условию задачи поскольку ты скорее всего имел ввиду int 32 разрядный целочисленный знаковый тип то значение 0xFFFFFFFF будет интерпретировано как -1, а в условии от 1 до M. Да слабость этого алгоритма в выделении дополнительной памяти, а так если не считать memset(AsPresent,0,sizeof(int)*M) то он удовлетворяет условию O(N).
если использовать в качестве словаря контейнеры на основе бинарных деревьев , то сложность будет O(N*log(N)).
Re[4]: Поиск повторяющегося числа в массиве
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 01.08.11 08:15
Оценка:
Здравствуйте, SergeySymbol, Вы писали:

SS>Приведенный массив не соответствует условию задачи поскольку ты скорее всего имел ввиду int 32 разрядный целочисленный знаковый тип то значение 0xFFFFFFFF будет интерпретировано как -1, а в условии от 1 до M. Да слабость этого алгоритма в выделении дополнительной памяти, а так если не считать memset(AsPresent,0,sizeof(int)*M) то он удовлетворяет условию O(N).

SS>если использовать в качестве словаря контейнеры на основе бинарных деревьев , то сложность будет O(N*log(N)).

Как это "не считать"? Инициализация этой памяти займёт O(M), а значит сложность будет O(M+N).
Ce n'est que pour vous dire ce que je vous dis.
Re[5]: Поиск повторяющегося числа в массиве
От: SergeySymbol Россия  
Дата: 01.08.11 09:00
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Здравствуйте, SergeySymbol, Вы писали:


SS>>Приведенный массив не соответствует условию задачи поскольку ты скорее всего имел ввиду int 32 разрядный целочисленный знаковый тип то значение 0xFFFFFFFF будет интерпретировано как -1, а в условии от 1 до M. Да слабость этого алгоритма в выделении дополнительной памяти, а так если не считать memset(AsPresent,0,sizeof(int)*M) то он удовлетворяет условию O(N).

SS>>если использовать в качестве словаря контейнеры на основе бинарных деревьев , то сложность будет O(N*log(N)).

DR>Как это "не считать"? Инициализация этой памяти займёт O(M), а значит сложность будет O(M+N).

так я это и указал.
Re[8]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 20.08.11 16:59
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>На каких входных данных моё решение даёт неверный ответ?


Не знаю (лень думать). Это не то решение, которое нужно было найти.
Re[8]: Поиск повторяющегося числа в массиве
От: opener  
Дата: 20.08.11 17:01
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Здравствуйте, opener, Вы писали:


O>>Здравствуйте, vsb, Вы писали:


vsb>>>Здравствуйте, samius, Вы писали:


S>>>>Здравствуйте, vsb, Вы писали:


vsb>>>>>Здравствуйте, samius, Вы писали:


S>>>>>>Здравствуйте, vsb, Вы писали:


vsb>>>>>>>Здравствуйте, Xobotik, Вы писали:


vsb>>>>>>>Если M < N, то вот решение. Не выделяет лишней памяти, не изменяет исходный массив. Печатает одно из чисел, которые повторяются 2 или более раз.

S>>>>>>int[] a = { 1, 3, 2, 1, 4 };
S>>>>>>выдает 4

vsb>>>>>N = 5, M = 5, условие не удовлетворено. В общем цифры надо считать с нуля. Если каждое число в вашем примере уменьшить на единицу, то всё работает.


S>>>>Вы условие задачи читали? Числа от 1-го до M!


vsb>>>Не придирайтесь Пусть будут от 0 до M-1, это ничего не изменит, если надо для исходной задачи — просто -1 написать в некоторых местах.


O>>Никто и не придирается. Просто твое решение неправильное, вот и все.


vsb>На каких входных данных моё решение даёт неверный ответ?


На таком массиве что получится?

int arr[3] = { 1, 1, MAX_INT };
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.