หนึ่งในคำถามยอดนิยมจากโครงสร้างข้อมูลและอัลกอริทึมส่วนใหญ่ถามในการสัมภาษณ์ทางโทรศัพท์
หนึ่งในคำถามยอดนิยมจากโครงสร้างข้อมูลและอัลกอริทึมส่วนใหญ่ถามในการสัมภาษณ์ทางโทรศัพท์
คำตอบ:
โดยการโกงและทำสองผ่านในเวลาเดียวกันในแบบคู่ขนาน แต่ฉันไม่รู้ว่านายหน้าจะเป็นแบบนี้หรือไม่
สามารถทำได้ในรายการเชื่อมโยงเดียวกับเคล็ดลับดี พอยน์เตอร์สองตัวเดินทางข้ามรายการหนึ่งรายการด้วยความเร็วสองเท่า เมื่อคนที่อดอาหารมาถึงจุดสุดท้ายอีกคนหนึ่งก็ครึ่งทาง
หากไม่ใช่รายการที่เชื่อมโยงเป็นสองเท่าคุณสามารถนับและใช้รายการได้ แต่ต้องมีการเพิ่มหน่วยความจำของคุณเป็นสองเท่าในกรณีที่เลวร้ายที่สุดและจะไม่ทำงานหากรายการมีขนาดใหญ่เกินกว่าจะจัดเก็บในหน่วยความจำได้
ทางออกที่เรียบง่ายและไร้สาระเกือบเป็นเพียงการเพิ่มโหนดกลางทุกสองโหนด
function middle(start) {
var middle = start
var nextnode = start
var do_increment = false;
while (nextnode.next != null) {
if (do_increment) {
middle = middle.next;
}
do_increment = !do_increment;
nextnode = nextnode.next;
}
return middle;
}
อธิบายอย่างละเอียดเกี่ยวกับคำตอบของ Hendrik
หากเป็นรายการที่เชื่อมโยงเป็นสองเท่าให้ทำซ้ำจากปลายทั้งสองด้าน
function middle(start, end) {
do_advance_start = false;
while(start !== end && start && end) {
if (do_advance_start) {
start = start.next
}
else {
end = end.prev
}
do_advance_start = !do_advance_start
}
return (start === end) ? start : null;
}
ป.ร. ให้ไว้ [1, 2, 3] => 2
1, 3
1, 2
2, 2
ป.ร. ให้ไว้ [1, 2] => 1
1, 2
1, 1
ป.ร. ให้ไว้ [1] => 1
ป.ร. ให้ไว้ [] => null
สร้างโครงสร้างที่มีตัวชี้ที่สามารถชี้ไปยังโหนดของรายการที่เชื่อมโยงและมีตัวแปรจำนวนเต็มซึ่งเก็บจำนวนของโหนดในรายการ
struct LL{
struct node *ptr;
int count;
}start;
สร้างอาเรย์แบบไดนามิกโดยที่แต่ละองค์ประกอบของอาเรย์เป็นตัวชี้ไปยังแต่ละโหนดในรายการตามลำดับการสำรวจโดยเริ่มจากจุดเริ่มต้น สร้างจำนวนเต็มเริ่มต้นที่ 1 ที่ติดตามจำนวนโหนดที่คุณได้เยี่ยมชม (ซึ่งเพิ่มขึ้นทุกครั้งที่คุณไปที่โหนดใหม่) เมื่อคุณไปถึงจุดสิ้นสุดคุณจะรู้ว่ารายการใหญ่แค่ไหนและคุณมีลำดับของพอยน์เตอร์ที่สั่งให้แต่ละโหนด สุดท้ายหารขนาดของรายการด้วย 2 (และลบ 1 สำหรับการจัดทำดัชนีแบบ 0) และดึงตัวชี้ที่จัดขึ้นในดัชนีของอาร์เรย์นั้น หากขนาดของรายการคี่คุณสามารถเลือกองค์ประกอบที่จะกลับมา (ฉันจะยังคงกลับมาเป็นคนแรก)
นี่คือโค้ด Java บางส่วนที่ทำให้เกิดประเด็น (แม้ว่าแนวคิดของอาเรย์แบบไดนามิกจะดูสับสนเล็กน้อย) ฉันจะให้ C / C ++ แต่ฉันเป็นสนิมในพื้นที่นั้น
public Node getMiddleNode(List<Node> nodes){
int size = 1;
//add code to dynamically increase size if at capacity after adding
Node[] pointers = new Node[10];
for (int i = 0; i < nodes.size(); i++){
//remember to dynamically allocate more space if needed
pointers[i] = nodes.get(i);
size++;
}
return pointers[(size - 1)/2];
}
การเรียกซ้ำเป็นการพิจารณามากกว่าหนึ่งรอบหรือไม่
สำรวจรายการไปยังจุดสิ้นสุดผ่านการนับจำนวนเต็มโดยการอ้างอิง ทำสำเนาโลคัลของค่านั้นในแต่ละระดับเพื่อการอ้างอิงในภายหลังและเพิ่มจำนวนการอ้างอิงไปยังการโทรครั้งต่อไป
บนโหนดสุดท้ายให้หารจำนวนด้วยสองแล้วตัดทอน / floor () ผลลัพธ์ (หากคุณต้องการให้โหนดแรกเป็น "กลาง" เมื่อมีเพียงสององค์ประกอบเท่านั้น) หรือปัดเศษขึ้น (ถ้าคุณต้องการให้โหนดที่สองเป็น ตรงกลาง"). ใช้ดัชนีที่เป็นศูนย์หรือหนึ่งฐานอย่างเหมาะสม
คลี่คลายให้จับคู่การอ้างอิงกับสำเนาโลคัล (ซึ่งเป็นหมายเลขของโหนด) ถ้าเท่ากับส่งคืนโหนดนั้น มิฉะนั้นส่งคืนโหนดที่ส่งคืนจากการเรียกซ้ำ
.
มีวิธีอื่นในการทำเช่นนี้ บางคนอาจยุ่งยากน้อยกว่า (ฉันคิดว่าฉันเห็นคนพูดว่าอ่านมันลงในอาเรย์และใช้ความยาวของอาเรย์เพื่อกำหนดความรุ่งโรจน์กลาง) แต่ตรงไปตรงมาไม่มีคำตอบที่ดีเพราะเป็นคำถามสัมภาษณ์ที่โง่ หมายเลขหนึ่งที่ยังคงใช้รายการที่เชื่อมโยง ( สนับสนุนความคิดเห็น ); ประการที่สองการค้นหาโหนดกลางเป็นแบบฝึกหัดตามอำเภอใจโดยไม่มีค่าในสถานการณ์จริง สามถ้าฉันต้องการทราบโหนดกลางรายการที่เชื่อมโยงของฉันจะแสดงจำนวนโหนด มันง่ายกว่าที่จะรักษาทรัพย์สินนั้นให้เสียเวลาไปกับการสำรวจรายการทั้งหมดทุกครั้งที่ฉันต้องการโหนดกลาง และสุดท้ายสี่ผู้สัมภาษณ์ทุกคนจะชอบหรือปฏิเสธคำตอบที่ต่างกัน - สิ่งที่ผู้สัมภาษณ์คนหนึ่งคิดว่าลื่นแล้วคนอื่นจะเรียกว่าไร้สาระ
ฉันมักจะตอบคำถามสัมภาษณ์ด้วยคำถามเพิ่มเติม หากฉันได้รับคำถามเช่นนี้ (ฉันไม่เคยมี) ฉันจะถาม (1) คุณเก็บอะไรไว้ในรายการที่เชื่อมโยงนี้และมีโครงสร้างที่เหมาะสมกว่าในการเข้าถึงโหนดกลางได้อย่างมีประสิทธิภาพหากมีความจำเป็นอย่างแท้จริง ; (2) ข้อ จำกัด ของฉันคืออะไร ฉันสามารถทำให้เร็วขึ้นหากหน่วยความจำไม่เป็นปัญหา (เช่นคำตอบของอาร์เรย์) แต่ถ้าผู้สัมภาษณ์คิดว่าการพะรุงพะรังของหน่วยความจำนั้นสิ้นเปลืองฉันจะได้รับผลกระทบ (3) ฉันจะพัฒนาภาษาอะไร เกือบทุกภาษาสมัยใหม่ที่ฉันรู้จักมีคลาสในตัวเพื่อจัดการกับรายการเชื่อมโยงที่ทำให้การข้ามผ่านรายการไม่จำเป็น - ทำไมต้องบูรณาการสิ่งที่ปรับให้มีประสิทธิภาพโดยนักพัฒนาของภาษา
โดยใช้ 2 พอยน์เตอร์ เพิ่มหนึ่งครั้งในการทำซ้ำแต่ละครั้งและอื่น ๆ ในทุก ๆ รอบที่สอง เมื่อตัวชี้ที่ 1 ชี้ไปที่จุดสิ้นสุดของรายการที่เชื่อมโยงไปที่ตัวชี้ที่ 2 จะชี้ไปที่โหมดตรงกลางของรายการที่เชื่อมโยง