N ควีนคำถามสัมภาษณ์โดย X ใน Y


10

ฉันถูกถามคำถามต่อไปนี้ในการสัมภาษณ์วันนี้และฉันก็คิดถึงมันมานับตั้งแต่ ฉันไม่สามารถตอบได้และไม่สามารถหาวิธีแก้ปัญหาออนไลน์ได้

มอบกระดานหมากรุกที่มีขนาด X โดย Y และ N ให้พิจารณาว่าเป็นไปได้หรือไม่ที่จะจัดเรียงราชินีเหล่านี้บนกระดานเพื่อให้พวกเขาไม่สามารถโจมตีซึ่งกันและกันได้

บอร์ด 2 x 3 ที่มี 2 ควีนส์มีทางออกดังนั้นอัลกอริทึมจะกลับมาเป็นจริง:

Q . .
. . Q

ฉันกำลังมองหาวิธีการเขียนโปรแกรมสำหรับปริศนานี้ไม่ใช่แค่วิธีแก้ปัญหาบนกระดาษเช่น


การค้นหาครั้งแรกที่ดีที่สุดเป็นตัวเลือกอย่างแน่นอนเช่นเดียวกับการวิเคราะห์พฤติกรรมการค้นหาอื่น ๆ
เจสัน

2
เสนอชื่อเข้าชิงหนึ่งในคำถามสัมภาษณ์ที่เลวร้ายที่สุด - เว้นแต่ซอฟต์แวร์ที่พวกเขาทำงานนั้นต้องอาศัยโซลูชันย้อนรอยซึ่งในกรณีนี้เกี่ยวข้องกันโดยสิ้นเชิง
Steven A. Lowe

1
เพื่อความยุติธรรมผู้สัมภาษณ์กล่าวว่านี่เป็นเพียงเครดิตชนิดพิเศษ ส่วนที่เหลือของการสัมภาษณ์เป็น IMO ที่ค่อนข้างถูกกฎหมาย ผมก็แค่อยากรู้.
ให้สัมภาษณ์

อาจเป็นการทดสอบว่าเขาจะจำลองสถานการณ์ด้วยการย้อนรอยหรือ (คิดเกี่ยวกับการหา) วิธีแก้ปัญหา O (1) โดยใช้ข้อเท็จจริงที่ Caleb ระบุไว้ในคำตอบของเขา ความสามารถในการเขียนโปรแกรมสิ่งง่าย ๆ ไม่ใช่ทุกสิ่งที่เราต้องการในงาน
Sopel

การบ้านได้รับมอบหมายอย่างชัดเจนนอกขอบเขตที่นี่
jwenting

คำตอบ:


16

นี่ไม่ใช่ (IMO) ปัญหาที่น่าสนใจมากจากมุมมองการเขียนโปรแกรม คุณสามารถคิดอัลกอริทึมแบบเรียกซ้ำได้ซึ่งจะลองทุกการจัดเรียงดังนี้:

bool try_queens(Board board, int n)
{
    if (n == 0) {
        // no queens left to place, so we're done
        return true
    }
    // try each open position until we find one that works
    for each position on the board {
        if (is_empty(board, position) and not is_attacked(board, position)) {
            place_queen(board, position)
            if (try_queens(board, n-1)) {
                return true
            }
            remove_queen(board, position)
        }
    }
    // if we get this far, there's no available position
    return false
}

main()
{
    initialize board(X,Y)
    return try_queens(board, N)
}

หากคุณคิดถึงปัญหาเล็กน้อยคุณจะรู้ว่าไม่มีทางที่จะพอดีกับราชินีควีนส์ในกระดานที่ X <N หรือ Y <N เพราะนั่นจะต้องมีอย่างน้อยสองราชินีจบลงในอันดับเดียวกันหรือไฟล์เดียวกัน และพวกเขาก็จะโจมตีซึ่งกันและกัน หากคุณอ่านเกี่ยวกับปัญหาของ n-queens คุณจะได้เรียนรู้อย่างรวดเร็วว่าเป็นไปได้ที่จะวาง N queens บนกระดาน NxN สำหรับ N> 3 ตอนนี้เรารู้แล้วว่าคำตอบนั้นไม่ใช่สำหรับ (X <N หรือ Y <N) และ YES สำหรับ (X> = N และ Y> = N, N> 3) สิ่งที่เหลืออยู่เป็นกรณีพิเศษ:

  • N = 1 (ใช่)
  • N = 2 (YES สำหรับ X> = 2 และ Y> 2 หรือในทางกลับกัน)
  • N = 3 (YES สำหรับ X> = 3 และ Y> 3 หรือในทางกลับกัน)

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

(และเด็กชายโอ้เด็กฉันหวังว่าฉันจะไม่ทำผิดพลาดโง่ ๆ ในคำตอบที่ชาญฉลาดของฉันกางเกง ;-)


That's great from a performance point of view, since you can get an answer in constant time. It's not so great from a programming point of view because you realize, at this point, that the question is really more about how well you can solve puzzles than it is about your ability to write a recursive function.ฉันคิดว่าผู้สัมภาษณ์กำลังรอการแก้ปัญหา O (1) เพราะในท้ายที่สุดมันดีกว่าและไม่ชัดเจนสำหรับหลาย ๆ คน ปัญหาของ nxn queen นั้นอยู่ในหลักสูตรการเขียนโปรแกรมทั้งหมดซึ่งเป็นเครื่องออกกำลังกายสำหรับการเรียกซ้ำ - หลาย ๆ คนจะไม่คิดลึกลงไปเมื่อเห็นปัญหานั้นอีกครั้ง
Sopel

4

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

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

http://en.wikipedia.org/wiki/Eight_queens_puzzle

รหัสสามารถพบได้ที่นี่: http://www.codeproject.com/KB/java/EightQueen.aspx

อย่ารู้สึกแย่เกี่ยวกับเรื่องนี้อย่างที่ฉันบอกไปมันไม่ใช่เรื่องง่าย


0

นี่เป็นความคิดเห็นที่มากขึ้นจริง ๆ แต่มันไม่พอดีกับที่นั่น ...

กระดานหมากรุกมีสี่เหลี่ยมขนาด 8x8 ไม่มากไม่น้อย (คำถามเหล่านี้ทำให้ฉันรำคาญกับวิธีการของกระดานหมากรุกที่กำหนดเอง)

แต่อย่างไรก็ตามถ้าคุณมีกระดานหมากรุก x * y และ n ควีนและรับว่าราชินี "รับ" สาขาเหล่านี้

ป้อนคำอธิบายรูปภาพที่นี่

คุณสามารถสร้างอาเรย์สองมิติและ "ตั้งค่าสถานะ" ฟิลด์ทั้งหมดที่ราชินีหนึ่งโจมตีได้หรือไม่ จากนั้นวางอีกอันหนึ่ง (จากกึ่งกลางกระดาน) ตั้งค่าสถานะฟิลด์ที่เหลือและอื่น ๆ ... จนกว่าคุณจะเรียกใช้ฟิลด์หรือราชินีใดก็ได้

แน่นอนว่านี่เป็นวิธีการที่ง่ายมากเนื่องจากหากตำแหน่งในลักษณะที่ไม่ดีฉันรวบรวมจำนวนสูงสุดของราชินีจะแตกต่างกันไป

อืมเพิ่งพบสิ่งนี้เช่นกัน - ปัญหา 8 ควีนส์


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

@Interviewee - ใช่ฉันรู้ นี่เป็นเพียงสิ่งที่ฉันคิดว่าปิดหัวของฉัน ดังที่กล่าวไว้มันเป็นปัญหาที่น่าสนใจและน่าจะดีขึ้น แต่ใน 04:00 (ที่นี่) ฉันขี้เกียจเกินกว่าจะคิด Btw การสัมภาษณ์ไปได้อย่างไร
โกง

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

ฉันชอบรูปประจำตัวของคุณที่เป็นชิ้นหมากรุก :)
วอร์เรน

0

โดยทั่วไปอัลกอริทึมย้อนรอยทำงานเช่นนี้

  1. สร้างอาร์เรย์ X โดย Y ตั้งค่าสี่เหลี่ยมทั้งหมดให้ว่างเปล่า

  2. ตั้งค่าการนับราชินีเป็นศูนย์

  3. ตั้งตำแหน่งปัจจุบันของคุณเป็น (1,1)

  4. ดูว่าคุณสามารถวางราชินีในตำแหน่งปัจจุบันได้หรือไม่

  5. หากทำได้ให้ตั้งค่า Array (X, Y) เป็น queen เพิ่มจำนวนของราชินี หากคุณวางราชินีทั้งหมดหยุดคุณมีทางออก

  6. ถ้าตำแหน่งปัจจุบันไม่ (X, Y) เพิ่มตำแหน่งปัจจุบันและไปที่ขั้นตอนที่ 4

  7. ค้นหาราชินีในตำแหน่งสุดท้าย (ลำดับที่สุดท้ายตามลำดับที่คุณเพิ่มตำแหน่ง) ตั้งค่าตำแหน่งปัจจุบันเป็นตำแหน่งของราชินีนั้นลบออกและลดจำนวนควีน

  8. หากการนับราชินีเป็นศูนย์หยุดไม่มีวิธีแก้ปัญหา

  9. เพิ่มตำแหน่งปัจจุบัน

  10. ไปที่ขั้นตอนที่ 4


ในคำอธิบายนี้อัลกอริทึมไม่ย้อนกลับอย่างถูกต้อง: จะลบราชินีที่วางตำแหน่งสุดท้ายเท่านั้น คุณมีความเสี่ยงที่จะไม่ลองราชินีก่อนหน้านี้ในตำแหน่งอื่น
Kasper van den Berg

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

0

การเพิ่มคำตอบอื่น ๆ : การสร้างอาร์เรย์สองมิติจะทำให้โค้ดซับซ้อนเท่านั้น

คุณแค่ต้องการเวกเตอร์ขนาด 8 สำหรับกระดานหมากรุกทั่วไป หรือ 8 + 1 ถ้าชอบตำแหน่งที่ 1 C คือ 0 เพียงเพื่อลดความซับซ้อนของรหัสและจัดการกับ 1-8 และไม่ใช่ 0-7

หากคุณคิดว่า x เป็นตำแหน่งของคุณในอาร์เรย์และ y เป็นเนื้อหาของตำแหน่ง เช่น board [1] = 8 หมายถึงราชินีคนแรกอยู่ที่ [1,8]

ด้วยวิธีนี้คุณจะต้องตรวจสอบความถูกต้องของคอลัมน์

ในช่วงเวลาที่ฉันเรียนหนังสือเล่มเก่า (60s) เกี่ยวกับอัลกอริทึมที่ใช้ในดาร์ทเมาท์เบสิคที่ใช้ปัญหา 8 ราชินีโดยใช้หน่วยความจำน้อยที่สุดเท่าที่จะเป็นไปได้

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

น่าเศร้าที่ฉันลืมหนังสือเล่มนั้น ...

อัลกอริทึมดังกล่าวพบวิธีแก้ปัญหาทั้งหมดสำหรับปัญหาราชินี


0

หากคุณเพียงแค่ต้องมีการเขียนขั้นตอนวิธีการตรวจสอบว่าวิธีการดังกล่าวมีอยู่แล้วมองไปที่การวิจัยที่มีอยู่: ปริศนาแปดราชินีวิกิพีเดีย

คุณสามารถคืนค่าเท็จได้ถ้า N> min (X, Y)
หลังจากอ่านหน้านั้นแล้วคุณจะรู้ว่าคืนจริงถ้า N <= min (X, Y) และ 2, 3! = min (X, Y)

ซึ่งเหลือ 2, 3 == นาที (X, Y) และ N <= นาที (X, Y)

ถ้า N <min (X, Y) การหาคำตอบนั้นไม่สำคัญ
ถ้า N == ขั้นต่ำ (X, Y) มีวิธีแก้ปัญหาเฉพาะถ้า max (X, Y)> N

f(X, Y, N)
    if X < Y => f(Y, X, N)
    if Y > N => false
    => (Y < N) or (Y != 2 and Y != 3) or (X > N)

0

เห็นได้ชัดว่าไม่มีวิธีแก้ปัญหาถ้า N> min (X, Y) มิฉะนั้นคุณสามารถแสดงได้อย่างง่ายดายว่าไม่มีวิธีแก้ปัญหาสำหรับ N = X = Y = 2, N = X = Y = 3 สำหรับกรณีอื่น ๆ ทั้งหมดดูเหมือนจะเป็นวิธีแก้ปัญหา จำนวนโซลูชั่นดูเหมือนจะเพิ่มขึ้นเมื่อ N เติบโตขึ้น

คุณสามารถหาวิธีการแก้ปัญหาผ่านการค้นหาอย่างละเอียดด้วยการย้อนรอย: ใส่ราชินีในแถวแรกคอลัมน์ 1 ใส่ราชินีในแถวที่สองในคอลัมน์แรกที่ราชินีในแถว 1 ไม่สามารถเข้าถึงได้ วางราชินีในแถวที่สองเป็นต้นหากราชินีไม่สามารถใส่เข้าไปในแถว k ได้ดังนั้นคุณจึงลบมันและย้ายราชินีในแถว k-1 ในตำแหน่งว่างถัดไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.