41 Востаннє редагувалося steamwater (16.08.2024 18:55:28)

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

Ось ця, наче, все знаходить:

bool
//std::pair<int, int>
 find_in_matrix_lg_lg(
                         const std::vector<std::vector<int>>& matrix,
                         const int target
                         )
{

    using Vec=std::vector<int>;
    Vec vtarget={target};

     auto vec_it=
         std::lower_bound(matrix.begin(), matrix.end(), vtarget,
                               [](const Vec &a, const Vec &b){
                                return a.back()<b.back();
                                }
                               );

    auto vec_it_last=std::upper_bound(matrix.begin(), matrix.end(), vtarget,
                               [](const Vec &a, const Vec &b){
                                return a.front()<b.front();
                                }
                               );

        for(;vec_it!=vec_it_last; ++vec_it)
        {
             if(*vec_it->begin()>target || *(vec_it->end()-1)<target)continue;

                auto it=std::lower_bound(vec_it->begin(), vec_it->end(), target);
               if(*it==target)
                 {
                     return true;
                     //return {vec_it-matrix.begin(), vec_it->begin()-it};
                 }
        }


    return false;
   // return{-1,-1};

}
Подякували: koala1

42

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

Так, про складність мого алгоритму - я дещо помилився.
Отже, якщо його складність F(N), де N - площа масиву, то маємо F(N) = 1 + F(N/2)+F(N/4) = 2 + 2F(N/4) + F(N/8) = 4 + 3F(N/8)+2F(N/16) = 7 + 5F(N/16) + 3F(N/32), тобто коефіцієнти - числа Фібоначчі, а не степені двійки. Інша експоненційна залежність. Але маю таке відчуття, що кінець-кінцем там усе одно той самий O(h*log(w)) (чи навпаки), що й у steamwater.

Останній алгоритм steamwater за логарифмічний час відсіює рядки, де не може бути цільового числа, а далі та сама лінійнологарифмічна складність.

Подякували: steamwater, leofun012

43 Востаннє редагувалося steamwater (17.08.2024 15:04:59)

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

koala, все ж лишається не зрозумiлiлим, чому ваш алгоритм не знаходить всiх значень. Наприклад, для розмiру матрицi 10000х10000 ми маємо лише 14 влучень з 10000, тодi коли має бути 10000... Набiр даних готувався згiдно рецепту:

std::vector<std::vector<int>>
     matrix (
     make_matrix(num_min, num_max, v_size)//початок з нуля
     );

 std::vector<int> vtargets=matrix[v_size/2];//посерединi


де make_matrix у текучiй редакцiї:

std::vector<std::vector<int>> make_matrix(int num_min, int num_max, unsigned v_size)
{   
    std::vector<std::vector<int>> matrix;
    auto vec=make_source_vector(num_min, num_max, v_size);
    int deca=1;//// змiщення мiж рядками
    for(int el:vec)
    {
       // deca*=10;/////////////////  тут можна ще експерементувати)
        for(int &el:vec)el+=deca*(num_max-num_min)/10;///////////
        // for(int &el:vec)el+=1;//old variant
        std::sort(vec.begin(), vec.end());
        matrix.push_back(vec);
        ++deca;///////////////////
    }
    
    return matrix;
}

а make_source_vector :

template<typename It>
void uniform_random_fill(int num_min, int num_max, It first, It last)
{
    std::random_device r;
    std::mt19937 g(r());
    std::uniform_int_distribution<int> ud(num_min, num_max);

    while(first!=last) *first++=ud(g);
}

std::vector<int> make_source_vector(int num_min, int num_max, unsigned v_size)
{
    std::vector<int> vec(v_size);
    uniform_random_fill(num_min, num_max, vec.begin(), vec.end());
    return vec;
}

На малих розмiрах, ваш алгоритм знаходить усi элементи, що дивно.
В мене є припущення, що якщо пофiксити багу, то швидкiсть вашого алгоритму виросте що найменш у двiчи. А дивлячись ваш текст про складнiсть, може й на багато бiльше. Це тому, що саме неуспiшнi виклики вартують досить багато.

44

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

А які num_min і num_max ви використовуєте? Там переповнення не відбувається?
І взагалі який сенс у випадковому рядку, якщо далі всі рядки однакові із зсувом?

45

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

Якщо вас так хвилюють невдалі пошуки, то

    bool searchMatrix(const Matrix &matrix, int target, int x0, int x1, int y0, int y1) {
        if(x1==x0||y1==y0||target<matrix[y0][x0]||matrix[y1-1][x1-1]<target) //перевіряємо кути
            return false;
        if(x1-x0==1 && y1-y0==1)
            return matrix[y0][x0]==target;
        int xmid = (x0+x1)/2;
        int ymid = (y0+y1)/2;
        if(matrix[ymid][xmid]==target)
            return true;
        else if(matrix[ymid][xmid]>target)
            return searchMatrix(matrix, target, x0, xmid, ymid, y1)
                || searchMatrix(matrix, target, x0, x1, y0, ymid);
        else 
            return searchMatrix(matrix, target, x0, xmid+1, ymid+1, y1)
                || searchMatrix(matrix, target, xmid+1, x1, y0, y1);
    }
Подякували: steamwater1

46

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

По рандомних матрицях - там краще не сортувати вектор, а додавати рандомне число до максимуму з сусідів. Крім того, форма матриці теж має значення - ваш перший алгоритм дуже погано працюватиме на вертикальній матриці (а от останній - чудово). Ну і кількість дублів теж має значення - значно легше шукати числа, які повторюються багато разів у матриці.

47 Востаннє редагувалося steamwater (18.08.2024 16:25:36)

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

koala написав:

По рандомних матрицях - там краще не сортувати вектор, а додавати рандомне число до максимуму з сусідів.

У текстi leetcode.com/problems/search-a-2d-matrix-ii/ є вимога сортування рядкiв з лiвого боку до правого. Я лише виконував вимогу. Досягати змiщення рядкiв, це спосiб уникнути загальної вiдсортованостi матрицi, зберiгаючи сортування по стовбцях. Я не змiг сформулювати загальний алгоритм заповнювання матрицi згiдно умови сайту i роблю це одержуючи часний випадок... Якщо ви має кращий, - покажiть, буду вдячнмй.
Покажiть приклади, того що можна потестити. Питання ненаходження элементiв вашим алгоритмом лишається. Щодо вертикальностi чи горизонтальностi, - звicно, у випадках n>>m чи навпаки, алгоритми будуть мати рiзну эффективнiсть. Останнiй є бiльш стiйким.

48 Востаннє редагувалося steamwater (18.08.2024 16:41:38)

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

koala написав:

Якщо вас так хвилюють невдалі пошуки, то

Даруйте, - не помiтив цього посту. Протестив по останнiм налаштуванням (дивiться вище) i хороша новина в тiм, що швидкicть наблизилась до мого алгоритму, програючи лише у 1,5 рази. Погана новина в тому, що ваш алгоритм знаходить 14 з 10000 можливих, як i попереднiй. Може мiй тест, десь бреше?
Щодо хвилювань, то їх нема.

49

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

"Відсортований" не означає, що до множини застосували алгоритм сортування, це лише означає, що для будь-яких двох елементів виконується i>j => a[i]>=a[j]. Цього цілком можливо досягти додаванням випадкового значення до попереднього елементу.

Гаразд, ви моє питання проігнорували, спитаю інакше. В матриці 10000х10000 яке значення останнього ([9999][9999]) елементу?

50 Востаннє редагувалося steamwater (19.08.2024 08:33:40)

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

koala написав:

"Відсортований" не означає, що до множини застосували алгоритм сортування, це лише означає, що для будь-яких двох елементів виконується i>j => a[i]>=a[j].

Це абсолютно вiрно. Але якщо є не вiдсортована, тобто случайна послiдовнiсть, то получити з неї впорядковану, можно шляхом сортування. Тому я використовую впорядкування та сортування як синонiми.

koala написав:

Цього цілком можливо досягти додаванням випадкового значення до попереднього елементу.

Не зрозумiв.

koala написав:

Гаразд, ви моє питання проігнорували, спитаю інакше. В матриці 10000х10000 яке значення останнього ([9999][9999]) елементу?

В даному тестi три останнiх у останньому рядку: 1.833.893.644, 1.833.893.651, 1.833.893.662
Числа у дiапазонi int32. На жаль, доволi скупченi. Запропонуйте свiй алгоритм заповненя матрицi, я згоден на будь який, задоволняючий умовам задачi.
Але ж ви теж iгноруєте моє питання про те що ваш алгоритм у тестi незнаходить майже нiчого. З ваших непрямих висловлювань я розумiю, що винен тест. То скажiть прямо, - де, чому, та як виправити.
Може таки десь переповнення? Дiйсно, при зменшеннi максимальної границi num_max (коли 100 - результати спiвпадають!) результати змiнюються на краще. Треба роздивитись.

51 Востаннє редагувалося steamwater (19.08.2024 08:22:07)

Re: Рекурсивний пошук по двовимірній впорядкованій матриці

Я вирiшив не гратись з великими змiщеннями по рядках - 10 на рядок. Тепер ваш алгоритм все знаходить. Програш у часi вдвiчи не такий вже й великий. Це каже, мiж iншим, що складнiсть у вас теж логарифмiчна. Цiлком може бути, що за певних умов, ваш буде навiть швидше. А от сформулювати обмеження цiх умов, самостiйна задача.
Teg Miles, у цiєї задачi, складнiсть не пов'язана з рекурсiєю, вiд слова зовсiм. Бiнарнi пошуки, std::lower_bound, та std::upper_bound можна легко написати самому, ще й рекурсивно. Та чи воно буде помiтно на тлi самого будування алгоритму. Звiсно ж нi. Напроти, - слушне використання std це плюс. А рекурсiю у кодi вiд koala, можна переписати на цiклах i воно теж буде робити, навiть, безпечнiше. Iнша справа, що шановний koala вiдповiдаючи на моє питання, довiв, що це можливо зробити саме рекурсивно.