ओवरलैप के लिए दो पूर्णांक श्रेणियों का परीक्षण करने का सबसे कुशल तरीका क्या है?


252

दो समावेशी पूर्णांक श्रेणियों को देखते हुए [X1: x2] और [y1: y2], जहां X1 2 x2 और y1 y y2 है, यह परीक्षण करने का सबसे कुशल तरीका है कि क्या दो श्रेणियों में कोई ओवरलैप है?

एक साधारण कार्यान्वयन इस प्रकार है:

bool testOverlap(int x1, int x2, int y1, int y2) {
  return (x1 >= y1 && x1 <= y2) ||
         (x2 >= y1 && x2 <= y2) ||
         (y1 >= x1 && y1 <= x2) ||
         (y2 >= x1 && y2 <= x2);
}

लेकिन मुझे उम्मीद है कि इसकी गणना करने के लिए अधिक कुशल तरीके हैं।

सबसे कम संचालन के संदर्भ में कौन सी विधि सबसे अधिक कुशल होगी।


दिलचस्प रूप से कुछ के लिए संबंधित हो सकता है - stackoverflow.com/q/17138760/104380
vsync

जवाबों:


454

ओवरलैप करने के लिए सीमाओं का क्या मतलब है? इसका अर्थ है कि कुछ संख्या C मौजूद है जो दोनों श्रेणियों में है, अर्थात

x1 <= C <= x2

तथा

y1 <= C <= y2

अब, यदि हमें यह मानने की अनुमति है कि श्रेणियाँ अच्छी तरह से बनाई गई हैं (ताकि X1 <= x2 और y1 <= y2) तो यह परीक्षण के लिए पर्याप्त है

x1 <= y2 && y1 <= x2

1
मेरा मानना ​​है कि यह होना चाहिए x1 <= y2 && y1 >= x2, नहीं?
डेविड बेक

8
@DavidBeck: नहीं, यदि y1> x2 है, तो निश्चित रूप से सीमाएं ओवरलैप नहीं होती हैं (जैसे [1: 2] और [3: 4] पर विचार करें: y1 = 3 और x2 = 2, इसलिए y1> x2, लेकिन कोई ओवरलैप नहीं है) ।
साइमन निकर्सन

8
यह एक बेहतर जवाब होगा यदि आपने तर्क को थोड़ा और समझाया
shoosh

2
@ विनीत देवराज - आपको क्यों लगता है कि यह काम नहीं करता है? X1 = 1, y1 = 1, x2 = 1, y2 = 1, इसलिए X1 <= y2 && y1 <= x2 सत्य है, इस प्रकार, एक ओवरलैप है।
dcp

2
स्पष्टीकरण यहाँ है: stackoverflow.com/questions/325933/…
एलेक्स

138

दो श्रेणियों [X1, x2], [y1, y2] को देखते हुए

def is_overlapping(x1,x2,y1,y2):
    return max(x1,y1) <= min(x2,y2)

4
@ uyuyuy99 - केवल इतना कुशल नहीं है, क्योंकि जब यह चेक प्रति सेकंड कई बार किया जा रहा है, तो कॉलिंग फ़ंक्शन कुछ ऐसा है जिससे आप बचना चाहते हैं, और खुद को जितना गणित करना है, उसे मूल पर रखें
vsync

7
@vsync आधुनिक ब्राउज़र, Math.max जैसे फ़ंक्शन को इनलाइन और ऑप्टिमाइज़ करेंगे, प्रदर्शन पर कोई ध्यान देने योग्य प्रभाव नहीं होना चाहिए।
एश्टन सिक्स

1
@AshtonWar - दिलचस्प। क्या आपके पास एक लेख है जो यह बताता है कि क्या अंतर्निर्मित है और क्या नहीं है?
vsync

@vsync नहीं, लेकिन मुझे यकीन है कि आप स्वयं जानकारी पा सकते हैं
एश्टन सिक्स

6
इसके अलावा, ध्यान दें कि min(x2,y2) - max(x1,y1)आपकी आवश्यकता के मामले में ओवरलैप की मात्रा प्रदान करता है।
13:15 बजे user1556435

59

यह एक सामान्य मानव मस्तिष्क को आसानी से ताना जा सकता है, इसलिए मैंने समझने के लिए आसान होने के लिए एक दृश्य दृष्टिकोण पाया है:

ओवरलैप पागलपन

ले स्पष्टीकरण

यदि दो रेंज एक स्लॉट में फिट होने के लिए "बहुत मोटी हैं" जो कि दोनों की चौड़ाई का योग है, तो वे ओवरलैप करते हैं।

श्रेणियों के लिए [a1, a2]और [b1, b2]यह होगा:

/**
 * we are testing for:
 *     max point - min point < w1 + w2    
 **/
if max(a2, b2) - min(a1, b1) < (a2 - a1) + (b2 - b1) {
  // too fat -- they overlap!
}

3
आपके चित्रों में चित्रित किए गए मामलों की तुलना में अधिक मामले हैं। जैसे, क्या होगा अगर w2 w1 से पहले शुरू होता है और w1 के बाद समाप्त होता है?
विलियमकफ

7
@WilliamKF तर्क सही है
फ्लोटिंगरॉक

2
सहमत हुए, लेकिन मुझे लगता है कि यह तीसरी तस्वीर प्रदान करने में मदद कर सकता है।
विलियमके

3
@WilliamKF के बाद आपको और अधिक छवियों की आवश्यकता है 16 अलग-अलग संयोजन हैं जिन्हें 2 श्रेणियों में रखा जा सकता है ...
पीटर

3
यदि आप इस विधि का उपयोग करते हैं, तो सावधान रहें, क्योंकि राशि a2 - a1 + b2 - b1अतिप्रवाह कर सकती है। इसे ठीक करने के लिए max(a2, b2) - a2 - b2 < min(a1, b1) - a1 - b1, फार्मूला को पुनर्व्यवस्थित करें , जो सरल max(a1, b1) < min(a2, b2)बनाता है, कुछ अंकगणित को सहेजता है और किसी भी संभावित ओवरफ्लो से बचता है (यह AX-Labs का जवाब नीचे है)। विशेष मामले में जहां आप जानते हैं b2-b1=a2-a1, फ्लोटिंगरॉक के सूत्र का एक और उपयोगी पुनर्व्यवस्था है max(a2, b2) - min(a1, b1) - (b2 - b1) < a2-a1, जो बन जाता है abs(b1-a1) < a2 - a1
पाओलो बोन्जिनी

44

साइमन का शानदार जवाब , लेकिन मेरे लिए रिवर्स केस के बारे में सोचना आसान था।

ओवरलैप कब नहीं होता है? जब उनमें से एक दूसरे के समाप्त होने के बाद शुरू होता है तो वे ओवरलैप नहीं करते हैं:

dont_overlap = x2 < y1 || x1 > y2

जब वे ओवरलैप करते हैं तो यह व्यक्त करना आसान होता है:

overlap = !dont_overlap = !(x2 < y1 || x1 > y2) = (x2 >= y1 && x1 <= y2)

1
मेरे लिए, अभिव्यक्ति को समझना आसान है: x2 <y1 || y2 <X1 // जहां मैं "से अधिक" के बजाय 'से कम' का उपयोग करता हूं।
पार्क जोंगबम

26

शुरू के अधिकतम से पर्वतमाला के सिरों के न्यूनतम को घटाना लगता है। यदि परिणाम शून्य से कम या इसके बराबर है, तो हमारे पास एक ओवरलैप है। यह इसे अच्छी तरह से दिखाता है:

यहां छवि विवरण दर्ज करें


2
यह सभी मामलों को शामिल करता है
user3290180

10

मुझे लगता है कि सवाल सबसे तेज कोड के बारे में था, न कि सबसे छोटे कोड के बारे में। सबसे तेज़ संस्करण को शाखाओं से बचना है, इसलिए हम कुछ इस तरह लिख सकते हैं:

साधारण मामले के लिए:

static inline bool check_ov1(int x1, int x2, int y1, int y2){
    // insetead of x1 < y2 && y1 < x2
    return (bool)(((unsigned int)((y1-x2)&(x1-y2))) >> (sizeof(int)*8-1));
};

या, इस मामले के लिए:

static inline bool check_ov2(int x1, int x2, int y1, int y2){
    // insetead of x1 <= y2 && y1 <= x2
    return (bool)((((unsigned int)((x2-y1)|(y2-x1))) >> (sizeof(int)*8-1))^1);
};

7
अपने कंपाइलर पर विश्वास रखें। एक यथोचित सक्षम संकलक और सीपीयू आर्किटेक्चर (यहां तक ​​कि 2010 में भी) की अभिव्यक्ति की x1 <= y2 && y1 <= x2 इसमें कोई शाखा नहीं है । वास्तव में, x86 पर, उत्पन्न कोड मूल रूप से सरल अभिव्यक्ति बनाम इस उत्तर में कोड के लिए समान है।
सोरेन लोर्बोर्ग


4

यदि आप एक ही समय में दो श्रेणियों [x1:x2]और [y1:y2], प्राकृतिक / विरोधी प्राकृतिक आदेश श्रेणियों के साथ काम कर रहे थे :

  • प्राकृतिक आदेश: x1 <= x2 && y1 <= y2या
  • प्राकृतिक विरोधी आदेश: x1 >= x2 && y1 >= y2

तो आप इस का उपयोग करने के लिए जाँच कर सकते हैं:

वे अतिव्याप्त हैं <=> (y2 - x1) * (x2 - y1) >= 0

जहां केवल चार ऑपरेशन शामिल हैं:

  • दो घटाव
  • एक गुणा
  • एक तुलना

1

यदि कोई एक-लाइनर की तलाश में है जो वास्तविक ओवरलैप की गणना करता है:

int overlap = ( x2 > y1 || y2 < x1 ) ? 0 : (y2 >= y1 && x2 <= y1 ? y1 : y2) - ( x2 <= x1 && y2 >= x1 ? x1 : x2) + 1; //max 11 operations

यदि आप कुछ कम संचालन चाहते हैं, लेकिन कुछ और चर:

bool b1 = x2 <= y1;
bool b2 = y2 >= x1;
int overlap = ( !b1 || !b2 ) ? 0 : (y2 >= y1 && b1 ? y1 : y2) - ( x2 <= x1 && b2 ? x1 : x2) + 1; // max 9 operations

1

उलटे तरीके से सोचें : 2 पर्वतमालाओं को कैसे ओवरलैप नहीं बनाया जाए ? दिया गया है [x1, x2], तो बाहर[y1, y2] होना चाहिए , अर्थात, जो इसके बराबर है । [x1, x2]y1 < y2 < x1 or x2 < y1 < y2y2 < x1 or x2 < y1

इसलिए, 2 पर्वतमाला को ओवरलैप करने की शर्त:, not(y2 < x1 or x2 < y1)जो कि y2 >= x1 and x2 >= y1(साइमन द्वारा स्वीकार किए गए उत्तर के साथ समान) के बराबर है ।


एक ही लग रहा है के रूप में क्या (17:36 पर 2 मार्च '16) जवाब @damluar
Nakilon

0

आपके पास पहले से ही सबसे कुशल प्रतिनिधित्व है - यह नंगे न्यूनतम है जिसे जांचने की आवश्यकता है जब तक कि आपको यह सुनिश्चित नहीं है कि X1 <x2 आदि, तब दूसरों द्वारा प्रदान किए गए समाधानों का उपयोग करें।

आपको शायद ध्यान देना चाहिए कि कुछ संकलक वास्तव में आपके लिए इसे अनुकूलित करेंगे - जैसे ही उन 4 अभिव्यक्तियों में से कोई भी सही वापस लौटता है। यदि कोई सच में लौटता है, तो अंतिम परिणाम होगा - इसलिए अन्य चेक को छोड़ दिया जा सकता है।


2
सभी कंपाइलर करेंगे। सभी (मेरे ज्ञान के लिए) वर्तमान में सी-स्टाइल सिंटैक्स (सी, सी ++, सी #, जावा, आदि) के साथ इस्तेमाल की जाने वाली भाषाएं शॉर्ट-सर्क्युलेटेड बूलियन ऑपरेटरों को नियुक्त करती हैं और यह उन भाषाओं को संचालित करने वाले विभिन्न मानकों का हिस्सा है। यदि ऑपरेशन के परिणाम को निर्धारित करने के लिए बाएंहैंड मान का परिणाम पर्याप्त है, तो दाहिने मूल्य का मूल्यांकन नहीं किया जाता है।
जोनाथन ग्रिप्सन

1
मार्क एच - संकलक दूसरे खंड पर छोड़ देगा यदि यह हो सकता है: तो अगर आपके पास एक फ़ंक्शन है जो कहता है: फू (इंट सी) {इंट i = 0; if (c <3 || ++ i == argc) printf ("इनसाइड \ n"); प्रिंटफ ("i% d \ n", i); फू (2) प्रिंट करेगा: इनसाइड आई 0 है और फू (4) प्रिंट होगा: i 1 है (gcc 4.4.3 पर परीक्षण किया गया है, लेकिन मैंने icc में कुछ बदसूरत कोड के लिए इस व्यवहार पर भरोसा किया है)
जे टेलर

0

मेरा मामला अलग है। मैं दो समय सीमा ओवरलैप की जाँच करना चाहते हैं। एक यूनिट टाइम ओवरलैप नहीं होना चाहिए। यहाँ गो कार्यान्वयन है।

    func CheckRange(as, ae, bs, be int) bool {
    return (as >= be) != (ae > bs)
    }

परीक्षण के मामलों

if CheckRange(2, 8, 2, 4) != true {
        t.Error("Expected 2,8,2,4 to equal TRUE")
    }

    if CheckRange(2, 8, 2, 4) != true {
        t.Error("Expected 2,8,2,4 to equal TRUE")
    }

    if CheckRange(2, 8, 6, 9) != true {
        t.Error("Expected 2,8,6,9 to equal TRUE")
    }

    if CheckRange(2, 8, 8, 9) != false {
        t.Error("Expected 2,8,8,9 to equal FALSE")
    }

    if CheckRange(2, 8, 4, 6) != true {
        t.Error("Expected 2,8,4,6 to equal TRUE")
    }

    if CheckRange(2, 8, 1, 9) != true {
        t.Error("Expected 2,8,1,9 to equal TRUE")
    }

    if CheckRange(4, 8, 1, 3) != false {
        t.Error("Expected 4,8,1,3 to equal FALSE")
    }

    if CheckRange(4, 8, 1, 4) != false {
        t.Error("Expected 4,8,1,4 to equal FALSE")
    }

    if CheckRange(2, 5, 6, 9) != false {
        t.Error("Expected 2,5,6,9 to equal FALSE")
    }

    if CheckRange(2, 5, 5, 9) != false {
        t.Error("Expected 2,5,5,9 to equal FALSE")
    }

आप देख सकते हैं कि सीमा तुलना में XOR पैटर्न है


-10

यहाँ मेरा संस्करण है:

int xmin = min(x1,x2)
  , xmax = max(x1,x2)
  , ymin = min(y1,y2)
  , ymax = max(y1,y2);

for (int i = xmin; i < xmax; ++i)
    if (ymin <= i && i <= ymax)
        return true;

return false;

जब तक आप व्यापक स्तर पर पूर्णांक के अरबों पर कुछ उच्च-प्रदर्शन रेंज-चेकर नहीं चला रहे हैं, तब तक हमारे संस्करणों को इसी तरह प्रदर्शन करना चाहिए। मेरा कहना है, यह सूक्ष्म अनुकूलन है।


मुझे लगता है कि आप यहां विनिर्देश पर चले गए हैं। यह माना जाता है कि एक्स 1 से एक्स 2 आरोही / डिकोडिंग (किसी भी तरह से, यह क्रमबद्ध है) - लूप की कोई आवश्यकता नहीं है, आपको केवल सिर और पूंछ तत्वों की जांच करने की आवश्यकता है। मैं हालांकि न्यूनतम / अधिकतम समाधान पसंद करता हूं - सिर्फ इसलिए कि जब आप बाद में कोड पर वापस आते हैं तो पढ़ना आसान होता है।
मार्क

12
-1: यह माइक्रो-ऑप्टिमाइज़ेशन नहीं है; यह एक उपयुक्त एल्गोरिथ्म चुन रहा है। आपका एल्गोरिथ्म O (n) है जब एक साधारण O (1) विकल्प होता है।
साइमन निकर्सन

ऐसा तब होता है जब "समय से पहले अनुकूलन सभी बुराई की जड़ है" व्यवहार के कुछ सामयिक पैटर्न पर आधे-गंभीर टिप्पणी के बजाय अयोग्य के लिए एक हिंसात्मक धार्मिक सिद्धांत बन जाता है।
रगोम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.