อัลกอริทึม: วิธีที่มีประสิทธิภาพในการลบจำนวนเต็มที่ซ้ำกันออกจากอาร์เรย์


93

ฉันได้รับปัญหานี้จากการสัมภาษณ์กับ Microsoft

ให้อาร์เรย์ของจำนวนเต็มสุ่มเขียนอัลกอริทึมใน C ที่ลบตัวเลขที่ซ้ำกันและส่งกลับตัวเลขที่ไม่ซ้ำกันในอาร์เรย์เดิม

เช่นอินพุต: {4, 8, 4, 1, 1, 2, 9} เอาต์พุต:{4, 8, 1, 2, 9, ?, ?}

ข้อแม้อย่างหนึ่งคืออัลกอริทึมที่คาดไว้ไม่ควรกำหนดให้เรียงลำดับอาร์เรย์ก่อน และเมื่อนำองค์ประกอบออกแล้วองค์ประกอบต่อไปนี้จะต้องเลื่อนไปข้างหน้าเช่นกัน อย่างไรก็ตามค่าขององค์ประกอบที่หางของอาร์เรย์ซึ่งองค์ประกอบถูกเลื่อนไปข้างหน้านั้นมีความสำคัญเล็กน้อย

อัปเดต:ผลลัพธ์จะต้องถูกส่งคืนในอาร์เรย์ดั้งเดิมและไม่ควรใช้โครงสร้างข้อมูลตัวช่วย (เช่นแฮชแท็ก) อย่างไรก็ตามฉันเดาว่าไม่จำเป็นต้องเก็บรักษาคำสั่งซื้อ

Update2:สำหรับผู้ที่สงสัยว่าเหตุใดจึงมีข้อ จำกัด ที่ทำไม่ได้นี่เป็นคำถามสัมภาษณ์และจะมีการพูดถึงข้อ จำกัด เหล่านี้ในระหว่างกระบวนการคิดเพื่อดูว่าฉันจะคิดอย่างไร


4
คุณต้องรักษาลำดับของตัวเลขที่ไม่ซ้ำกันหรือไม่?
Douglas Leeder

1
ต้องส่งคืนผลลัพธ์ในอาร์เรย์เดิมหรือไม่
Douglas Leeder

1
ฉันได้อัปเดตคำถามแล้ว ผลลัพธ์ควรถูกส่งคืนในอาร์เรย์เดิม อย่างไรก็ตามลำดับของลำดับไม่สำคัญ
ejel

3
มันค่อนข้างน่ารำคาญเมื่อมีคนจับผิดคำตอบของคำถามและคำตอบอื่น ๆ เพียงแค่อดทนคนจะไปที่นั่น
GManNickG

2
เหตุใดจึงไม่อนุญาตให้ใช้แฮชแท็ก ข้อ จำกัด นั้นไม่สมเหตุสมผล
RBarryYoung

คำตอบ:


20

เกี่ยวกับ:

void rmdup(int *array, int length)
{
    int *current , *end = array + length - 1;

    for ( current = array + 1; array < end; array++, current = array + 1 )
    {
        while ( current <= end )
        {
            if ( *current == *array )
            {
                *current = *end--;
            }
            else
            {
                current++;
            }
        }
    }
}

ควรเป็น O (n ^ 2) หรือน้อยกว่า


3
นี่เป็นวิธีง่ายๆและมีแนวโน้มว่าคำถามสัมภาษณ์จะเป็นอย่างไร
Kirk Broadhurst

8
พวกเขาอาจกำลังตรวจสอบเพื่อดูว่าคุณไม่ต้องทนทุกข์ทรมานกับการเพิ่มประสิทธิภาพก่อนเวลาอันควรเว้นแต่ว่าจะให้ข้อ จำกัด รันไทม์แก่คุณด้วย! :-)
Trevor Tippins

16
ฮ่า ๆ แม้ว่าจะเร็วกว่าอย่างแน่นอนในการจัดเรียงอาร์เรย์และทำงานกับอาร์เรย์ที่จัดเรียง การเรียงลำดับควรจัดเตรียมโดย API และไม่มีการเพิ่มประสิทธิภาพก่อนกำหนด
ziggystar

2
ไม่ควรเป็น while (ปัจจุบัน <= end) แทนที่จะเป็น while (ปัจจุบัน <end)?
Shail

2
เหตุใดจึงยอมรับว่าเป็นคำตอบที่ถูกต้อง หากไม่จำเป็นต้องเก็บรักษาคำสั่งซื้อก็ไม่ดีกว่าที่จะใช้การผสานการเรียงลำดับ O (nlogn) แล้วลบองค์ประกอบที่ซ้ำกันใน O (n) ... ความซับซ้อนทั้งหมด - O (nlogn) ซึ่งดีกว่าโซลูชันนี้มาก
Pawan

136

วิธีแก้ปัญหาที่แฟนของฉันแนะนำคือรูปแบบของการผสาน การปรับเปลี่ยนเพียงอย่างเดียวคือในระหว่างขั้นตอนการผสานให้ละเว้นค่าที่ซ้ำกัน วิธีนี้จะเป็นเช่นกัน O (n log n) ด้วยวิธีนี้การลบการเรียงลำดับ / การทำซ้ำจะรวมเข้าด้วยกัน อย่างไรก็ตามฉันไม่แน่ใจว่ามันสร้างความแตกต่างหรือไม่


8
คำแนะนำที่ดี แต่คุณจะต้องมีการทำบัญชีเพื่อติดตามการสิ้นสุดของผลลัพธ์การรวมแต่ละรายการ ฉันทำครั้งนี้จริง ๆ แล้วและใช่การกำจัดรายการที่ซ้ำกันเมื่อคุณผสานทำให้เร็วขึ้นมาก
Mark Ransom

2
ไม่ชัดเจนว่าพื้นที่พิเศษ O (N / 2) นับเป็น "โครงสร้างข้อมูลตัวช่วย" ที่ถูกห้ามในคำถามหรือไม่ - ฉันไม่รู้ว่าข้อ จำกัด นี้มีจุดมุ่งหมายเพื่อกำหนด O (1) พื้นที่เพิ่มเติมหรือเพียงเพื่อกำหนดว่า คำตอบไม่ควรขึ้นอยู่กับการใช้โครงสร้างข้อมูลขนาดใหญ่ บางทีการผสานมาตรฐานก็ใช้ได้ แต่ถ้าไม่ใช่เคล็ดลับยอดนิยม: อย่าพยายามเขียนการเรียงลำดับการผสานในสถานที่ในการสัมภาษณ์เว้นแต่คุณจะรู้จริงๆว่าคุณกำลังทำอะไรอยู่
Steve Jessop

ความคิดที่ดี. แต่ต้องการให้ข้อมูลที่เหลืออยู่คงลำดับเดิม
Hardy Feng

4
กระดาษที่อธิบายถึงสิ่งที่แฟนของคุณแนะนำมีดังนี้dc-pubs.dbs.uni-leipzig.de/files/…
Mike B

50

ฉันเคยโพสต์สิ่งนี้มาแล้วครั้งหนึ่งใน SO แต่ฉันจะทำซ้ำที่นี่เพราะมันเจ๋งมาก มันใช้การแฮชสร้างสิ่งที่เหมือนแฮชที่ตั้งไว้ รับประกันว่าจะเป็น O (1) ในช่องว่างของซอกใบ (การเรียกซ้ำเป็นการเรียกหาง) และโดยทั่วไปจะมีความซับซ้อนของเวลา O (N) อัลกอริทึมมีดังนี้:

  1. รับองค์ประกอบแรกของอาร์เรย์ซึ่งจะเป็นหน่วยยาม
  2. จัดลำดับส่วนที่เหลือของอาร์เรย์ใหม่ให้มากที่สุดเพื่อให้แต่ละองค์ประกอบอยู่ในตำแหน่งที่สอดคล้องกับแฮช เมื่อขั้นตอนนี้เสร็จสมบูรณ์รายการที่ซ้ำกันจะถูกค้นพบ ตั้งค่าให้เท่ากับแมวมอง
  3. ย้ายองค์ประกอบทั้งหมดที่ดัชนีเท่ากับแฮชไปที่จุดเริ่มต้นของอาร์เรย์
  4. ย้ายองค์ประกอบทั้งหมดที่มีค่าเท่ากับ sentinel ยกเว้นองค์ประกอบแรกของอาร์เรย์ไปยังจุดสิ้นสุดของอาร์เรย์
  5. สิ่งที่เหลืออยู่ระหว่างองค์ประกอบที่แฮชอย่างถูกต้องและองค์ประกอบที่ซ้ำกันจะเป็นองค์ประกอบที่ไม่สามารถวางในดัชนีที่สอดคล้องกับแฮชของพวกมันได้เนื่องจากการชนกัน ฟื้นฟูเพื่อจัดการกับองค์ประกอบเหล่านี้

สิ่งนี้สามารถแสดงให้เห็นว่าเป็น O (N) หากไม่มีสถานการณ์ทางพยาธิวิทยาในการแฮช: แม้ว่าจะไม่มีการซ้ำกันองค์ประกอบประมาณ 2/3 จะถูกกำจัดออกในการเรียกซ้ำแต่ละครั้ง การเรียกซ้ำแต่ละระดับคือ O (n) โดยที่ n ขนาดเล็กคือจำนวนองค์ประกอบที่เหลือ ปัญหาเดียวคือในทางปฏิบัติมันช้ากว่าการเรียงลำดับอย่างรวดเร็วเมื่อมีรายการที่ซ้ำกันน้อยเช่นการชนกันจำนวนมาก อย่างไรก็ตามเมื่อมีการทำซ้ำจำนวนมากมันรวดเร็วอย่างน่าอัศจรรย์

แก้ไข: ในการใช้งาน D ปัจจุบัน hash_t คือ 32 บิต ทุกอย่างเกี่ยวกับอัลกอริทึมนี้อนุมานได้ว่าจะมีการชนกันของแฮชน้อยมากในพื้นที่เต็ม 32 บิต อย่างไรก็ตามการชนกันอาจเกิดขึ้นได้บ่อยในโมดูลัสสเปซ อย่างไรก็ตามสมมติฐานนี้จะเป็นจริงสำหรับชุดข้อมูลที่มีขนาดสมเหตุสมผล หากคีย์มีค่าน้อยกว่าหรือเท่ากับ 32 บิตอาจเป็นแฮชของตัวเองได้หมายความว่าการชนกันในพื้นที่ 32 บิตทั้งหมดเป็นไปไม่ได้ หากมีขนาดใหญ่กว่าคุณก็ไม่สามารถใส่เข้าไปในพื้นที่แอดเดรสหน่วยความจำ 32 บิตได้เพียงพอเนื่องจากเป็นปัญหา ฉันคิดว่า hash_t จะเพิ่มขึ้นเป็น 64 บิตในการใช้งาน D แบบ 64 บิตโดยที่ชุดข้อมูลสามารถมีขนาดใหญ่ขึ้นได้ นอกจากนี้หากสิ่งนี้เคยพิสูจน์ได้ว่าเป็นปัญหาเราสามารถเปลี่ยนฟังก์ชันแฮชได้ในแต่ละระดับของการเรียกซ้ำ

นี่คือการใช้งานในภาษาโปรแกรม D:

void uniqueInPlace(T)(ref T[] dataIn) {
    uniqueInPlaceImpl(dataIn, 0);
}

void uniqueInPlaceImpl(T)(ref T[] dataIn, size_t start) {
    if(dataIn.length - start < 2)
        return;

    invariant T sentinel = dataIn[start];
    T[] data = dataIn[start + 1..$];

    static hash_t getHash(T elem) {
        static if(is(T == uint) || is(T == int)) {
            return cast(hash_t) elem;
        } else static if(__traits(compiles, elem.toHash)) {
            return elem.toHash;
        } else {
            static auto ti = typeid(typeof(elem));
            return ti.getHash(&elem);
        }
    }

    for(size_t index = 0; index < data.length;) {
        if(data[index] == sentinel) {
            index++;
            continue;
        }

        auto hash = getHash(data[index]) % data.length;
        if(index == hash) {
            index++;
            continue;
        }

        if(data[index] == data[hash]) {
            data[index] = sentinel;
            index++;
            continue;
        }

        if(data[hash] == sentinel) {
            swap(data[hash], data[index]);
            index++;
            continue;
        }

        auto hashHash = getHash(data[hash]) % data.length;
        if(hashHash != hash) {
            swap(data[index], data[hash]);
            if(hash < index)
                index++;
        } else {
            index++;
        }
    }


    size_t swapPos = 0;
    foreach(i; 0..data.length) {
        if(data[i] != sentinel && i == getHash(data[i]) % data.length) {
            swap(data[i], data[swapPos++]);
        }
    }

    size_t sentinelPos = data.length;
    for(size_t i = swapPos; i < sentinelPos;) {
        if(data[i] == sentinel) {
            swap(data[i], data[--sentinelPos]);
        } else {
            i++;
        }
    }

    dataIn = dataIn[0..sentinelPos + start + 1];
    uniqueInPlaceImpl(dataIn, start + swapPos + 1);
}

1
คำตอบที่ยอดเยี่ยมและประเมินต่ำมาก! ฉันชอบแนวคิดในการใช้องค์ประกอบในตำแหน่งที่ 1 เป็นค่ายาม ถ้าฉันสามารถให้คำแนะนำเล็ก ๆ น้อย ๆ ได้ก็จะต้องเปลี่ยนขั้นตอนที่ 2 เพื่อรวม "แต่ละองค์ประกอบอยู่ในตำแหน่งที่สอดคล้องกับโมดูโลขนาดอาร์เรย์ของแฮช" และอาจชี้แจงว่ารายการที่ซ้ำกันที่จะตั้งค่าเป็นทหารรักษาการณ์คือ องค์ประกอบที่มีค่าเท่ากัน (ตรงข้ามกับแฮชเดียวกันหรือขนาดอาร์เรย์แฮชโมดูโลเดียวกัน)
j_random_hacker

20

อีกหนึ่งการใช้งานที่มีประสิทธิภาพมากขึ้น

int i, j;

/* new length of modified array */
int NewLength = 1;

for(i=1; i< Length; i++){

   for(j=0; j< NewLength ; j++)
   {

      if(array[i] == array[j])
      break;
   }

   /* if none of the values in index[0..j] of array is not same as array[i],
      then copy the current value to corresponding new position in array */

  if (j==NewLength )
      array[NewLength++] = array[i];
}

ในการนำไปใช้งานนี้ไม่จำเป็นต้องเรียงลำดับอาร์เรย์ นอกจากนี้หากพบองค์ประกอบที่ซ้ำกันก็ไม่จำเป็นต้องเลื่อนองค์ประกอบทั้งหมดหลังจากนี้ไปทีละตำแหน่ง

ผลลัพธ์ของรหัสนี้คือ array [] ที่มีขนาด NewLength

ที่นี่เรากำลังเริ่มต้นจากองค์ประกอบที่ 2 ในอาร์เรย์และเปรียบเทียบกับองค์ประกอบทั้งหมดในอาร์เรย์จนถึงอาร์เรย์นี้ เราถือตัวแปรดัชนีพิเศษ 'NewLength' สำหรับการแก้ไขอาร์เรย์อินพุต NewLength ตัวแปรเริ่มต้นเป็น 0

องค์ประกอบในอาร์เรย์ [1] จะถูกเปรียบเทียบกับอาร์เรย์ [0] หากต่างกันค่าในอาร์เรย์ [NewLength] จะถูกแก้ไขด้วยอาร์เรย์ [1] และเพิ่มค่า NewLength หากเหมือนกัน NewLength จะไม่ถูกแก้ไข

ดังนั้นถ้าเรามีอาร์เรย์ [1 2 1 3 1] แล้ว

ใน First pass ของลูป 'j' อาร์เรย์ [1] (2) จะถูกเปรียบเทียบกับ array0 จากนั้น 2 จะถูกเขียนลงในอาร์เรย์ [NewLength] = array [1] ดังนั้นอาร์เรย์จะเป็น [1 2] เนื่องจาก NewLength = 2

ในรอบที่สองของลูป 'j' อาร์เรย์ [2] (1) จะถูกเปรียบเทียบกับ array0 และ array1 ที่นี่เนื่องจาก array [2] (1) และ array0 เป็นลูปเดียวกันจะแตกที่นี่ ดังนั้นอาร์เรย์จะเป็น [1 2] ตั้งแต่ NewLength = 2

และอื่น ๆ


3
ทำได้ดีนี่. ฉันมีข้อเสนอแนะในการปรับปรุง ลูปที่ซ้อนกันที่สองสามารถเปลี่ยนเป็นสำหรับ (j = 0; j <NewLength; j ++) และสุดท้ายหากการตรวจสอบสามารถเปลี่ยนเป็น if (j == NewLength)
Vadakkumpadath

นั่นเป็นความสุขที่ยอดเยี่ยม ฉันได้อัปเดตรหัสตามความคิดเห็นของคุณ
Byju

ล้มเหลวอย่างน้อยถ้าเรามีค่าเดียวกันในอาร์เรย์ {1,1,1,1,1,1} รหัสไร้ประโยชน์
Yuriy Chernyshov

อะไรคือความซับซ้อนของสิ่งนี้มันไม่ใช่ O (n ^ 2) ด้วยหรือ?
JavaSa

1
การโหวตเพิ่มจำนวนมาก แต่ก็ไม่ได้ผล: เป็น O (n ^ 2) เมื่อมีรายการที่ซ้ำกันน้อย
Paul Hankin

19

หากคุณกำลังมองหาสัญกรณ์ O ที่เหนือกว่าให้จัดเรียงอาร์เรย์ด้วย O (n log n) การเรียงลำดับการส่งผ่าน O (n) อาจเป็นเส้นทางที่ดีที่สุด โดยไม่ต้องเรียงลำดับคุณกำลังดู O (n ^ 2)

แก้ไข: ถ้าคุณกำลังทำเลขจำนวนเต็มคุณยังสามารถเรียงลำดับเลขเพื่อรับ O (n)


คำตอบของ Jeff B คือ O (n) เท่านั้น ชุดแฮชและพจนานุกรมแฮชคือหัวเข่าของผึ้ง
ChrisW

3
ChrisW: ชุดแฮช / พจนานุกรมเป็นเพียง O (1) หากคุณถือว่าไม่มีการชนกัน (ฉันไม่ได้บอกว่าฉันจะไม่ใช้มันสำหรับปัญหานี้ - ฉันอาจจะ - เป็นเพียงความเข้าใจผิดที่อ้างว่าพวกเขาเป็น O (1) อย่างแท้จริง)
Laurence Gonsalves

2
อันที่จริงเนื่องจากคุณทราบขนาดของอาร์เรย์ล่วงหน้าคุณจึงสามารถรับประกัน O (1) ได้ จากนั้นคุณสามารถแลกเปลี่ยนการชนเทียบกับจำนวนหน่วยความจำเพิ่มเติมที่คุณใช้
Vitali

คุณอาจต้องการคิดใหม่ว่าการลงคะแนน - เงื่อนไขที่โพสต์ใหม่สำหรับปัญหาทำให้โซลูชันของ Jeff B ไม่ถูกต้อง
Mark Ransom

3
คุณอาจต้องการอธิบายรายละเอียดเกี่ยวกับ "traversal" เนื่องจากวิธีการลบที่ไร้เดียงสาอาจส่งผลให้ O (n ^ 2) สำหรับรายการที่ซ้ำกันจำนวนมาก
Mark Ransom

11

1. ใช้ O (1) พื้นที่พิเศษในเวลา O (n log n)

สิ่งนี้เป็นไปได้เช่น:

  • ขั้นแรกให้ทำการเรียงลำดับ O (n log n) ในสถานที่
  • จากนั้นเดินดูรายการหนึ่งครั้งโดยเขียนอินสแตนซ์แรกของทุกหลังไปที่จุดเริ่มต้นของรายการ

ฉันเชื่อว่าพันธมิตรของ ejel ถูกต้องว่าวิธีที่ดีที่สุดในการทำเช่นนี้คือการจัดเรียงการผสานแบบแทนที่ด้วยขั้นตอนการผสานที่เรียบง่ายและนั่นอาจเป็นจุดประสงค์ของคำถามหากคุณเป็นเช่น การเขียนฟังก์ชันไลบรารีใหม่เพื่อทำสิ่งนี้ให้มีประสิทธิภาพมากที่สุดโดยไม่มีความสามารถในการปรับปรุงอินพุตและมีบางกรณีที่จะมีประโยชน์หากไม่มีตารางแฮชทั้งนี้ขึ้นอยู่กับประเภทของอินพุต แต่ฉันยังไม่ได้ตรวจสอบสิ่งนี้จริงๆ

2. ใช้ O (จำนวนมาก) พื้นที่พิเศษในเวลา O (n)

  • ประกาศอาร์เรย์ศูนย์ที่ใหญ่พอที่จะเก็บจำนวนเต็มทั้งหมด
  • เดินผ่านอาร์เรย์หนึ่งครั้ง
  • ตั้งค่าองค์ประกอบอาร์เรย์ที่สอดคล้องกันเป็น 1 สำหรับแต่ละจำนวนเต็ม
  • หากเป็น 1 อยู่แล้วให้ข้ามจำนวนเต็มนั้น

สิ่งนี้ใช้ได้เฉพาะเมื่อมีข้อสันนิษฐานที่น่าสงสัยหลายประการ:

  • เป็นไปได้ที่จะเป็นศูนย์หน่วยความจำราคาถูกหรือขนาดของ ints มีขนาดเล็กเมื่อเทียบกับจำนวนของหน่วยความจำ
  • คุณยินดีที่จะขอ OS ของคุณสำหรับหน่วยความจำ 256 ^ sizepof (int)
  • และมันจะแคชให้คุณได้อย่างมีประสิทธิภาพจริงๆถ้ามันใหญ่โต

เป็นคำตอบที่ไม่ดี แต่ถ้าคุณมีองค์ประกอบอินพุตจำนวนมาก แต่เป็นจำนวนเต็ม 8 บิตทั้งหมด (หรืออาจเป็นจำนวนเต็ม 16 บิต) อาจเป็นวิธีที่ดีที่สุด

3. พื้นที่พิเศษ O (เล็กน้อย), O (n) -ish time

เป็น # 2 แต่ใช้ตารางแฮช

4. วิธีที่ชัดเจน

หากองค์ประกอบมีจำนวนน้อยการเขียนอัลกอริทึมที่เหมาะสมจะไม่มีประโยชน์หากโค้ดอื่นเขียนได้เร็วกว่าและอ่านเร็วกว่า

เช่น. เดินผ่านอาร์เรย์สำหรับแต่ละองค์ประกอบที่ไม่ซ้ำกัน (เช่นองค์ประกอบแรกองค์ประกอบที่สอง (รายการที่ซ้ำกันขององค์ประกอบแรกที่ถูกลบออก) ฯลฯ ) ลบองค์ประกอบที่เหมือนกันทั้งหมด O (1) เว้นวรรคพิเศษ O (n ^ 2) เวลา

เช่น. ใช้ฟังก์ชันไลบรารีที่ทำสิ่งนี้ ประสิทธิภาพขึ้นอยู่กับสิ่งที่คุณสามารถใช้ได้อย่างง่ายดาย


7

การใช้งานขั้นพื้นฐานนั้นค่อนข้างง่าย ดูองค์ประกอบทั้งหมดตรวจสอบว่ามีรายการที่ซ้ำกันในองค์ประกอบที่เหลืออยู่หรือไม่และเลื่อนส่วนที่เหลือไป

มันไม่มีประสิทธิภาพมากและคุณสามารถเร่งความเร็วได้โดยใช้อาร์เรย์ตัวช่วยสำหรับเอาต์พุตหรือการเรียงลำดับ / ต้นไม้ไบนารี แต่ดูเหมือนจะไม่ได้รับอนุญาต


1
OTOH รหัสเพิ่มเติมที่จำเป็นในการติดตั้งแผนผังการจัดเรียงอาจมีประสิทธิภาพ (หน่วยความจำ) น้อยกว่าโซลูชันแบบง่ายและอาจมีประสิทธิภาพน้อยกว่าในขณะรันสำหรับอาร์เรย์ขนาดเล็ก (พูดน้อยกว่า 100 องค์ประกอบ)
TMN

6

หากคุณได้รับอนุญาตให้ใช้ C ++ การโทรstd::sortตามด้วยการโทรถึงstd::uniqueจะให้คำตอบ ความซับซ้อนของเวลาคือ O (N log N) สำหรับการเรียงลำดับและ O (N) สำหรับการข้ามผ่านที่ไม่ซ้ำกัน

และถ้า C ++ อยู่นอกตารางจะไม่มีสิ่งใดที่ป้องกันไม่ให้อัลกอริทึมเดียวกันนี้ถูกเขียนด้วย C


"ข้อแม้ประการหนึ่งคืออัลกอริทึมที่คาดไว้ไม่ควรกำหนดให้เรียงลำดับอาร์เรย์ก่อน"
sbi

2
ไม่ได้บอกว่าคุณไม่สามารถจัดเรียงอาร์เรย์ได้เมื่อคุณได้รับมัน ... หากไม่มีการจัดเรียงหน่วยความจำภายนอก O (N) เป็นวิธีเดียวที่จะทำได้ใน O (N log N) หรือดีกว่า
Greg Rogers

เพื่อจุดประสงค์ของปัญหาไม่ควรใช้ยูทิลิตี้ไลบรารีมาตรฐาน อย่างไรก็ตามเกี่ยวกับการเรียงลำดับยิ่งฉันคิดก็ยิ่งไม่แน่ใจว่าตกลงหรือไม่
ejel

1
ฉันคิดว่าคำตอบที่อ้างถึงฟังก์ชันมาตรฐาน C ++ และ C ++ นั้นมีประโยชน์แม้ว่าจะไม่ได้ตอบคำถามเดิมก็ตามเนื่องจากคำตอบเหล่านี้ให้คำตอบที่กลมกว่าสำหรับผู้ที่พบคำถามนี้ในภายหลัง
Douglas Leeder

6

คุณสามารถทำได้ในการส่งผ่านเพียงครั้งเดียวถ้าคุณเต็มใจที่จะเสียสละความทรงจำ คุณสามารถนับได้ว่าคุณเห็นจำนวนเต็มหรือไม่ในอาร์เรย์แฮช / การเชื่อมโยง หากคุณเห็นตัวเลขแล้วให้ลบออกทันทีหรือดีกว่านั้นย้ายตัวเลขที่คุณไม่เคยเห็นไปยังอาร์เรย์ใหม่เพื่อหลีกเลี่ยงการขยับในอาร์เรย์เดิม

ใน Perl:

foreach $i (@myary) {
    if(!defined $seen{$i}) {
        $seen{$i} = 1;
        push @newary, $i;
    }
}

ไม่ชัดเจนว่าคำตอบต้องอยู่ในอาร์เรย์เดิมหรือไม่
Douglas Leeder

ในการดำเนินการนี้โดยไม่ต้องใช้อาร์เรย์ใหม่คุณสามารถแทนที่รายการที่ซ้ำกันด้วยองค์ประกอบที่โผล่ออกมาจากส่วนท้ายของอาร์เรย์และทำซ้ำลูปปัจจุบันเนื่องจากปัญหาไม่ได้ระบุว่าคำสั่งนั้นสำคัญ สิ่งนี้ต้องมีการตรวจสอบขอบเขตเพิ่มเติม แต่ทำได้มาก
Jeff B

6
นี่เป็นความคิดที่ดีจนกว่าคำถามจะได้รับการแก้ไข เห็นได้ชัดว่าความคิดแฮชแท็กของคุณขัดต่อกฎ
WCWedin

14
ฉันไม่เข้าใจว่าทำไมคำตอบนี้ถึงได้รับการโหวตมากที่สุด มันเขียนด้วยภาษา perl และใช้คุณสมบัติที่สำคัญที่ไม่มีใน C ตามที่คำถามถาม
LiraNuna

5
คำถามที่ถามสำหรับรหัส c ไม่ใช่ perl การใช้ perl จะทำให้คุณได้รับแฮชแท็กและ "push" ฟรี ถ้าฉันทำได้ในสกาลาคุณก็จะเรียก input.removeDuplicates แต่ฉันสงสัยว่าผู้สัมภาษณ์จะยอมรับได้ :)
Peter Recore

5

ค่าที่ส่งคืนของฟังก์ชันควรเป็นจำนวนขององค์ประกอบที่ไม่ซ้ำกันและทั้งหมดจะถูกเก็บไว้ที่ด้านหน้าของอาร์เรย์ หากไม่มีข้อมูลเพิ่มเติมนี้คุณจะไม่รู้ด้วยซ้ำว่ามีรายการที่ซ้ำกันหรือไม่

การวนซ้ำของวงนอกแต่ละครั้งจะประมวลผลองค์ประกอบหนึ่งของอาร์เรย์ หากไม่ซ้ำกันก็จะอยู่ด้านหน้าอาร์เรย์และหากซ้ำกันจะถูกเขียนทับโดยองค์ประกอบสุดท้ายที่ยังไม่ได้ประมวลผลในอาร์เรย์ โซลูชันนี้ทำงานในเวลา O (n ^ 2)

#include <stdio.h>
#include <stdlib.h>

size_t rmdup(int *arr, size_t len)
{
  size_t prev = 0;
  size_t curr = 1;
  size_t last = len - 1;
  while (curr <= last) {
    for (prev = 0; prev < curr && arr[curr] != arr[prev]; ++prev);
    if (prev == curr) {
      ++curr;
    } else {
      arr[curr] = arr[last];
      --last;
    }
  }
  return curr;
}

void print_array(int *arr, size_t len)
{
  printf("{");
  size_t curr = 0;
  for (curr = 0; curr < len; ++curr) {
    if (curr > 0) printf(", ");
    printf("%d", arr[curr]);
  }
  printf("}");
}

int main()
{
  int arr[] = {4, 8, 4, 1, 1, 2, 9};
  printf("Before: ");
  size_t len = sizeof (arr) / sizeof (arr[0]);
  print_array(arr, len);
  len = rmdup(arr, len);
  printf("\nAfter: ");
  print_array(arr, len);
  printf("\n");
  return 0;
}

4

นี่คือเวอร์ชัน Java

int[] removeDuplicate(int[] input){

        int arrayLen = input.length;
        for(int i=0;i<arrayLen;i++){
            for(int j = i+1; j< arrayLen ; j++){
                if(((input[i]^input[j]) == 0)){
                    input[j] = 0;
                }
                if((input[j]==0) && j<arrayLen-1){
                        input[j] = input[j+1];
                        input[j+1] = 0;
                    }               
            }
        }       
        return input;       
    }

ล้มเหลวอย่างน้อยกับอินพุตถัดไป: {1,1,1,1,1,1,1} {0,0,0,0,0,1,1,1,1,1,1}
Yuriy Chernyshov

3

นี่คือทางออกของฉัน

///// find duplicates in an array and remove them

void unique(int* input, int n)
{
     merge_sort(input, 0, n) ;

     int prev = 0  ;

     for(int i = 1 ; i < n ; i++)
     {
          if(input[i] != input[prev])
               if(prev < i-1)
                   input[prev++] = input[i] ;                         
     }
}

2

เห็นได้ชัดว่าอาร์เรย์ควร "ข้าม" จากขวาไปซ้ายเพื่อหลีกเลี่ยงการคัดลอกค่าไปมาโดยไม่จำเป็น

หากคุณมีหน่วยความจำไม่ จำกัด คุณสามารถจัดสรรอาร์เรย์บิตสำหรับsizeof(type-of-element-in-array) / 8ไบต์เพื่อให้แต่ละบิตแสดงว่าคุณพบค่าที่ตรงกันแล้วหรือไม่

ถ้าคุณไม่ทำฉันคิดว่าไม่มีอะไรดีไปกว่าการข้ามอาร์เรย์และเปรียบเทียบแต่ละค่ากับค่าที่ตามมาจากนั้นหากพบว่าซ้ำกันให้ลบค่าเหล่านี้ออกทั้งหมด นี่คือที่ไหนสักแห่งใกล้O (n ^ 2) (หรือO ((n ^ 2-n) / 2) )

IBM มีบทความเกี่ยวกับเรื่องใกล้ตัว


อันที่จริง - O (n) ผ่านเพื่อค้นหาองค์ประกอบที่ใหญ่ที่สุดจะไม่เพิ่มต้นทุน O () โดยรวม
Douglas Leeder

2

มาดูกัน:

  • O (N) ส่งผ่านเพื่อค้นหาการจัดสรร min / max
  • บิตอาร์เรย์สำหรับพบ
  • O (N) ส่งผ่านการแลกเปลี่ยนซ้ำเพื่อสิ้นสุด

เนื่องจากเป็นจำนวนเต็มเท่านั้นเพื่อความง่ายคุณสามารถสมมติว่าเป็น 32 บิตและไม่ต้องกังวลกับการค้นหา min / max: 2 ^ 32 บิตคือ 512MB "เท่านั้น" ดังนั้นการค้นหาขอบเขตจึงเป็นเพียงการใช้หน่วยความจำและการเพิ่มประสิทธิภาพ O (1) เวลา (ได้รับการปรับให้เหมาะสมอย่างหนักในกรณีของตัวอย่างที่กำหนด) และถ้าเป็น 64 บิตก็ไม่เกี่ยวข้องเนื่องจากคุณไม่รู้ว่าค่าต่ำสุดและสูงสุดจะไม่ห่างกันเกินกว่าจำนวนบิตของหน่วยความจำที่คุณมี
Steve Jessop

นอกเหนือจากทฤษฎีแล้วการจัดสรร 512MB จะใช้เวลามากกว่าการค้นหา min / max ไม่ใช่หรือ
LiraNuna

ขึ้นอยู่กับจำนวนข้อมูลและค่าต่ำสุด / สูงสุดคือเท่าใด หากคุณกำลังดูอินพุตมากกว่า 512MB อาจเป็นไปได้ว่าจะเร็วกว่าที่จะหลีกเลี่ยงการส่งผ่าน O (N) พิเศษนั้น แน่นอนว่าหากคุณกำลังมองหาอินพุตจำนวนมากนั่นก็เป็นไปได้น้อยที่คุณจะมี 512MB ในการสำรองข้อมูล ในกรณีที่ค่าต่ำสุด / สูงสุดใกล้ 0 / INT_MAX การเพิ่มประสิทธิภาพจะไม่ช่วยเช่นกัน ฉันแค่บอกว่าแม้ว่าขั้นตอนแรกจะช่วยได้อย่างชัดเจน แต่ก็ไม่สามารถหลีกเลี่ยงความจริงที่ว่าอัลกอริทึมนี้ใช้บิต UINT_MAX ในกรณีที่เลวร้ายที่สุดดังนั้นคุณต้องวางแผนสำหรับข้อ จำกัด นั้น
Steve Jessop

คุณอาจจะพูดถูก - ไม่ว่าในกรณีใดก็ตามการชี้แจงคำถามหมายความว่าการใช้บิตอาร์เรย์จะไม่ทำงาน ฉันจะปล่อยให้คำตอบนี้ในกรณีที่มีคนมาพบในภายหลังโดยไม่มีข้อ จำกัด และต้องการดูคำตอบที่เป็นไปได้ทั้งหมด
Douglas Leeder

2

ซึ่งสามารถทำได้ในครั้งเดียวโดยใช้อัลกอริทึม O (N log N) และไม่มีพื้นที่เก็บข้อมูลเพิ่มเติม

ดำเนินการต่อจากองค์ประกอบที่จะa[1] a[N]ในแต่ละขั้นตอนiทุกองค์ประกอบไปทางซ้ายของa[i]ประกอบด้วยเรียงกองขององค์ประกอบผ่านa[0] a[j]ในขณะเดียวกันดัชนีที่สองjซึ่งเริ่มต้นเป็น 0 จะติดตามขนาดของฮีป

ตรวจสอบa[i]และใส่ลงในกองซึ่งขณะนี้อยู่องค์ประกอบที่จะa[0] a[j+1]ในขณะที่แทรกองค์ประกอบหากa[k]พบว่าองค์ประกอบที่ซ้ำกันมีค่าเท่ากันอย่าใส่a[i]เข้าไปในฮีป (กล่าวคือทิ้ง) มิฉะนั้นจะใส่ลงในกองซึ่งขณะนี้เติบโตขึ้นโดยองค์ประกอบหนึ่งและตอนนี้ประกอบด้วยa[0]การและเพิ่มขึ้นa[j+1]j

ดำเนินการต่อในลักษณะนี้ที่เพิ่มขึ้นiจนทุกองค์ประกอบมากมายที่ได้รับการตรวจสอบและแทรกเข้าไปในกองซึ่งสิ้นสุดครอบครองเพื่อa[0] คือดัชนีขององค์ประกอบสุดท้ายของฮีปและฮีปมีเฉพาะค่าองค์ประกอบที่ไม่ซ้ำกันa[j]j

int algorithm(int[] a, int n)
{
    int   i, j;  

    for (j = 0, i = 1;  i < n;  i++)
    {
        // Insert a[i] into the heap a[0...j]
        if (heapInsert(a, j, a[i]))
            j++;
    }
    return j;
}  

bool heapInsert(a[], int n, int val)
{
    // Insert val into heap a[0...n]
    ...code omitted for brevity...
    if (duplicate element a[k] == val)
        return false;
    a[k] = val;
    return true;
}

เมื่อดูตัวอย่างนี่ไม่ใช่สิ่งที่ถูกถามอย่างแน่นอนเนื่องจากอาร์เรย์ผลลัพธ์จะรักษาลำดับองค์ประกอบดั้งเดิม แต่ถ้าข้อกำหนดนี้ผ่อนคลายอัลกอริทึมข้างต้นควรทำเคล็ดลับ


1

ใน Java ฉันจะแก้แบบนี้ ไม่รู้จะเขียนในค. นี้ยังไง

   int length = array.length;
   for (int i = 0; i < length; i++) 
   {
      for (int j = i + 1; j < length; j++) 
      {
         if (array[i] == array[j]) 
         {
            int k, j;
            for (k = j + 1, l = j; k < length; k++, l++) 
            {
               if (array[k] != array[i]) 
               {
                  array[l] = array[k];
               }
               else
               {
                  l--;
               }
            }
            length = l;
         }
      }
   }

หากคุณเขียนทับรายการที่ซ้ำกันที่คุณพบด้วยค่าที่ส่วนท้ายของอาร์เรย์คุณสามารถหลีกเลี่ยงการขยับของอาร์เรย์ทั้งหมดในวงใน for () ที่จะนำคุณไปสู่ ​​O (n ^ 2) จาก O (n ^ 3) การใช้งาน C ของฉันลอยอยู่ที่นี่ที่ไหนสักแห่ง ...
mocj

ฉันคิดว่าการขยับเป็นส่วนหนึ่งของข้อกำหนด แต่คุณพูดถูก
Dominik

1
@mocj: ฉันชอบโซลูชันของคุณดูหรูหรามาก แต่ฉันคิดว่ามันไม่ได้ผลถ้าสององค์ประกอบสุดท้ายเท่ากันเพราะคุณหยุดตรวจสอบความเท่าเทียมกันก่อนสุดท้าย (มาที่นี่เพราะดูมีชื่อเสียงเกินกว่าจะแสดงความคิดเห็นที่อื่นได้ :()
โดมินิก

คุณพูดถูกยกเว้นว่าปัญหาเดิมระบุว่าค่าที่ท้ายอาร์เรย์มีค่าเล็กน้อย เนื่องจากคุณไม่ได้ส่งคืนความยาวของอาร์เรย์ที่แก้ไขความแตกต่างระหว่างค่าสุดท้ายและค่าที่สองถึงค่าสุดท้ายจึงไม่สำคัญเมื่อทั้งสองค่าเท่ากัน ผู้เรียกตีความจุดสิ้นสุดของอาร์เรย์ที่ส่งคืนไปที่ใด
mocj

1

ต่อไปนี้เป็นอย่างไร?

int* temp = malloc(sizeof(int)*len);
int count = 0;
int x =0;
int y =0;
for(x=0;x<len;x++)
{
    for(y=0;y<count;y++)
    {
        if(*(temp+y)==*(array+x))
        {
            break;
        }
    }
    if(y==count)
    {
        *(temp+count) = *(array+x);
        count++;
    }
}
memcpy(array, temp, sizeof(int)*len);

ฉันพยายามประกาศอาร์เรย์ชั่วคราวและใส่องค์ประกอบลงในนั้นก่อนที่จะคัดลอกทุกอย่างกลับไปที่อาร์เรย์เดิม


1

หลังจากตรวจสอบปัญหาแล้วนี่คือวิธีเดลฟีของฉันที่อาจช่วยได้

var
A: Array of Integer;
I,J,C,K, P: Integer;
begin
C:=10;
SetLength(A,10);
A[0]:=1; A[1]:=4; A[2]:=2; A[3]:=6; A[4]:=3; A[5]:=4;
A[6]:=3; A[7]:=4; A[8]:=2; A[9]:=5;

for I := 0 to C-1 do
begin
  for J := I+1 to C-1 do
    if A[I]=A[J] then
    begin
      for K := C-1 Downto J do
        if A[J]<>A[k] then
        begin
          P:=A[K];
          A[K]:=0;
          A[J]:=P;
          C:=K;
          break;
        end
        else
        begin
          A[K]:=0;
          C:=K;
        end;
    end;
end;

//tructate array
setlength(A,C);
end;

1

ตัวอย่างต่อไปนี้ควรแก้ปัญหาของคุณ:

def check_dump(x):
   if not x in t:
      t.append(x)
      return True

t=[]

output = filter(check_dump, input)

print(output)
True

1
import java.util.ArrayList;


public class C {

    public static void main(String[] args) {

        int arr[] = {2,5,5,5,9,11,11,23,34,34,34,45,45};

        ArrayList<Integer> arr1 = new ArrayList<Integer>();

        for(int i=0;i<arr.length-1;i++){

            if(arr[i] == arr[i+1]){
                arr[i] = 99999;
            }
        }

        for(int i=0;i<arr.length;i++){
            if(arr[i] != 99999){

                arr1.add(arr[i]);
            }
        }

        System.out.println(arr1);
}
    }

arr [i + 1] ควรโยน ArrayIndexOutOfBoundsException สำหรับองค์ประกอบสุดท้ายหรือไม่
Sathesh

@Sathesh No. เพราะ "<arr.length-1"
GabrielBB

1

นี่คือวิธีแก้ปัญหาไร้เดียงสา (N * (N-1) / 2) ใช้พื้นที่เพิ่มเติมคงที่และรักษาลำดับเดิม คล้ายกับการแก้ปัญหาโดย @Byju แต่ไม่ใช้if(){}บล็อก นอกจากนี้ยังหลีกเลี่ยงการคัดลอกองค์ประกอบลงในตัวเอง

#include <stdio.h>
#include <stdlib.h>

int numbers[] = {4, 8, 4, 1, 1, 2, 9};
#define COUNT (sizeof numbers / sizeof numbers[0])

size_t undup_it(int array[], size_t len)
{
size_t src,dst;

  /* an array of size=1 cannot contain duplicate values */
if (len <2) return len; 
  /* an array of size>1 will cannot at least one unique value */
for (src=dst=1; src < len; src++) {
        size_t cur;
        for (cur=0; cur < dst; cur++ ) {
                if (array[cur] == array[src]) break;
                }
        if (cur != dst) continue; /* found a duplicate */

                /* array[src] must be new: add it to the list of non-duplicates */
        if (dst < src) array[dst] = array[src]; /* avoid copy-to-self */
        dst++;
        }
return dst; /* number of valid alements in new array */
}

void print_it(int array[], size_t len)
{
size_t idx;

for (idx=0; idx < len; idx++)  {
        printf("%c %d", (idx) ? ',' :'{' , array[idx] );
        }
printf("}\n" );
}

int main(void) {    
    size_t cnt = COUNT;

    printf("Before undup:" );    
    print_it(numbers, cnt);    

    cnt = undup_it(numbers,cnt);

    printf("After undup:" );    
    print_it(numbers, cnt);

    return 0;
}

0

สิ่งนี้สามารถทำได้ในรอบเดียวในเวลา O (N) ในจำนวนจำนวนเต็มในรายการอินพุตและหน่วยเก็บ O (N) ในจำนวนจำนวนเต็มที่ไม่ซ้ำกัน

เดินผ่านรายการจากด้านหน้าไปด้านหลังโดยเริ่มต้นตัวชี้สองตัว "dst" และ "src" ให้กับรายการแรก เริ่มต้นด้วยตารางแฮชว่างของ "จำนวนเต็มเห็น" หากไม่มีจำนวนเต็มที่ src ในแฮชให้เขียนลงในช่องที่ dst และ Increment dst เพิ่มจำนวนเต็มที่ src ลงในแฮชจากนั้นเพิ่ม src ทำซ้ำจนกว่า src จะผ่านจุดสิ้นสุดของรายการอินพุต


2
ในการแก้ไขคำถามเดิมไม่อนุญาตให้ใช้ตารางแฮช วิธีการชี้สองตัวของคุณเป็นวิธีที่ดีในการกระชับเอาต์พุตเมื่อคุณระบุรายการที่ซ้ำกันแล้ว
Mark Ransom

0

ใส่องค์ประกอบทั้งหมดใน-binary tree the disregards duplicates O(nlog(n))แล้วดึงทั้งหมดของพวกเขากลับมาอยู่ในแถวโดยการทำข้ามผ่าน O(n)- ฉันสมมติว่าคุณไม่ต้องการการเก็บรักษาคำสั่งซื้อ


0

ใช้ตัวกรองบานในการแฮช ซึ่งจะช่วยลดค่าใช้จ่ายของหน่วยความจำลงอย่างมาก


สนใจที่จะอธิบายรายละเอียดหรือให้ข้อมูลอ้างอิง?
dldnh

0

ใน JAVA

    Integer[] arrayInteger = {1,2,3,4,3,2,4,6,7,8,9,9,10};

    String value ="";

    for(Integer i:arrayInteger)
    {
        if(!value.contains(Integer.toString(i))){
            value +=Integer.toString(i)+",";
        }

    }

    String[] arraySplitToString = value.split(",");
    Integer[] arrayIntResult = new Integer[arraySplitToString.length];
    for(int i = 0 ; i < arraySplitToString.length ; i++){
        arrayIntResult[i] = Integer.parseInt(arraySplitToString[i]);
    }

เอาต์พุต: {1, 2, 3, 4, 6, 7, 8, 9, 10}

หวังว่านี่จะช่วยได้


1
ทดสอบกับอินพุตarrayInteger = {100,10,1};
Blastfurnace


0

ขั้นแรกคุณควรสร้างอาร์เรย์check[n]โดยที่ n คือจำนวนองค์ประกอบของอาร์เรย์ที่คุณต้องการทำให้ไม่ซ้ำกันและตั้งค่าของทุกองค์ประกอบ (ของอาร์เรย์ตรวจสอบ) ให้เท่ากับ 1 โดยใช้สำหรับลูปสำรวจอาร์เรย์ด้วย ซ้ำกันพูดว่าชื่อarrและใน for-loop ให้เขียนสิ่งนี้:

{
    if (check[arr[i]] != 1) {
        arr[i] = 0;
    }
    else {
        check[arr[i]] = 0;
    }
}

ด้วยวิธีนี้คุณตั้งค่าทุกรายการที่ซ้ำกันเท่ากับศูนย์ ดังนั้นสิ่งเดียวที่ต้องทำคือสำรวจarrอาร์เรย์และพิมพ์ทุกอย่างที่ไม่เท่ากับศูนย์ คำสั่งยังคงอยู่และใช้เวลาเชิงเส้น (3 * n)


คำถามไม่อนุญาตให้ใช้โครงสร้างข้อมูลเพิ่มเติม
ejel

0

ให้อาร์เรย์ของ n องค์ประกอบเขียนอัลกอริทึมเพื่อลบรายการที่ซ้ำกันทั้งหมดออกจากอาร์เรย์ในเวลา O (nlogn)

Algorithm delete_duplicates (a[1....n])
//Remove duplicates from the given array 
//input parameters :a[1:n], an array of n elements.

{

temp[1:n]; //an array of n elements. 

temp[i]=a[i];for i=1 to n

 temp[i].value=a[i]

temp[i].key=i

 //based on 'value' sort the array temp.

//based on 'value' delete duplicate elements from temp.

//based on 'key' sort the array temp.//construct an array p using temp.

 p[i]=temp[i]value

  return p.

ในองค์ประกอบอื่น ๆ จะถูกเก็บรักษาไว้ในอาร์เรย์เอาต์พุตโดยใช้ 'คีย์' พิจารณาว่าคีย์มีความยาว O (n) เวลาที่ใช้ในการจัดเรียงคีย์และค่าคือ O (nlogn) ดังนั้นเวลาที่ใช้ในการลบรายการที่ซ้ำกันทั้งหมดจากอาร์เรย์คือ O (nlogn)


สำหรับร่ายมนตร์ตัวหนาทั้งหมดคุณทำมาจากhelper data structure (e.g. hashtable) should not be usedอะไร?
greybeard

ไม่จำเป็น ฉันแค่เน้นที่จุดประสงค์เพื่อความเข้าใจ
Sharief Muzammil

0

นี่คือสิ่งที่ฉันได้รับแม้ว่ามันจะวางลำดับผิดที่เราสามารถเรียงลำดับจากน้อยไปหามากหรือมากไปหาน้อยเพื่อแก้ไขได้

#include <stdio.h>
int main(void){
int x,n,myvar=0;
printf("Enter a number: \t");
scanf("%d",&n);
int arr[n],changedarr[n];

for(x=0;x<n;x++){
    printf("Enter a number for array[%d]: ",x);
    scanf("%d",&arr[x]);
}
printf("\nOriginal Number in an array\n");
for(x=0;x<n;x++){
    printf("%d\t",arr[x]);
}

int i=0,j=0;
// printf("i\tj\tarr\tchanged\n");

for (int i = 0; i < n; i++)
{
    // printf("%d\t%d\t%d\t%d\n",i,j,arr[i],changedarr[i] );
    for (int j = 0; j <n; j++)
    {   
        if (i==j)
        {
            continue;

        }
        else if(arr[i]==arr[j]){
            changedarr[j]=0;

        }
        else{
            changedarr[i]=arr[i];

        }
    // printf("%d\t%d\t%d\t%d\n",i,j,arr[i],changedarr[i] );
    }
    myvar+=1;
}
// printf("\n\nmyvar=%d\n",myvar);
int count=0;
printf("\nThe unique items:\n");
for (int i = 0; i < myvar; i++)
{
        if(changedarr[i]!=0){
            count+=1;
            printf("%d\t",changedarr[i]);   
        }
}
    printf("\n");
}

-1

จะดีมากถ้าคุณมี DataStructure ที่ดีที่สามารถบอกได้อย่างรวดเร็วว่ามีจำนวนเต็มหรือไม่ บางทีอาจเป็นต้นไม้บางชนิด

DataStructure elementsSeen = new DataStructure();
int elementsRemoved = 0;
for(int i=0;i<array.Length;i++){
  if(elementsSeen.Contains(array[i])
    elementsRemoved++;
  else
    array[i-elementsRemoved] = array[i];
}
array.Length = array.Length - elementsRemoved;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.