বাম থেকে ডানে এবং উপরে থেকে নীচে বাছাই করা 2 ডি অ্যারেটিতে আমি কীভাবে সন্ধান করব?


90

আমাকে সম্প্রতি এই সাক্ষাত্কারের প্রশ্ন দেওয়া হয়েছিল এবং আমি কৌতূহল বোধ করি এর উত্তম সমাধানটি কী হতে পারে।

বলুন আমাকে একটি 2 ডি অ্যারে দেওয়া হয়েছে যেখানে অ্যারের সমস্ত নম্বর বাম থেকে ডানে এবং উপরে থেকে নীচে ক্রম বর্ধমান।

কোনও লক্ষ্য নম্বর অ্যারেতে থাকলে অনুসন্ধান এবং নির্ধারণের সর্বোত্তম উপায় কী?

এখন, আমার প্রথম প্রবণতাটি বাইনারি অনুসন্ধানটি ব্যবহার করা যেহেতু আমার ডেটা সাজানো হয়েছে search ও (লগ এন) সময়ে কোনও সংখ্যা একটি একক সারিতে রয়েছে কিনা তা আমি নির্ধারণ করতে পারি। তবে এটি 2 দিক যা আমাকে ফেলে দেয় off

আমি যে অন্য সমাধানটি কাজ করতে পারি তা ভেবেছিলাম মাঝখানে কোথাও শুরু করা। মাঝারি মানটি যদি আমার টার্গেটের চেয়ে কম হয় তবে আমি নিশ্চিত হতে পারি যে এটি মাঝখান থেকে ম্যাট্রিক্সের বাম বর্গক্ষেত্রে রয়েছে। আমি তখন তির্যকভাবে সরানো এবং আবার যাচাই করে, লক্ষ্য সংখ্যায় সম্মতি না দেওয়া পর্যন্ত লক্ষ্যটি সম্ভাব্যভাবে থাকতে পারে এমন বর্গের আকার হ্রাস করে।

এই সমস্যা সমাধানে কারও কি কোনও ভাল ধারণা আছে?

উদাহরণ অ্যারে:

বাম থেকে ডানে, উপরে থেকে নীচে বাছাই করা।

1  2  4  5  6  
2  3  5  7  8  
4  6  8  9  10  
5  8  9  10 11  

সহজ প্রশ্ন: এটা হতে পারে আপনি একই মান প্রতিবেশী থাকতে পারে যে: [[1 1][1 1]]?
ম্যাথিউ এম।

উত্তর:


115

এখানে একটি সহজ পদ্ধতি:

  1. নীচে-বাম কোণে শুরু করুন।
  2. লক্ষ্যটি যদি সেই মানটির চেয়ে কম হয় তবে এটি অবশ্যই আমাদের উপরে থাকতে হবে, সুতরাং একটি উপরে চলে যান
  3. অন্যথায় আমরা জানি যে লক্ষ্যটি সেই কলামে থাকতে পারে না, তাই ডানদিকে যান
  4. গোটো 2।

একটি NxMঅ্যারের জন্য, এটি চালু O(N+M)। আমি মনে করি এটি আরও ভাল করা কঠিন হবে। :)


সম্পাদনা: প্রচুর ভাল আলোচনা। আমি উপরের সাধারণ মামলার কথা বলছিলাম; স্পষ্টত, যদি Nবা M ছোট হয়, লগারিদমিক সময়ে পৌঁছানোর কোনও কিছুতে আপনি এটি করতে বাইনারি অনুসন্ধানের পদ্ধতির ব্যবহার করতে পারেন।

যারা কৌতূহলী তাদের জন্য এখানে কিছু বিশদ দেওয়া হল:

ইতিহাস

এই সাধারণ অ্যালগরিদমকে স্যাডলব্যাক অনুসন্ধান বলা হয় । এটি প্রায় সময় হয়ে গেছে, এবং কখন অনুকূল হয় N == M। কিছু উল্লেখ:

যাইহোক, যখন N < M, অন্তর্দৃষ্টি পরামর্শ দেয় যে বাইনারি অনুসন্ধানের চেয়ে আরও ভাল করতে সক্ষম হওয়া উচিত O(N+M): উদাহরণস্বরূপ, কখন N == 1, একটি খাঁটি বাইনারি অনুসন্ধান লিনিয়ার সময়ের পরিবর্তে লোগারিথমিকতে চলবে।

সবচেয়ে খারাপ মামলায় আবদ্ধ

রিচার্ড বার্ড এই স্বজ্ঞাততাটি পরীক্ষা করে দেখেন যে বাইনারি অনুসন্ধান 2006 এর একটি গবেষণাপত্রে স্যাডলব্যাক অ্যালগরিদমকে উন্নত করতে পারে:

একটি অস্বাভাবিক কথোপকথন কৌশল ব্যবহার করে, বার্ড আমাদের দেখায় যে N <= M, এই সমস্যার কম সীমাবদ্ধ রয়েছে Ω(N * log(M/N))। এটি আমাদের লিনিয়ার পারফরম্যান্স কখন N == Mএবং লগারিদমিক পারফরম্যান্স দেয় তা বুদ্ধিমান করে তোলে N == 1

আয়তক্ষেত্রাকার অ্যারেগুলির জন্য অ্যালগরিদম

সারি সারি সারি বাইনারি অনুসন্ধান ব্যবহার করে এমন একটি পদ্ধতির চেহারা দেখতে এটি দেখতে পাওয়া যায়:

  1. যেখানে একটি আয়তক্ষেত্রাকার অ্যারে দিয়ে শুরু করুন N < M। ধরা যাক Nসারি এবং Mকলামগুলি।
  2. এর জন্য মাঝারি সারিতে একটি বাইনারি অনুসন্ধান করুন value। আমরা যদি এটি খুঁজে পাই তবে আমরা শেষ করেছি।
  3. অন্যথায় আমরা সংখ্যার সংলগ্ন জোড়া sএবং gকোথায় খুঁজে পেয়েছি s < value < g
  4. উপরে এবং বাম সংখ্যার আয়তক্ষেত্রের sচেয়ে কম value, তাই আমরা এটিকে নির্মূল করতে পারি।
  5. নীচের ও ডানদিকে আয়তক্ষেত্রটি এর gচেয়ে বড় value, সুতরাং আমরা এটিকে নির্মূল করতে পারি।
  6. দুটি অবশিষ্ট আয়তক্ষেত্রের জন্য প্রতিটি পদক্ষেপে (2) যান।

নিকৃষ্টতম জটিলতার ক্ষেত্রে, এই অ্যালগরিদম log(M)সম্ভাব্য অর্ধেক সমাধান সমাধান করতে কাজ করে এবং তারপরে পুনরাবৃত্তভাবে দুটি ছোট সমস্যার জন্য নিজেকে দু'বার কল করে। আমাদের log(M)প্রতিটি সারির জন্য সেই কাজের একটি ছোট সংস্করণ পুনরাবৃত্তি করতে হবে, তবে কলামগুলির সংখ্যার তুলনায় যদি সারিগুলির সংখ্যা ছোট হয়, তবে লোগারিটিমিক সময়ে col সমস্ত কলামগুলি অপসারণ করতে সক্ষম হওয়া সার্থক হতে শুরু করে

এটি অ্যালগরিদমকে একটি জটিলতা দেয় T(N,M) = log(M) + 2 * T(M/2, N/2)যা বার্ডটি দেখায় O(N * log(M/N))

ক্রেগ গিডনি দ্বারা পোস্ট করা আরেকটি পদ্ধতির উপরের পদ্ধতির অনুরূপ একটি অ্যালগরিদম বর্ণনা করেছে: এটি একটি ধাপের আকারের সাহায্যে একবারে একটি সারি পরীক্ষা করে M/N। তাঁর বিশ্লেষণ দেখায় যে এটি ফলাফলের O(N * log(M/N))পাশাপাশি কর্মক্ষমতাও অর্জন করে।

পারফরম্যান্স তুলনা

বিগ-ও বিশ্লেষণগুলি সমস্ত ভাল এবং ভাল, তবে এই পদ্ধতিগুলি বাস্তবে কতটা কার্যকর হয়? নীচের চার্টটি ক্রমবর্ধমান "স্কোয়ার" অ্যারেগুলির জন্য চারটি অ্যালগরিদম পরীক্ষা করে:

বর্গক্ষেত্র বনাম অ্যালগরিদম কর্মক্ষমতা

("নিষ্পাপ" অ্যালগরিদম কেবল অ্যারের প্রতিটি উপাদান সন্ধান করে above "পুনরাবৃত্ত" এলগোরিদমকে উপরে বর্ণিত হয়েছে। "সংকর" অ্যালগরিদম গিডনির অ্যালগরিদমের একটি বাস্তবায়ন each প্রতিটি অ্যারের আকারের জন্য, প্রতিটি অ্যালগরিদমকে নির্দিষ্ট সেটের উপরে সময় নির্ধারণ করে পরিমাপ করা হয়েছিল 1,000,000 এলোমেলোভাবে উত্পন্ন অ্যারে।)

কয়েকটি উল্লেখযোগ্য বিষয়:

  • প্রত্যাশিত হিসাবে, "বাইনারি অনুসন্ধান" অ্যালগরিদমগুলি আয়তক্ষেত্রাকার অ্যারেতে সর্বোত্তম পারফরম্যান্স সরবরাহ করে এবং স্যাডলব্যাক অ্যালগরিদম স্কোয়ার অ্যারেতে সেরা কাজ করে।
  • স্যাডলব্যাক অ্যালগরিদম 1-ডি অ্যারেগুলির জন্য "নিষ্পাপ" অ্যালগরিদমের চেয়েও খারাপ সম্পাদন করে, সম্ভবত এটি কারণ এটি প্রতিটি আইটেমের একাধিক তুলনা করে।
  • "বাইনারি অনুসন্ধান" অ্যালগরিদমগুলি বর্গাকার অ্যারেগুলিতে গ্রহণ করে এমন পারফরম্যান্সটি সম্ভবত বারবার বাইনারি অনুসন্ধানগুলি চালানোর ওভারহেডের কারণে সম্ভবত।

সারসংক্ষেপ

বাইনারি অনুসন্ধানের চতুর ব্যবহার O(N * log(M/N)আয়তক্ষেত্রাকার এবং বর্গাকার উভয়ের জন্য পারফরম্যান্স সরবরাহ করতে পারে । O(N + M)"Saddleback" অ্যালগরিদম অনেক সহজ, কিন্তু অ্যারে কর্মক্ষমতাকে অবনতি ভুগছেন ক্রমবর্ধমান আয়তক্ষেত্রাকার হয়ে।


6
তির্যক পদক্ষেপে বাইনারি অনুসন্ধান প্রয়োগ করুন এবং আপনি ও (লগএন) বা ও (লগএম) যাহা বেশি উচ্চতর পাবেন।
অনুরাগ

4
@ আনুরাগ - আমার মনে হয় না জটিলতা খুব ভালভাবে কার্যকর হয়েছে। একটি বাইনারি অনুসন্ধান আপনাকে শুরু করার জন্য একটি ভাল জায়গা দেবে, তবে আপনাকে এক দিক বা অন্য দিক দিয়ে চলতে হবে এবং সবচেয়ে খারাপ ক্ষেত্রে, আপনি এখনও একটি কোণে শুরু করতে এবং অন্যদিকে শেষ করতে পারেন could
জেফ্রি এল হুইলেটজ

4
যদি এন = 1 এবং এম = 1000000 আমি ও (এন + এম) এর চেয়ে আরও ভাল করতে পারি, সুতরাং অন্য সমাধানটি প্রতিটি সারিতে বাইনারি অনুসন্ধান প্রয়োগ করছে যা ও (এন * লগ (এম)) আনবে যেখানে এন <এম যদি এই ফলন করে তবে ছোট ধ্রুবক।
লুকা রাহনে

4
আমি আপনার পদ্ধতি এবং বাইনারি অনুসন্ধান পদ্ধতি উভয়ই ব্যবহার করে কিছু পরীক্ষা করেছি এবং ফলাফলগুলি এখানে পোস্ট করেছি । মনে হচ্ছে জিগজ্যাগ পদ্ধতিটি সবচেয়ে ভাল, যদি না আমি উভয় পদ্ধতির জন্য সবচেয়ে খারাপ পরিস্থিতিটি সঠিকভাবে তৈরি করতে ব্যর্থ হই।
The111

4
রেফারেন্সের দুর্দান্ত ব্যবহার! তবে M==Nআমরা যখন O(N)জটিলতা চাই , O(N*log(N/N))যেহেতু পরেরটি শূন্য নয়। একটি সঠিক "একত্রে" ধারালো আবদ্ধ হয় O(N*(log(M/N)+1))যখন N<=M
হার্ডম্যাথ

35

এই সমস্যাটি Θ(b lg(t))সময় নেয় , কোথায় b = min(w,h)এবং t=b/max(w,h)। আমি এই ব্লগ পোস্টে সমাধান আলোচনা ।

নিম্ন সীমা

একটি বিরোধী Ω(b lg(t))নিজেকে মূল তির্যককে সীমাবদ্ধ রেখে প্রশ্ন তৈরি করতে একটি অ্যালগরিদমকে বাধ্য করতে পারে:

প্রধান তির্যক ব্যবহার করে বিরোধী

জনশ্রুতি: সাদা কক্ষগুলি ছোট আইটেম, ধূসর কোষগুলি বৃহত্তর আইটেম, হলুদ কোষগুলি ছোট-সমান আইটেম এবং কমলা কোষগুলি বৃহত্তর বা সমমানের আইটেম। বিরোধীরা সমাধানটিকে যেকোনও হলুদ বা কমলা কোষের অ্যালগোরিদম প্রশ্নগুলি স্থায়ী হতে বাধ্য করে।

লক্ষ্য করুন যে bআকারের স্বতন্ত্র অনুসারে বাছাই করা তালিকা রয়েছে t, Ω(b lg(t))সম্পূর্ণরূপে মুছে ফেলার জন্য প্রশ্নের প্রয়োজন ।

অ্যালগরিদম

  1. (সাধারণতার ক্ষতি ছাড়াই অনুমান করুন w >= h)
  2. tবৈধ ক্ষেত্রের উপরের ডান দিকের কোণে বাম দিকের ঘরের তুলনায় লক্ষ্য আইটেমটি তুলনা করুন
    • যদি ঘরের আইটেমটি মেলে তবে বর্তমান অবস্থানটি ফিরে আসুন।
    • যদি ঘরে আইটেমটি লক্ষ্য আইটেমের চেয়ে কম হয় তবে tবাইনারি অনুসন্ধানের সাথে সারিতে থাকা অবশিষ্ট কক্ষগুলি সরিয়ে ফেলুন। এটি করার সময় যদি কোনও মিলে যাওয়া আইটেম পাওয়া যায়, তবে তার অবস্থানটি নিয়ে ফিরে আসুন।
    • অন্যথায় কক্ষের আইটেমটি লক্ষ্য আইটেমের চেয়ে বেশি, tসংক্ষিপ্ত কলামগুলি মুছে ফেলে ।
  3. যদি কোনও বৈধ ক্ষেত্র বাকী না থাকে, ফিরে আসার ব্যর্থতা
  4. গোটো পদক্ষেপ 2

একটি আইটেম সন্ধান করা:

একটি আইটেম সন্ধান করা হচ্ছে

কোনও আইটেম নির্ধারণের অস্তিত্ব নেই:

কোনও আইটেম নির্ধারণের অস্তিত্ব নেই

জনশ্রুতি: সাদা কক্ষগুলি ছোট আইটেম, ধূসর কোষগুলি বৃহত্তর আইটেম এবং সবুজ কোষ একটি সমান আইটেম।

বিশ্লেষণ

অপসারণের জন্য b*tসংক্ষিপ্ত কলাম রয়েছে। bনির্মূল করার জন্য দীর্ঘ সারি রয়েছে। দীর্ঘ সারি দূর করতে O(lg(t))সময় ব্যয় হয় । tসংক্ষিপ্ত কলামগুলি বাদ দিতে O(1)সময় লাগে costs

সবচেয়ে খারাপ ক্ষেত্রে আমাদের সময়কালে প্রতিটি কলাম এবং প্রতিটি সারি মুছে ফেলতে হবে O(lg(t)*b + b*t*1/t) = O(b lg(t))

নোট করুন যে আমি lg1 (অর্থাৎ lg(x) = log_2(max(2,x))) এর উপরে একটি ফলাফলকে ক্ল্যাম্পগুলি ধরে নিচ্ছি । এ কারণেই যখন আমরা w=hঅর্থের t=1প্রত্যাশিত সীমাটি পেয়ে যাই O(b lg(1)) = O(b) = O(w+h)

কোড

public static Tuple<int, int> TryFindItemInSortedMatrix<T>(this IReadOnlyList<IReadOnlyList<T>> grid, T item, IComparer<T> comparer = null) {
    if (grid == null) throw new ArgumentNullException("grid");
    comparer = comparer ?? Comparer<T>.Default;

    // check size
    var width = grid.Count;
    if (width == 0) return null;
    var height = grid[0].Count;
    if (height < width) {
        var result = grid.LazyTranspose().TryFindItemInSortedMatrix(item, comparer);
        if (result == null) return null;
        return Tuple.Create(result.Item2, result.Item1);
    }

    // search
    var minCol = 0;
    var maxRow = height - 1;
    var t = height / width;
    while (minCol < width && maxRow >= 0) {
        // query the item in the minimum column, t above the maximum row
        var luckyRow = Math.Max(maxRow - t, 0);
        var cmpItemVsLucky = comparer.Compare(item, grid[minCol][luckyRow]);
        if (cmpItemVsLucky == 0) return Tuple.Create(minCol, luckyRow);

        // did we eliminate t rows from the bottom?
        if (cmpItemVsLucky < 0) {
            maxRow = luckyRow - 1;
            continue;
        }

        // we eliminated most of the current minimum column
        // spend lg(t) time eliminating rest of column
        var minRowInCol = luckyRow + 1;
        var maxRowInCol = maxRow;
        while (minRowInCol <= maxRowInCol) {
            var mid = minRowInCol + (maxRowInCol - minRowInCol + 1) / 2;
            var cmpItemVsMid = comparer.Compare(item, grid[minCol][mid]);
            if (cmpItemVsMid == 0) return Tuple.Create(minCol, mid);
            if (cmpItemVsMid > 0) {
                minRowInCol = mid + 1;
            } else {
                maxRowInCol = mid - 1;
                maxRow = mid - 1;
            }
        }

        minCol += 1;
    }

    return null;
}

4
আকর্ষণীয় এবং সম্ভবত আমার মাথার উপরে আংশিক। জটিলতার বিশ্লেষণের এই "বিরোধী" শৈলীর সাথে আমি পরিচিত নই। শত্রুরা আসলে কীভাবে আপনি অনুসন্ধান করার সাথে সাথে অ্যারে পরিবর্তন করে চলেছেন, বা খারাপ নাম অনুসন্ধানে আপনি যে দুর্ভাগ্যের মুখোমুখি হয়েছেন তিনি কি কেবলই একটি নাম দিয়েছেন?
The111

4
@ দ্য 111 দুর্ভাগ্য এমন কেউ এমন একটি খারাপ পথ বেছে নেওয়ার সমতুল্য যা এ পর্যন্ত দেখা জিনিসগুলি লঙ্ঘন করে না, সুতরাং এই সংজ্ঞা দুটিই একই কাজ করে। কম্পিউটেশনাল জটিলতার ক্ষেত্রে বিশেষত কৌশলটি ব্যাখ্যা করার জন্য লিঙ্কগুলি খুঁজে পেতে আমার আসলেই সমস্যা হচ্ছে ... আমি ভেবেছিলাম এটি অনেক বেশি পরিচিত ধারণা।
ক্রেগ গিডনি

কারণ লগ (1) = 0, জটিলতার অনুমানের O(b*(lg(t)+1))পরিবর্তে দেওয়া উচিত O(b*lg(t))। ভাল লেখার আপ, esp। একটি "সবচেয়ে খারাপ ক্ষেত্রে" আবদ্ধ দেখিয়ে "প্রতিপক্ষ কৌশল" মনোযোগ আহ্বান জানাতে।
হার্ডম্যাথ

@ হার্মথ আমি উত্তরে তা উল্লেখ করেছি। আমি কিছুটা স্পষ্ট করে বললাম।
ক্রেগ গিডনি

17

এই সমস্যার জন্য আমি বিভাজন এবং বিজয়ী কৌশলটি ব্যবহার করব, আপনার পরামর্শ অনুসারে, তবে বিবরণটি কিছুটা আলাদা।

এটি ম্যাট্রিক্সের শহরতলিতে পুনরাবৃত্ত অনুসন্ধান হবে।

প্রতিটি পদক্ষেপে, ব্যাপ্তির মাঝখানে একটি উপাদান বাছুন। যদি খুঁজে পাওয়া মান যদি আপনি যা খুঁজছেন তা হয় তবে আপনি হয়ে গেছেন।

অন্যথায়, যদি খুঁজে পাওয়া মানটি আপনি যে মানটি খুঁজছেন তার চেয়ে কম হয়, তবে আপনি জানেন যে এটি আপনার বর্তমান অবস্থানের চতুর্ভুজ এবং বাম দিকে নয় to সুতরাং অবিচ্ছিন্নভাবে দুটি সাব্রেনজ অনুসন্ধান করুন: বর্তমান অবস্থানের নীচে সমস্ত কিছু (একচেটিয়া) এবং বর্তমান অবস্থানে বা তার উপরে ডানদিকে (একচেটিয়া) সমস্ত কিছু।

অন্যথায়, (প্রাপ্ত মানটি আপনি যে মানের চেয়ে সন্ধান করছেন তার চেয়ে বেশি) আপনি জানেন যে এটি নীচের চতুর্ভুজ এবং আপনার বর্তমান অবস্থানের ডানদিকে নেই। সুতরাং অবিচ্ছিন্নভাবে দুটি সাব্রেনজ অনুসন্ধান করুন: বর্তমান অবস্থানের বাম দিকে সমস্ত কিছু (একচেটিয়া) এবং বর্তমান স্তরের উপরে বা ডান দিকে একটি কলামে বর্তমান অবস্থানের উপরে (একচেটিয়া) সমস্ত কিছু।

এবং বা-দা-বিং, আপনি এটি খুঁজে পেয়েছেন।

মনে রাখবেন যে প্রতিটি পুনরাবৃত্তি কল কেবল বর্তমান সাব্রঞ্জের সাথেই ডিল করে, উদাহরণস্বরূপ (বর্তমান) সমস্ত অবস্থানের অবস্থানের উপরে সারি নেই। কেবলমাত্র বর্তমানের সাব্রজেড।

আপনার জন্য এখানে কয়েকটি সিউডোকোড:

bool numberSearch(int[][] arr, int value, int minX, int maxX, int minY, int maxY)

if (minX == maxX and minY == maxY and arr[minX,minY] != value)
    return false
if (arr[minX,minY] > value) return false;  // Early exits if the value can't be in 
if (arr[maxX,maxY] < value) return false;  // this subrange at all.
int nextX = (minX + maxX) / 2
int nextY = (minY + maxY) / 2
if (arr[nextX,nextY] == value)
{
    print nextX,nextY
    return true
}
else if (arr[nextX,nextY] < value)
{
    if (numberSearch(arr, value, minX, maxX, nextY + 1, maxY))
        return true
    return numberSearch(arr, value, nextX + 1, maxX, minY, nextY)
}
else
{
    if (numberSearch(arr, value, minX, nextX - 1, minY, maxY))
        return true
    reutrn numberSearch(arr, value, nextX, maxX, minY, nextY)
}

+1: এটি একটি ও (লগ (এন)) কৌশল এবং সুতরাং এটি যেমন অর্ডার পাবে তেমনই ভাল।
রেক্স কের

4
@ রেক্স কের - এটি ও (লগ (এন)) এর মতো দেখায়, যেহেতু সাধারণ বাইনারি অনুসন্ধান এটিই, তবে নোট করুন যে প্রতিটি স্তরে সম্ভাব্য দুটি পুনরাবৃত্তি কল রয়েছে। এর অর্থ এটি সরল লোগারিটিমিকের চেয়ে অনেক খারাপ। আমি বিশ্বাস করি না যে ও (এম + এন) এর চেয়ে আরও খারাপ পরিস্থিতি সম্ভবত সম্ভাব্য, প্রতিটি সারি বা প্রতিটি কলাম অবশ্যই অনুসন্ধান করা উচিত। আমি অনুমান করব যে যদিও এই অ্যালগরিদমটি অনেক মানগুলির জন্য সবচেয়ে খারাপ ক্ষেত্রে পরাজিত করতে পারে। এবং সর্বোত্তম অংশটি হ'ল এটি প্যারালাইলাইজযোগ্য, যেহেতু হার্ডওয়ারটি ইদানীং এগিয়ে চলেছে।
জেফরি এল হুইলেটজ

4
@ জেএলডাব্লু: এটি ও (লগ (এন)) - তবে এটি আসলে ও (লগ_ (4/3) (এন ^ 2)) বা এর মতো কিছু। সোভান্তের উত্তর নীচে দেখুন। আপনার উত্তরটি আসলে একই (যদি আপনি মনে করেন যে আপনি যেভাবে করেছিলেন পুনরাবৃত্ত হয়)।
রেক্স কের

4
@ সোভান্তে - সাবহারিগুলি ওভারল্যাপ হয় না। প্রথম বিকল্পে, তাদের কোনও y- উপাদান সাধারণ নেই common দ্বিতীয় বিকল্পে, তাদের কোনও এক্স-এলিমেন্ট মিল নেই।
জেফ্রি এল হুইলেটজ

4
আমি নিশ্চিত নই যে এটি লোগারিথমিক কিনা। আমি টি (0) = 1, টি (এ) = টি (এ / 2) + টি (এ / 4) + 1, যেখানে এ অনুসন্ধান ক্ষেত্র, এবং টি দিয়ে সমাপ্ত হয়ে জটিলতার গণনা করেছি T ক) = ও (ফাইব (এলজি (এ))), যা প্রায় ও (এ ^ 0.7) এবং ও (এন + মি) এর চেয়ে খারাপ যা হে (এ ^ 0.5) হয়। হতে পারে আমি কিছু বোকা ভুল করেছি, তবে দেখে মনে হচ্ছে অ্যালগরিদম ফলহীন শাখাগুলিতে নেমে যেতে অনেক সময় নষ্ট করছে।
ক্রেগ গিডনি

6

দুটি প্রধান উত্তর এখনও অবধি দেওয়া যুক্তিযুক্ত O(log N)"ZigZag পদ্ধতি" এবং O(N+M)বাইনারি অনুসন্ধান পদ্ধতি বলে মনে হচ্ছে । আমি ভেবেছিলাম কিছু দুটি সেটআপের সাথে দুটি পদ্ধতির তুলনা করে কিছু পরীক্ষা করব। বিশদটি এখানে:

অ্যারেটি প্রতিটি পরীক্ষায় N x N বর্গক্ষেত্র হয়, যার সাথে এন 125 থেকে 8000 পর্যন্ত পরিবর্তিত হয় (সবচেয়ে বড় আমার JVM হিপ হ্যান্ডেল করতে পারে)। প্রতিটি অ্যারের আকারের জন্য, আমি একটি একক রাখতে অ্যারেতে একটি এলোমেলো জায়গা বেছে নিয়েছি 2। আমি তারপরে 3যেকোন জায়গায় সম্ভব (2 এর ডান এবং নীচে) রেখেছি এবং তারপরে বাকী অ্যারেটি পূরণ করেছি1। পূর্ববর্তী কিছু মন্তব্যকারীদের মনে হয়েছিল যে এই ধরণের সেটআপ উভয় অ্যালগরিদমের জন্য সবচেয়ে খারাপ পরিস্থিতি চালায় yield প্রতিটি অ্যারের আকারের জন্য, আমি ২ (অনুসন্ধান লক্ষ্য) এর জন্য 100 টি বিভিন্ন এলোমেলো অবস্থান বেছে নিয়ে পরীক্ষা চালিয়েছি। আমি প্রতিটি অ্যালগরিদমের জন্য গড় রান সময় এবং সবচেয়ে খারাপ ক্ষেত্রে রান সময় রেকর্ড করেছি। জাভাতে ভাল এমএস রিডিং পাওয়ার জন্য এটি খুব দ্রুত ঘটছিল, এবং আমি জাভার ন্যানোটাইম ()-তে বিশ্বাস করি না, তাই সমস্ত সময়গুলিতে অভিন্ন পক্ষপাতের উপাদান যুক্ত করতে আমি প্রতিটি পরীক্ষার 1000 বার পুনরাবৃত্তি করেছি। ফলাফল এখানে:

এখানে চিত্র বর্ণনা লিখুন

জিগজেগ গড় এবং খারাপতম উভয় ক্ষেত্রেই প্রতিটি পরীক্ষায় বাইনারিকে পরাজিত করে, তবে এগুলি সবই একে অপরের আরও কম-বেশি মাত্রার ক্রমের মধ্যে থাকে।

জাভা কোডটি এখানে:

public class SearchSortedArray2D {

    static boolean findZigZag(int[][] a, int t) {
        int i = 0;
        int j = a.length - 1;
        while (i <= a.length - 1 && j >= 0) {
            if (a[i][j] == t) return true;
            else if (a[i][j] < t) i++;
            else j--;
        }
        return false;
    }

    static boolean findBinarySearch(int[][] a, int t) {
        return findBinarySearch(a, t, 0, 0, a.length - 1, a.length - 1);
    }

    static boolean findBinarySearch(int[][] a, int t,
            int r1, int c1, int r2, int c2) {
        if (r1 > r2 || c1 > c2) return false; 
        if (r1 == r2 && c1 == c2 && a[r1][c1] != t) return false;
        if (a[r1][c1] > t) return false;
        if (a[r2][c2] < t) return false;

        int rm = (r1 + r2) / 2;
        int cm = (c1 + c2) / 2;
        if (a[rm][cm] == t) return true;
        else if (a[rm][cm] > t) {
            boolean b1 = findBinarySearch(a, t, r1, c1, r2, cm - 1);
            boolean b2 = findBinarySearch(a, t, r1, cm, rm - 1, c2);
            return (b1 || b2);
        } else {
            boolean b1 = findBinarySearch(a, t, r1, cm + 1, rm, c2);
            boolean b2 = findBinarySearch(a, t, rm + 1, c1, r2, c2);
            return (b1 || b2);
        }
    }

    static void randomizeArray(int[][] a, int N) {
        int ri = (int) (Math.random() * N);
        int rj = (int) (Math.random() * N);
        a[ri][rj] = 2;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (i == ri && j == rj) continue;
                else if (i > ri || j > rj) a[i][j] = 3;
                else a[i][j] = 1;
            }
        }
    }

    public static void main(String[] args) {

        int N = 8000;
        int[][] a = new int[N][N];
        int randoms = 100;
        int repeats = 1000;

        long start, end, duration;
        long zigMin = Integer.MAX_VALUE, zigMax = Integer.MIN_VALUE;
        long binMin = Integer.MAX_VALUE, binMax = Integer.MIN_VALUE;
        long zigSum = 0, zigAvg;
        long binSum = 0, binAvg;

        for (int k = 0; k < randoms; k++) {
            randomizeArray(a, N);

            start = System.currentTimeMillis();
            for (int i = 0; i < repeats; i++) findZigZag(a, 2);
            end = System.currentTimeMillis();
            duration = end - start;
            zigSum += duration;
            zigMin = Math.min(zigMin, duration);
            zigMax = Math.max(zigMax, duration);

            start = System.currentTimeMillis();
            for (int i = 0; i < repeats; i++) findBinarySearch(a, 2);
            end = System.currentTimeMillis();
            duration = end - start;
            binSum += duration;
            binMin = Math.min(binMin, duration);
            binMax = Math.max(binMax, duration);
        }
        zigAvg = zigSum / randoms;
        binAvg = binSum / randoms;

        System.out.println(findZigZag(a, 2) ?
                "Found via zigzag method. " : "ERROR. ");
        //System.out.println("min search time: " + zigMin + "ms");
        System.out.println("max search time: " + zigMax + "ms");
        System.out.println("avg search time: " + zigAvg + "ms");

        System.out.println();

        System.out.println(findBinarySearch(a, 2) ?
                "Found via binary search method. " : "ERROR. ");
        //System.out.println("min search time: " + binMin + "ms");
        System.out.println("max search time: " + binMax + "ms");
        System.out.println("avg search time: " + binAvg + "ms");
    }
}

4
+1 হ্যাঁ, ডেটা। :) এনএক্সএম অ্যারেতে এই দুটি পদ্ধতির ভাড়া কীভাবে দেখা যায় তাও আকর্ষণীয় হতে পারে, যেহেতু বাইনারি অনুসন্ধানটি মনে হয় যে আমরা তত্ক্ষণিকভাবে আরও 1 টি-ত্রিমাত্রিক মামলার কাছে পৌঁছাতে চাই ততটুকু আরও দরকারী হওয়া উচিত।
নাট কোহল

5

এটি সমস্যার উপরের নীচে আবদ্ধ হওয়ার একটি সংক্ষিপ্ত প্রমাণ।

আপনি লিনিয়ার সময়ের চেয়ে এটি আরও ভাল করতে পারবেন না (অ্যারের মাত্রাগুলির ক্ষেত্রে, উপাদানগুলির সংখ্যা নয়)। নীচের অ্যারেতে চিহ্নিত হিসাবে চিহ্নিত প্রতিটি উপাদান *5 বা 6 (অন্যদের থেকে স্বতন্ত্রভাবে) হতে পারে। সুতরাং আপনার টার্গেটের মান যদি 6 (বা 5) হয় তবে অ্যালগরিদমের সমস্তটি পরীক্ষা করা দরকার।

1 2 3 4 *
2 3 4 * 7
3 4 * 7 8
4 * 7 8 9
* 7 8 9 10

অবশ্যই এটি বড় অ্যারেগুলিতেও প্রসারিত হয়। এর অর্থ এই উত্তরটি সর্বোত্তম।

আপডেট: জেফরি এল হুইটলজি দ্বারা নির্দেশিত হিসাবে, এটি কেবলমাত্র চলমান সময় বনাম ইনপুট ডেটার আকারের (একক ভেরিয়েবল হিসাবে বিবেচিত) এ্যাসিম্পটোটিক নিম্নতর আবদ্ধ হিসাবে অনুকূল। উভয় অ্যারে মাত্রায় দ্বি-পরিবর্তনশীল ফাংশন হিসাবে বিবেচিত রানিং টাইমকে উন্নত করা যেতে পারে।


আপনি যে উত্তরটি অনুকূল তা প্রদর্শিত হয় নি। উদাহরণস্বরূপ, দশটি জুড়ে এবং এক মিলিয়ন নীচে এমন একটি অ্যারে বিবেচনা করুন যা পঞ্চম সারিতে লক্ষ্য মানের থেকে সমস্ত উচ্চতর মান রয়েছে। সেক্ষেত্রে প্রস্তাবিত অ্যালগরিদম লক্ষ্যটির কাছে যাওয়ার আগে 999,995 মান সন্ধান করবে। আমার মতো একটি দ্বিখণ্ডিত অ্যালগরিদম লক্ষ্য সন্ধানের আগে কেবলমাত্র 18 টি মান সন্ধান করবে। এবং এটি সম্পাদন করে (অসমোটিকভাবে) অন্যান্য সমস্ত ক্ষেত্রে প্রস্তাবিত অ্যালগরিদমের চেয়ে খারাপ নয়।
জেফ্রি এল হুইটলেজ

@ জেফ্রি: হতাশাবাদী মামলার সমস্যাটি এটি নিম্নতর । আপনি ভাল ইনপুটগুলির জন্য অনুকূল করতে পারেন, তবে এমন ইনপুট রয়েছে যেখানে আপনি রৈখিকের চেয়ে ভাল করতে পারবেন না।
রাফা ডগিগার্ড

হ্যাঁ, এমন কিছু ইনপুট রয়েছে যেখানে আপনি রৈখিকের চেয়ে ভাল করতে পারবেন না। কোন ক্ষেত্রে আমার অ্যালগরিদম সেই লিনিয়ার অনুসন্ধান সম্পাদন করে। তবে এমন অন্যান্য ইনপুট রয়েছে যেখানে আপনি রৈখিকের চেয়ে আরও ভাল উপায় করতে পারেন । সুতরাং প্রস্তাবিত সমাধানটি সর্বোত্তম নয়, কারণ এটি সর্বদা লিনিয়ার অনুসন্ধান করে।
জেফরি এল হুইটলেজ

এটি দেখায় যে অ্যালগরিদমটি অবশ্যই বিগোমেগা (মিনিট (এন, মি)) সময় নেবে, বিগোমেগা (এন + এম) নয়। এই কারণেই যখন একটি মাত্রা উল্লেখযোগ্যভাবে ছোট হয় আপনি আরও বেশি ভাল করতে পারেন। উদাহরণস্বরূপ, আপনি যদি জানেন যে কেবলমাত্র 1 টি সারি থাকবে, আপনি লগারিদমিক সময়ে সমস্যাটি সমাধান করতে পারেন। আমি মনে করি একটি অনুকূল অ্যালগরিদমের জন্য সময় লাগবে হে (মিনিট (এন + এম, এন এলজি এম, এম এলজি এন))।
ক্রেগ গিডনি

সেই অনুযায়ী উত্তর আপডেট করুন।
রাফা ডগির্ড

4

আমি মনে করি এটির উত্তর এখানে এবং এটি কোনও ধরণের সাজানো ম্যাট্রিক্সের জন্য কাজ করে

bool findNum(int arr[][ARR_MAX],int xmin, int xmax, int ymin,int ymax,int key)
{
    if (xmin > xmax || ymin > ymax || xmax < xmin || ymax < ymin) return false;
    if ((xmin == xmax) && (ymin == ymax) && (arr[xmin][ymin] != key)) return false;
    if (arr[xmin][ymin] > key || arr[xmax][ymax] < key) return false;
    if (arr[xmin][ymin] == key || arr[xmax][ymax] == key) return true;

    int xnew = (xmin + xmax)/2;
    int ynew = (ymin + ymax)/2;

    if (arr[xnew][ynew] == key) return true;
    if (arr[xnew][ynew] < key)
    {
        if (findNum(arr,xnew+1,xmax,ymin,ymax,key))
            return true;
        return (findNum(arr,xmin,xmax,ynew+1,ymax,key));
    } else {
        if (findNum(arr,xmin,xnew-1,ymin,ymax,key))
            return true;
        return (findNum(arr,xmin,xmax,ymin,ynew-1,key));
    }
}

1

আকর্ষণীয় প্রশ্ন। এই ধারণাটি বিবেচনা করুন - এমন একটি সীমানা তৈরি করুন যেখানে সমস্ত সংখ্যা আপনার টার্গেটের চেয়ে বেশি এবং অন্য যেখানে সমস্ত সংখ্যা আপনার লক্ষ্য থেকে কম are দুজনের মধ্যে যদি কিছু থেকে যায় তবে এটাই আপনার টার্গেট।

যদি আমি আপনার উদাহরণে 3 টি সন্ধান করি, আমি 4 টি হিট না হওয়া পর্যন্ত প্রথম সারি জুড়ে পড়ি, তারপরে 3 টির চেয়ে বেশি সংলগ্ন সংখ্যার (তীরগুলি সহ) সন্ধান করুন:

1 2 4 5 6
2 3 5 7 8
4 6 8 9 10
5 8 9 10 11

এখন আমি 3 এর চেয়ে কম সংখ্যার জন্যও একই কাজ করছি:

1 2 4 5 6
2 3 5 7 8
4 6 8 9 10
5 8 9 10 11

এখন আমি জিজ্ঞাসা করি, দুটি সীমানার ভিতরে কি কিছু আছে? যদি হ্যাঁ, এটি অবশ্যই 3 হওয়া উচিত। যদি না হয় তবে 3 নেই ind পরোক্ষভাবে বাছাই করুন যেহেতু আমি আসলে নম্বরটি পাই না, আমি কেবল অনুমান করি যে এটি অবশ্যই সেখানে উপস্থিত রয়েছে। এতে সমস্ত 3 টি গণনা করার যুক্ত বোনাস রয়েছে।

আমি কয়েকটি উদাহরণে এটি চেষ্টা করেছি এবং মনে হচ্ছে এটি ঠিক আছে।


কোন মন্তব্য ছাড়াই ডাউন ভোট? আমি মনে করি এটি হে (এন ^ 1/2) কারণ সবচেয়ে খারাপ ক্ষেত্রে পারফরম্যান্সটির জন্য তির্যকের একটি চেক প্রয়োজন। কমপক্ষে আমাকে একটি পাল্টা উদাহরণ দেখান যেখানে এই পদ্ধতিটি কাজ করে না!
গ্র্যাম্বো

+1: দুর্দান্ত সমাধান ... সৃজনশীল, এবং ভাল এটির সমস্ত সমাধান খুঁজে পাওয়া যায়।
টনি ডেলরয়

1

অ্যারের তির্যক মাধ্যমে বাইনারি অনুসন্ধান সেরা বিকল্প। আমরা নির্ধারণ করতে পারি যে উপাদানটি তির্যকের উপাদানগুলির চেয়ে কম বা সমান কিনা।


0

উ: সেই লাইনগুলিতে বাইনারি অনুসন্ধান করুন যেখানে লক্ষ্য নম্বরটি থাকতে পারে।

খ। এটিকে একটি গ্রাফ করুন: খুব বড় সংখ্যা পাওয়া গেলে সর্বদা ক্ষুদ্রতম অবাক না হওয়া প্রতিবেশী নোড এবং ব্যাকট্র্যাকিং করে নম্বরটি সন্ধান করুন


0

বাইনারি অনুসন্ধান সেরা পদ্ধতির হবে, তবে। 1/2 x থেকে শুরু করে, 1/2 y এটি অর্ধেক কেটে দেবে। IE 5x5 স্কোয়ারটি x == 2 / y == 3 এর মতো কিছু হবে। আমি লক্ষ্যবস্তুটির দিকনির্দেশে একটি মান নিচে এবং আরও ভাল জোন পর্যন্ত একটি মানকে গোল করেছিলাম।

স্পষ্টতার জন্য পরবর্তী পুনরাবৃত্তি আপনাকে x == 1 / y == 2 বা x == 3 / y == 5 এর মতো কিছু দেবে


0

ঠিক আছে, শুরু করার জন্য, ধরে নেওয়া যাক আমরা একটি বর্গ ব্যবহার করছি।

1 2 3
2 3 4
3 4 5

1. একটি বর্গ অনুসন্ধান করা

আমি ত্রিভুজটিতে একটি বাইনারি অনুসন্ধান ব্যবহার করব। লক্ষ্যটি হ'ল ছোট সংখ্যাটি চিহ্নিত করুন যা লক্ষ্য সংখ্যার চেয়ে কম নয়।

আমি খোঁজ করছি বলুন 4উদাহরণস্বরূপ, তারপর আমি লোকেটিং শেষ পর্যন্ত হবে 5(2,2)

তারপরে, আমি আশ্বস্ত হয়েছি যে যদি 4টেবিলে থাকে তবে এটি হয় (x,2)বা ভিতরে (2,x)থাকা xঅবস্থায় রয়েছে [0,2]। ঠিক আছে, এটি কেবল 2 বাইনারি অনুসন্ধানগুলি।

জটিলতা হতাশ নয়: O(log(N))(দৈর্ঘ্যের সীমাতে 3 বাইনারি অনুসন্ধান N)

2. একটি আয়তক্ষেত্র, নিখুঁত পদ্ধতির সন্ধান করা

অবশ্যই, যখন এটি আলাদা হয় Nএবং Mএকটি আয়তক্ষেত্রের সাথে আলাদা হয়, এই অধঃপতিত কেসটি বিবেচনা করুন:

1  2  3  4  5  6  7  8
2  3  4  5  6  7  8  9
10 11 12 13 14 15 16 17

এবং ধরা যাক আমি খুঁজছি 9... তির্যক পদ্ধতিটি এখনও ভাল তবে তির্যক পরিবর্তনের সংজ্ঞা। এখানে আমার তির্যক [1, (5 or 6), 17]। ধরা যাক আমি তুলেছি [1,5,17], তবে আমি জানি যে 9টেবিলের মধ্যে থাকলে এটি হয় উপ-বিভাগে:

            5  6  7  8
            6  7  8  9
10 11 12 13 14 15 16

এটি আমাদেরকে দুটি আয়তক্ষেত্র দেয়:

5 6 7 8    10 11 12 13 14 15 16
6 7 8 9

সুতরাং আমরা পুনরাবৃত্তি করতে পারেন! সম্ভবত কম উপাদান দিয়ে এক দিয়ে শুরু করা (যদিও এই ক্ষেত্রে এটি আমাদের মেরে ফেলে)।

আমার উল্লেখ করা উচিত যে কোনও মাত্রা যদি এর চেয়ে কম হয় তবে 3আমরা তির্যক পদ্ধতি প্রয়োগ করতে পারি না এবং অবশ্যই একটি বাইনারি অনুসন্ধান ব্যবহার করা উচিত। এখানে এর অর্থ হবে:

  • বাইনারি অনুসন্ধান চালু করুন 10 11 12 13 14 15 16, পাওয়া গেল না
  • বাইনারি অনুসন্ধান চালু করুন 5 6 7 8, পাওয়া গেল না
  • বাইনারি অনুসন্ধান চালু করুন 6 7 8 9, পাওয়া গেল না

এটি মুশকিল কারণ ভাল পারফরম্যান্স পাওয়ার জন্য আপনি সাধারণ আকারের উপর নির্ভর করে বেশ কয়েকটি ক্ষেত্রে পার্থক্য করতে চাইতে পারেন ....

3. একটি আয়তক্ষেত্র, নির্মম পদ্ধতির সন্ধান করা

যদি আমরা একটি বর্গক্ষেত্র নিয়ে কাজ করি তবে এটি অনেক সহজ হবে ... সুতরাং আসুন আমরা কেবল স্কোয়ারের জিনিসগুলি আপ করি।

1  2  3  4  5  6  7  8
2  3  4  5  6  7  8  9
10 11 12 13 14 15 16 17
17 .  .  .  .  .  .  17
.                    .
.                    .
.                    .
17 .  .  .  .  .  .  17

আমাদের এখন একটি স্কোয়ার আছে।

অবশ্যই, আমরা সম্ভবত এই সারিগুলি তৈরি করব না, আমরা কেবল তাদের অনুকরণ করতে পারি।

def get(x,y):
  if x < N and y < M: return table[x][y]
  else: return table[N-1][M-1]            # the max

সুতরাং এটি আরও মেমরি দখল না করে একটি বর্গক্ষেত্রের মতো আচরণ করে (গতির দামে, সম্ভবত, ক্যাশের উপর নির্ভর করে ... ওহ ভাল: পি)


0

সম্পাদনা:

আমি প্রশ্নটি ভুল বুঝেছি। মন্তব্যগুলি নির্দেশ করে যেহেতু এটি কেবলমাত্র আরও সীমাবদ্ধ ক্ষেত্রে কাজ করে।

সি-এর মতো ভাষায় যা সারি-প্রধান ক্রমে ডেটা সঞ্চয় করে, কেবল এটিকে এন * এম আকারের 1D অ্যারে হিসাবে বিবেচনা করুন এবং বাইনারি অনুসন্ধান ব্যবহার করুন।


হ্যাঁ, কেন এটি হওয়ার চেয়ে আরও জটিল করে তুলুন।
এরিক্ক্যালেন

অ্যারে বাছাই করা হয় না, সুতরাং এটিতে কোনও বিন অনুসন্ধান প্রয়োগ করা যাবে না
মিয়লনিয়ার

4
এটি কেবল তখনই কাজ করবে যদি প্রতিটি সারির শেষ উপাদানটি পরবর্তী সারির প্রথম উপাদানটির চেয়ে বেশি হয়, যা সমস্যার প্রস্তাবের চেয়ে অনেক বেশি প্রতিবন্ধী প্রয়োজন।
জেফ্রি এল হুইটলেজ

ধন্যবাদ, আমি আমার উত্তর সম্পাদনা করেছি। যথেষ্ট যত্ন সহকারে পড়েনি, বিশেষত উদাহরণ অ্যারে।
হিউ ব্র্যাকেট

0

আমার কাছে একটি পুনরাবৃত্ত ডিভাইড এবং কনকয়ের সমাধান রয়েছে। এক ধাপের জন্য প্রাথমিক ধারণাটি: আমরা জানি যে বাম-উপরের (এলইউ) সবচেয়ে ছোট এবং ডান-নীচে (আরবি) বৃহত্তম নং, সুতরাং প্রদত্ত নম্বর (এন) অবশ্যই হবে: এন> = এলইউ এবং এন <= আরবি

আইএফ এন == এলইউ এবং এন == আরবি :::: এলিমেন্টটি পাওয়া যায় এবং অবস্থানটি ফেরত / সূচি ফিরে আসে যদি এন> = লু এবং এন <= আরবি = মিথ্যা, কোনটি নেই এবং গর্ভপাত বন্ধ রয়েছে। যদি N> = LU এবং N <= আরবি = সত্য, 2D অ্যারে 2D অ্যারের 4 সমান অংশে প্রতিটি যৌক্তিক উপায়ে ভাগ করুন .. এবং তারপরে চারটি সাব-অ্যারেতে একই অ্যালগো স্টেপ প্রয়োগ করুন।

আমার আলগো সঠিক আছে আমি আমার বন্ধুরা পিসিতে প্রয়োগ করেছি। জটিলতা: প্রতিটি 4 টি তুলনামূলক উপাদানগুলির মোট সংখ্যাকে এক চতুর্থাংশের নিকৃষ্টতম ক্ষেত্রে কমাতে ব্যবহৃত হতে পারে .. সুতরাং আমার জটিলতাটি 1 + 4 x lg (n) + 4 হয়ে আসে তবে সত্যই প্রত্যাশা করে যে এটি ওয়ে কাজ করবে (এন)

আমার মনে হয় আমার জটিলতার গণনায় কোথাও কিছু ভুল হয়েছে, দয়া করে যদি ঠিক করেন তবে ..


0

অনুকূল সমাধানটি শীর্ষ-বাম কোণে শুরু করা উচিত, এর ন্যূনতম মান রয়েছে। আপনি এমন কোনও উপাদানকে আঘাত না করা অবধি ডানদিকে ত্রিভুজটি ডানদিকে সরান যা প্রদত্ত উপাদানটির মান> = মান value যদি উপাদানটির মান প্রদত্ত উপাদানটির সমান হয় তবে প্রত্যাশাকে সত্য হিসাবে পাওয়া যাবে।

অন্যথায়, এখান থেকে আমরা দুটি উপায়ে এগিয়ে যেতে পারি।

কৌশল 1:

  1. কলামে উপরে চলে যান এবং প্রদত্ত উপাদানটির সন্ধান করুন যতক্ষণ না আমরা শেষ পর্যন্ত পৌঁছান। যদি পাওয়া যায়, প্রত্যাবর্তন সত্য হিসাবে পাওয়া যায়
  2. সারিতে বাম দিকে সরান এবং প্রদত্ত উপাদানটির সন্ধান করুন যতক্ষণ না আমরা শেষ প্রান্তে পৌঁছান। যদি পাওয়া যায়, প্রত্যাবর্তন সত্য হিসাবে পাওয়া যায়
  3. প্রত্যাবর্তন মিথ্যা হিসাবে পাওয়া যায়

কৌশল 2: আসুন আমি সারি সূচকটি বোঝাতে পারি এবং জে যে তির্যক উপাদানটির কলাম সূচকটি আমরা থামিয়েছি den (এখানে, আমরা আই = জে, বিটিডাব্লু)। কে = 1।

  • Ik> = 0 পর্যন্ত নীচের পদক্ষেপগুলি পুনরাবৃত্তি করুন
    1. যদি [ik] [j] প্রদত্ত উপাদানটির সমান হয় তবে অনুসন্ধান করুন। যদি হ্যাঁ, প্রত্যাবর্তন সত্য হিসাবে পাওয়া যায়
    2. যদি একটি [i] [জে কে] প্রদত্ত উপাদানের সমান হয় তবে অনুসন্ধান করুন। যদি হ্যাঁ, প্রত্যাবর্তন সত্য হিসাবে পাওয়া যায়
    3. বৃদ্ধি কে

1 2 4 5 6
2 3 5 7 8
4 6 8 9 10
5 8 9 10 11


0
public boolean searchSortedMatrix(int arr[][] , int key , int minX , int maxX , int minY , int maxY){

    // base case for recursion
    if(minX > maxX || minY > maxY)
        return false ;
    // early fails
    // array not properly intialized
    if(arr==null || arr.length==0)
        return false ;
    // arr[0][0]> key return false
    if(arr[minX][minY]>key)
        return false ;
    // arr[maxX][maxY]<key return false
    if(arr[maxX][maxY]<key)
        return false ;
    //int temp1 = minX ;
    //int temp2 = minY ;
    int midX = (minX+maxX)/2 ;
    //if(temp1==midX){midX+=1 ;}
    int midY = (minY+maxY)/2 ;
    //if(temp2==midY){midY+=1 ;}


    // arr[midX][midY] = key ? then value found
    if(arr[midX][midY] == key)
        return true ;
    // alas ! i have to keep looking

    // arr[midX][midY] < key ? search right quad and bottom matrix ;
    if(arr[midX][midY] < key){
        if( searchSortedMatrix(arr ,key , minX,maxX , midY+1 , maxY))
            return true ;
        // search bottom half of matrix
        if( searchSortedMatrix(arr ,key , midX+1,maxX , minY , maxY))
            return true ;
    }
    // arr[midX][midY] > key ? search left quad matrix ;
    else {
         return(searchSortedMatrix(arr , key , minX,midX-1,minY,midY-1));
    }
    return false ;

}

0

আমি পরামর্শ দিচ্ছি, একটিতে সমস্ত অক্ষর সংরক্ষণ করুন 2D list। তারপরে প্রয়োজনীয় উপাদানের সূচকটি তালিকায় উপস্থিত থাকলে এটি সন্ধান করুন।

উপস্থাপন না করা হলে যথাযথ বার্তা মুদ্রণ করুন অন্যথায় সারি এবং কলাম প্রিন্ট করুন:

row = (index/total_columns) এবং column = (index%total_columns -1)

এটি তালিকায় কেবল বাইনারি অনুসন্ধানের সময় ব্যয় করবে।

দয়া করে কোনও সংশোধন করার পরামর্শ দিন। :)


0

যদি ও (এম লগ (এন)) দ্রবণটি কোনও এমএক্সএন অ্যারের জন্য ঠিক থাকে -

template <size_t n>
struct MN * get(int a[][n], int k, int M, int N){
  struct MN *result = new MN;
  result->m = -1;
  result->n = -1;

  /* Do a binary search on each row since rows (and columns too) are sorted. */
  for(int i = 0; i < M; i++){
    int lo = 0; int hi = N - 1;
    while(lo <= hi){
      int mid = lo + (hi-lo)/2;
      if(k < a[i][mid]) hi = mid - 1;
      else if (k > a[i][mid]) lo = mid + 1;
      else{
        result->m = i;
        result->n = mid;
        return result;
      }
    }
  }
  return result;
}

ওয়ার্কিং সি ++ ডেমো।

এটি কাজ না করে বা এটিতে কোনও বাগ থাকলে এটি আমাকে জানান।


0

আমি এক দশকের আরও ভাল অংশের জন্য এই প্রশ্নটি সাক্ষাত্কারে জিজ্ঞাসা করছি এবং আমি মনে করি কেবল একজনই আছেন যিনি একটি অনুকূল অ্যালগরিদম নিয়ে আসতে সক্ষম হয়েছেন।

আমার সমাধান সর্বদা হয়েছে:

  1. বাইনারি মাঝের তির্যকটি অনুসন্ধান করুন যা নীচে এবং ডানদিকে চলমান তির্যকটি আইটেমটি অন্তর্ভুক্ত রয়েছে (rows.count/2, columns.count/2)

  2. যদি লক্ষ্য নম্বরটি পাওয়া যায় তবে সত্য ফিরে আসুন।

  3. অন্যথায়, দুটি সংখ্যার ( uএবং v) সন্ধান করা হবে uযা লক্ষ্যের চেয়ে ছোট, লক্ষ্যের চেয়ে vবড় এবং vএক ডান এবং নীচে থেকে u

  4. অবিচ্ছিন্নভাবে সাব-ম্যাট্রিক্সের ডান uএবং উপরে vএবং এর নীচে uএবং বামে অনুসন্ধান করুন v

আমি বিশ্বাস করি যে এখানে নেটের দেওয়া অ্যালগরিদমের তুলনায় এটি একটি কঠোর উন্নতি , যেহেতু তির্যকটি অনুসন্ধান করা প্রায়শই অনুসন্ধানের অর্ধেকেরও বেশি হ্রাস করতে দেয় (যদি ম্যাট্রিক্স বর্গের কাছাকাছি থাকে), তবে সারি বা কলাম অনুসন্ধান করা সর্বদা একটি বিলোপ ঘটায় ঠিক অর্ধেক

কোডটি এখানে (সম্ভবত ভয়ঙ্করভাবে সুইফটি নয়) রয়েছে:

import Cocoa

class Solution {
    func searchMatrix(_ matrix: [[Int]], _ target: Int) -> Bool {
        if (matrix.isEmpty || matrix[0].isEmpty) {
            return false
        }

        return _searchMatrix(matrix, 0..<matrix.count, 0..<matrix[0].count, target)
    }

    func _searchMatrix(_ matrix: [[Int]], _ rows: Range<Int>, _ columns: Range<Int>, _ target: Int) -> Bool {
        if (rows.count == 0 || columns.count == 0) {
            return false
        }
        if (rows.count == 1) {
            return _binarySearch(matrix, rows.lowerBound, columns, target, true)
        }
        if (columns.count == 1) {
            return _binarySearch(matrix, columns.lowerBound, rows, target, false)
        }

        var lowerInflection = (-1, -1)
        var upperInflection = (Int.max, Int.max)
        var currentRows = rows
        var currentColumns = columns
        while (currentRows.count > 0 && currentColumns.count > 0 && upperInflection.0 > lowerInflection.0+1) {
            let rowMidpoint = (currentRows.upperBound + currentRows.lowerBound) / 2
            let columnMidpoint = (currentColumns.upperBound + currentColumns.lowerBound) / 2
            let value = matrix[rowMidpoint][columnMidpoint]
            if (value == target) {
                return true
            }

            if (value > target) {
                upperInflection = (rowMidpoint, columnMidpoint)
                currentRows = currentRows.lowerBound..<rowMidpoint
                currentColumns = currentColumns.lowerBound..<columnMidpoint
            } else {
                lowerInflection = (rowMidpoint, columnMidpoint)
                currentRows = rowMidpoint+1..<currentRows.upperBound
                currentColumns = columnMidpoint+1..<currentColumns.upperBound
            }
        }
        if (lowerInflection.0 == -1) {
            lowerInflection = (upperInflection.0-1, upperInflection.1-1)
        } else if (upperInflection.0 == Int.max) {
            upperInflection = (lowerInflection.0+1, lowerInflection.1+1)
        }

        return _searchMatrix(matrix, rows.lowerBound..<lowerInflection.0+1, upperInflection.1..<columns.upperBound, target) || _searchMatrix(matrix, upperInflection.0..<rows.upperBound, columns.lowerBound..<lowerInflection.1+1, target)
    }

    func _binarySearch(_ matrix: [[Int]], _ rowOrColumn: Int, _ range: Range<Int>, _ target: Int, _ searchRow : Bool) -> Bool {
        if (range.isEmpty) {
            return false
        }

        let midpoint = (range.upperBound + range.lowerBound) / 2
        let value = (searchRow ? matrix[rowOrColumn][midpoint] : matrix[midpoint][rowOrColumn])
        if (value == target) {
            return true
        }

        if (value > target) {
            return _binarySearch(matrix, rowOrColumn, range.lowerBound..<midpoint, target, searchRow)
        } else {
            return _binarySearch(matrix, rowOrColumn, midpoint+1..<range.upperBound, target, searchRow)
        }
    }
}

-1

স্কোয়ার ম্যাট্রিক্স নীচে দেওয়া হয়েছে:

[এবিসি]
[ডিএফ]
[ইজক]

আমরা জানি যে একটি <সি, ডি <এফ, আই <কে। আমরা যা জানি না তা হ'ল ডি <সি বা ডি> সি ইত্যাদি We

শেষ উপাদানগুলি (সি, এফ, কে) এর দিকে তাকালে আমরা এক ধরণের ফিল্টার করতে পারি: এন এন <সি? অনুসন্ধান (): পরবর্তী ()। সুতরাং, আমাদের সারিগুলির উপর n পুনরাবৃত্তি রয়েছে, প্রতিটি সারি বাইনারি অনুসন্ধানের জন্য O (লগ (এন)) বা ফিল্টার আউট হলে O (1) নেবে with

আমাকে একটি উদাহরণ দাও যেখানে এন = জে,

1) সারি পরীক্ষা করুন 1. জে <সি? (না, পরবর্তী যান)

2) সারি পরীক্ষা করুন 2. j <f? (হ্যাঁ, বিন অনুসন্ধান কিছুই পান না)

3) সারি পরীক্ষা করুন 3. j <কে? (হ্যাঁ, বিন অনুসন্ধান এটি সন্ধান করে)

N = q দিয়ে আবার চেষ্টা করুন,

1) সারি পরীক্ষা করুন 1. কি <সি? (না, পরবর্তী যান)

2) সারি পরীক্ষা করুন 2. কি <এফ? (না, পরবর্তী যান)

3) সারি পরীক্ষা করুন 3. কি <কে? (না, পরবর্তী যান)

এর বাইরে সম্ভবত আরও ভাল সমাধান আছে তবে এটি ব্যাখ্যা করা সহজ .. :)


-4

যেহেতু এটি একটি সাক্ষাত্কারের প্রশ্ন, এটি সমান্তরাল প্রোগ্রামিং এবং মানচিত্র-হ্রাস অ্যালগরিদমগুলির আলোচনার দিকে নিয়ে গেছে বলে মনে হচ্ছে ।

Http://code.google.com/intl/de/edu/parallel/mapreduce-tutorial.html দেখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.