JavaRush /จาวาบล็อก /Random-TH /เรื่องราวของการสัมภาษณ์ครั้งหนึ่ง: คำถามที่น่าสนใจ
GuitarFactor
ระดับ
Санкт-Петербург

เรื่องราวของการสัมภาษณ์ครั้งหนึ่ง: คำถามที่น่าสนใจ

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

ร่าง 1. “วิธีการที่ดูเรียบง่าย”

เขียนว่าคุณจะใช้วิธีการส่งคืนผลลัพธ์ของการหารตัวเลข a ด้วยตัวเลข b อย่างไร ผู้สัมภาษณ์เขียนลงบนกระดาษ
int divide(int a, int b) {
}
*ฉันเหลือบมองกระดาษที่มีลายเซ็นวิธีการอย่างเหลือเชื่อ ที่จับคืออะไร * ฉันเขียน:
int divide(int a, int b) {
    return a/b;
}
วิธีนี้มีปัญหาหรือไม่? *ฉันเจอคนโง่เขลาจริงๆ* เห็นได้ชัดว่าไม่ใช่.. ถัดมาเป็นคำถามที่ถูกต้อง: จะเกิดอะไรขึ้นถ้า b=0? *โอ้โห ฉันกำลังจะโดนไล่ออกจากออฟฟิศแล้วถ้ายังทำแบบนี้ต่อไป!* โอ้ ใช่ แน่นอน ที่นี่เรามีอาร์กิวเมนต์ประเภท int ดังนั้น Arithmetic Exception จะถูกส่งออกไป หากอาร์กิวเมนต์เป็นแบบ float หรือ double ผลลัพธ์จะเป็น Infinity เราจะทำอย่างไรเกี่ยวกับเรื่องนี้? ฉันเริ่มเขียน try/catch
int divide(int a, int b) {
    try {
        return a/b;
    } catch (Exception e) {
        e.printStackTrace();
        return ... // ??? what the hack?
    }
}
*ฉันสามารถคืนสินค้าและหยุดนิ่งได้: จำเป็นต้องคืนบางสิ่งในกรณีที่เกิดข้อผิดพลาด แต่ "บางสิ่ง" นี้แตกต่างจากผลการคำนวณได้อย่างไร * เราจะได้อะไรกลับมา? หืม... ฉันจะเปลี่ยนประเภทของตัวแปรส่งคืนเป็น Integer และในกรณีที่มีข้อยกเว้น ฉันจะคืนค่า null ลองจินตนาการว่าเราไม่สามารถเปลี่ยนประเภทได้ เราจะออกไปได้ไหม? บางทีเราอาจทำอย่างอื่นได้ยกเว้นข้อยกเว้น? *มาแล้ว* เราสามารถส่งต่อไปยังวิธีการโทรได้เช่นกัน! ขวา. มันจะมีลักษณะอย่างไร?
int divide(int a, int b) throws ArithmeticException{
    return a/b;
}

void callDivide(int a, int b) {
    try {
        divide(a, b);
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
}
จำเป็นต้องจัดการกับข้อยกเว้นหรือไม่? ใช่ เพราะเราส่งต่ออย่างชัดเจนจากวิธีหาร (*ฉันผิดที่นี่! ต่อไปนี้คือคำถามนำจากผู้สัมภาษณ์เพื่อให้ได้คำตอบที่ถูกต้อง*) และข้อยกเว้นทางคณิตศาสตร์ - มีข้อยกเว้นประเภทใด - เลือกหรือไม่เลือก? นี่เป็นข้อยกเว้นรันไทม์ ซึ่งหมายความว่าไม่ได้เลือก *คำถามยอดฮิตมาถึงแล้ว* ปรากฏว่าตามคำพูดของคุณ ถ้าเราระบุ Throws Arithmetic Exception ในลายเซ็นเมธอด มันจะกลายเป็นข้อยกเว้นที่ถูกตรวจสอบใช่หรือไม่ *ฮึ!* อาจจะ... ไม่ ใช่ มันหายไปแล้ว หากเราระบุการพ่น /unchecked ข้อยกเว้น/ ในลายเซ็น เราจะเตือนเพียงว่าวิธีการนี้สามารถส่งข้อยกเว้นได้ แต่ไม่จำเป็นต้องจัดการในวิธีการเรียก ที่แยกออก มีอะไรอีกที่เราสามารถทำได้เพื่อหลีกเลี่ยงข้อผิดพลาดหรือไม่? *หลังจากคิดอยู่สักพัก* ใช่ เรายังสามารถตรวจสอบได้ว่า (b==0) หรือไม่ และดำเนินการตามตรรกะบางอย่าง ขวา. ดังนั้นเราสามารถไปได้ 3 วิธี:
  • ลอง/จับ
  • พ่น - ส่งต่อไปยังวิธีการโทร
  • การตรวจสอบข้อโต้แย้ง
ในกรณีนี้divideคุณคิดว่าวิธีไหนดีกว่ากัน?
ฉันจะเลือกที่จะส่งต่อข้อยกเว้นไปยังวิธีการโทรเพราะ... ในวิธีการหารยังไม่ชัดเจนว่าจะประมวลผลข้อยกเว้นนี้อย่างไรและผลลัพธ์ประเภทใดintที่ส่งคืนในกรณีที่เกิดข้อผิดพลาด และในวิธีการเรียก ฉันจะใช้อาร์กิวเมนต์ b เพื่อตรวจสอบว่ามีค่าเท่ากับศูนย์หรือไม่ ดูเหมือนว่าคำตอบนี้จะทำให้ผู้ให้สัมภาษณ์พอใจ แต่บอกตามตรง ฉันไม่แน่ใจว่าคำตอบนี้จะไม่คลุมเครือ))

ร่าง 2. “ใครเร็วกว่ากัน”

หลังจากคำถามมาตรฐาน ArrayList แตกต่างจาก LinkedList อย่างไร มาถึงสิ่งนี้: จะเกิดอะไรขึ้นเร็วกว่า - การแทรกองค์ประกอบลงตรงกลางArrayListหรือตรงLinkedListกลาง *ที่นี่ฉันข้ามไป ฉันจำได้ว่าทุกที่ที่ฉันอ่านข้อความเช่น “ใช้LinkedListเพื่อแทรกหรือลบองค์ประกอบที่อยู่ตรงกลางรายการ” ที่บ้านฉันตรวจสอบการบรรยายของ JavaRush อีกครั้ง มีวลีหนึ่ง: “ถ้าคุณจะแทรก (หรือลบ) องค์ประกอบหลายอย่างลงตรงกลางคอลเลกชัน คุณควรใช้LinkedList. ในกรณีอื่นๆ ทั้งหมด - ArrayList” ตอบอัตโนมัติ* จะเร็วขึ้นด้วยLinkedList. กรุณาชี้แจงด้วย
  1. ในการแทรกองค์ประกอบที่อยู่ตรงกลางArrayListเราจะค้นหาองค์ประกอบในรายการในเวลาคงที่ จากนั้นคำนวณดัชนีขององค์ประกอบทางด้านขวาขององค์ประกอบที่ถูกแทรกใหม่ตามเวลาเชิงเส้น
  2. สำหรับLinkedList.. ก่อนอื่นเราจะไปถึงจุดกึ่งกลางของเวลาเชิงเส้น จากนั้นจึงแทรกองค์ประกอบในเวลาคงที่ โดยเปลี่ยนลิงก์สำหรับองค์ประกอบข้างเคียง
ปรากฎว่าอันไหนเร็วกว่ากัน? อืม... ปรากฎว่าเหมือนกัน แต่เมื่อไหร่จะLinkedListเร็วกว่านี้? ปรากฎว่าเมื่อเราแทรกเข้าไปในครึ่งแรกของรายการ ตัวอย่างเช่น หากคุณแทรกไว้ที่จุดเริ่มต้น คุณArrayListจะต้องคำนวณดัชนีทั้งหมดใหม่จนถึงส่วนท้ายสุด แต่คุณLinkedListจะต้องเปลี่ยนการอ้างอิงขององค์ประกอบแรกเท่านั้น คุณธรรม: อย่าเชื่อทุกสิ่งที่เขียนอย่างแท้จริง แม้แต่ใน JavaRush!)

ร่าง 3. “เราจะอยู่ที่ไหนถ้าไม่มีความเท่าเทียมและแฮชโค้ด!”

การสนทนาเกี่ยวกับความเท่าเทียมกันและแฮชโค้ดนั้นยาวมาก - จะแทนที่มันได้อย่างไร การใช้งานแบบใดที่จะเกิดขึ้นObjectสิ่งที่เกิดขึ้นภายใต้ประทุน เมื่อมีการแทรกองค์ประกอบเข้าไปHashMapใน ฯลฯ ฉันจะให้คะแนนที่น่าสนใจในความคิดของฉันเพียงบางส่วน* ลองนึกภาพว่าเราได้สร้างชั้นเรียนขึ้นมา
public class A {
    int id;

    public A(int id) {
        this.id = id;
    }
}
และ พวกเขาไม่ได้แทนที่equalsและ hashcodeอธิบายว่าจะเกิดอะไรขึ้นเมื่อมีการรันโค้ด
A a1 = new A(1);
A a2 = new A(1);
Map<A, String> hash = new HashMap<>();
hash.put(a1, "1");
hash.get(a2);
*เป็นเรื่องดีที่ก่อนการสัมภาษณ์ ฉันใช้เวลาสองสามวันโดยเฉพาะในการทำความเข้าใจอัลกอริธึมพื้นฐาน ความซับซ้อน และโครงสร้างข้อมูล ซึ่งช่วยได้มาก ขอบคุณ CS50!*
  1. สร้างคลาส A สองอินสแตนซ์

  2. เราสร้างแผนที่เปล่า ซึ่งตามค่าเริ่มต้นจะมีตะกร้า 16 ใบ คีย์คืออ็อบเจ็กต์ของคลาส A ซึ่งเมธอดequalsและ จะไม่ถูก hashcodeแทนที่

  3. วางไว้a1ในแผนที่ ในการดำเนินการนี้ อันดับแรกเราคำนวณแฮa1

    แฮชจะเท่ากับอะไร?

    ที่อยู่ของเซลล์ในหน่วยความจำคือการนำวิธีการจากคลาสไปใช้Object

  4. เราจะคำนวณดัชนีตะกร้าตามแฮช

    เราจะคำนวณมันได้อย่างไร?

    *ขออภัย ฉันไม่ได้ให้คำตอบที่ชัดเจนที่นี่ คุณมีตัวเลขที่ยาว - แฮชและมีที่เก็บข้อมูล 16 อัน - จะกำหนดดัชนีได้อย่างไรเพื่อให้วัตถุที่มีแฮชต่างกันกระจายเท่า ๆ กันทั่วทั้งที่เก็บข้อมูล ฉันจินตนาการได้ว่าดัชนีมีการคำนวณดังนี้:

    int index = hash % buckets.length

    ที่บ้านฉันเห็นว่าการใช้งานดั้งเดิมในซอร์สโค้ดแตกต่างออกไปเล็กน้อย:

    static int indexFor(int h, int length)
    {
        return h & (length - 1);
    }
  5. เราตรวจสอบว่าไม่มีการชนกันและใส่ a1

  6. เรามาดูวิธีการกันดีgetกว่า รับประกันว่าอินสแตนซ์ a1 และ a2 จะมีที่แตกต่างกันhash(ที่อยู่ต่างกันในหน่วยความจำ) ดังนั้นเราจะไม่พบสิ่งใดสำหรับคีย์นี้

    จะเกิดอะไรขึ้นถ้าเรากำหนดมันใหม่เฉพาะhashcodeในคลาส A และพยายามแทรกลงในแฮชแมปก่อนด้วยคีย์ a1 แล้วตามด้วย a2?

    ก่อนอื่นเราจะค้นหาตะกร้าที่ต้องการโดยhashcode- การดำเนินการนี้จะดำเนินการอย่างถูกต้อง ต่อไป เรามาเริ่มดูออบเจ็กต์Entryใน LinkedList ที่แนบมากับรถเข็นแล้วเปรียบเทียบคีย์equalsด้วย เพราะ equalsไม่ได้ถูกแทนที่ ดังนั้นการใช้งานพื้นฐานจะถูกนำมาจากคลาสObject- การเปรียบเทียบโดยการอ้างอิง รับประกันว่า a1 และ a2 จะมีลิงก์ที่แตกต่างกัน ดังนั้นเราจะ "พลาด" องค์ประกอบที่แทรก a1 และ a2 จะถูกวางไว้ใน LinkedList เป็นโหนดใหม่

    ข้อสรุปคืออะไร? เป็นไปได้ไหมที่จะใช้เป็นคีย์ในHashMapวัตถุที่ไม่มีการแทนที่equalshashcode?

    ไม่คุณไม่สามารถ.

ร่าง 4. “จงใจทำลายมันซะ!”

หลังจากคำถามเกี่ยวกับข้อผิดพลาดและข้อยกเว้น คำถามต่อไปนี้ตามมา: เขียนตัวอย่างง่ายๆ ที่ฟังก์ชันจะส่ง StackOverflow *จากนั้นฉันก็จำได้ว่าข้อผิดพลาดนี้รบกวนจิตใจฉันอย่างไรเมื่อฉันพยายามเขียนฟังก์ชันแบบเรียกซ้ำ* สิ่งนี้อาจเกิดขึ้นในกรณีของการเรียกซ้ำ หากระบุเงื่อนไขในการออกจากการเรียกซ้ำไม่ถูกต้อง *จากนั้นฉันก็เริ่มฉลาดขึ้นนิดหน่อย ในที่สุดผู้สัมภาษณ์ก็ช่วย ทุกอย่างกลายเป็นเรื่องเรียบง่าย*
void sof() {
    sof();
}
Error นี้แตกต่างกับ อย่างไรOutOfMemory? *ฉันไม่ได้ตอบที่นี่ แต่ภายหลังฉันพบว่านี่เป็นคำถามเกี่ยวกับความรู้เกี่ยวStackกับHeapหน่วยความจำ Java (การเรียกและการอ้างอิงไปยังอ็อบเจ็กต์จะถูกเก็บไว้ใน Stack และอ็อบเจ็กต์เองก็ถูกเก็บไว้ในหน่วยความจำ Heap) ดังนั้น StackOverflow จะถูกโยนทิ้งไปเมื่อไม่มีพื้นที่ในStackหน่วยความจำเหลือสำหรับการเรียกใช้เมธอดถัดไป และOutOfMemoryพื้นที่สำหรับวัตถุในHeapหน่วยความจำหมด*
นี่คือช่วงเวลาจากการสัมภาษณ์ที่ฉันจำได้ ในที่สุดฉันก็ได้รับการยอมรับให้ฝึกงานดังนั้นฉันจึงมีเวลาฝึกอบรม 2.5 เดือนข้างหน้าและหากทุกอย่างเป็นไปด้วยดีจะได้งานในบริษัท) หากมีความสนใจฉันสามารถเขียนบทความอื่นได้ คราวนี้เล็กลงด้วย การวิเคราะห์ปัญหาง่ายๆ แต่เป็นตัวอย่างที่ฉันได้รับการสัมภาษณ์จากบริษัทอื่น นั่นคือทั้งหมดสำหรับฉัน ฉันหวังว่าบทความนี้จะช่วยให้ใครบางคนมีข้อมูลเชิงลึกหรือจัดระเบียบความรู้ของพวกเขา มีความสุขในการเรียนรู้ทุกคน!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION