تمارين
مراجعة المفاهيم
كيف تجد المصفوفات والقوائم المترابطة عنصراً
تخزّن مصفوفة وقائمة مترابطة أحادية [A, B, C, D, E] بالترتيب معاً. وتحتاج الآن إلى الوصول إلى العنصر الرابع D:
- أي فهرس يمكن للمصفوفة استخدامه مباشرةً؟
- بدءاً من العقدة الرأسية
A، أي العقد تُزار بالترتيب عند اتباعnext؟ - كلما تحرك العنصر المطلوب أبعد نحو النهاية، كيف يتغير عدد الخطوات في كل بنية؟ وأي البنيتين أفضل للوصول المتكرر حسب الموضع، ولماذا؟
الإجابة
-
مع الفهرس المبدوء من الصفر، يكون فهرس العنصر الرابع 3، لذا يمكن للمصفوفة الوصول إلى
arr[3]مباشرةً. -
يجب أن تبدأ القائمة المترابطة الأحادية من الرأس. ومسار الوصول فيها هو
A → B → C → D، وهو يتطلب ثلاث حركات عبرnext. -
تستطيع المصفوفة تحديد موقع عنصر مباشرةً من عنوانها الابتدائي وفهرسه، لذا يكون التعقيد الزمني للوصول حسب الموضع . وللوصول إلى العقدة رقم ، يجب أن تبدأ القائمة المترابطة الأحادية من العقدة الرأسية وتتبع
nextعدد مرة، وهو ما يستغرق زمن في أسوأ الحالات.وتتعلق هذه المقارنة بالوصول حسب الموضع فقط؛ وهي لا تعني أن القوائم المترابطة أبطأ في كل عملية.
كيف تدرج المصفوفات والقوائم المترابطة عنصراً
تخزّن مصفوفة وقائمة مترابطة أحادية A, B, C, D معاً. وتحتاج الآن إلى إدراج X بعد B:
- سعة المصفوفة 5 وهي حالياً
[A, B, C, D, _]. - القائمة المترابطة هي
A → B → C → D، ولديك بالفعل مرجع إلى العقدةB.
- أي العناصر يجب أن تحرّكها المصفوفة؟ اكتب المصفوفة بعد الإدراج.
- بأي ترتيب ينبغي للقائمة المترابطة تحديث
X.nextوB.next؟ اكتب القائمة المترابطة بعد الإدراج. - عند مقارنة كفاءة الإدراج، لماذا من المهم النص على أن «لديك بالفعل مرجع إلى العقدة B»؟
الإجابة
-
تحرّك المصفوفة
Dأولاً موضعاً واحداً إلى اليمين، ثم تحرّكCموضعاً واحداً إلى اليمين، وأخيراً تضعXعند الفهرس 2، فتنتج[A, B, X, C, D]. -
يشير
B.nextفي الأصل إلىC. عيّن أولاًX.next = B.next، فيشيرXإلىC؛ ثم عيّنB.next = X. وتكون النتيجةA → B → X → C → D. وإذا طُمسB.nextأولاً دون حفظ الرابط الأصلي، فقد يصبحCغير قابل للوصول. -
بمجرد معرفة موقع
B، لا يغيّر الإدراج في القائمة المترابطة سوى رابطين ويستغرق زمن . أما إذا وجب إيجادBأولاً انطلاقاً من الرأس، فقد يستغرق ذلك البحث وحده زمن .
كيف تنمو سعة القائمة
قائمة مبنية على مصفوفة تحتوي حالياً على [A, B, C]، بطول size = 3 وسعة capacity = 4.
وعندما لا تكون السعة كافية، تُنشأ مصفوفة جديدة بسعة تساوي ضعف السعة القديمة.
- بعد إلحاق
D، ما طول القائمة وسعتها؟ وهل يلزم توسيع السعة؟ - عند إلحاق
Eبعد ذلك، ما السعة التي تصبح عليها؟ وكم عنصراً موجوداً يجب نسخه؟ - لا يمكن أن يتغير طول المصفوفة الأساسية. فلماذا تبدو سعة القائمة قادرة على النمو رغم ذلك؟
الإجابة
-
يستوعب الموضع الفارغ الأخير
D. وتصبح المحتويات الآن[A, B, C, D]، معsize = 4وcapacity = 4، فلا حاجة إلى توسيع السعة. -
لا يوجد موضع فارغ عند إلحاق
E، لذا يجب إنشاء مصفوفة جديدة بسعة 8. وتُنسخ العناصر الأربعة الموجودةA, B, C, Dإليها قبل إضافةE. وتكون النتيجةsize = 5وcapacity = 8. -
المصفوفة الأصلية نفسها لا تنمو. وإنما تنشئ القائمة مصفوفة جديدة أكبر، وتنسخ العناصر الموجودة إليها، ثم تستخدم المصفوفة الجديدة كتخزين أساسي لها. ومن منظور المستخدم، تكون السعة قد نمت.
تمارين برمجية
إضافة واحد إلى عدد صحيح كبير مخزّن كمصفوفة
تخزّن المصفوفة digits الأرقام العشرية لعدد صحيح غير سالب من اليسار إلى اليمين. فمثلاً، تمثّل [3, 0, 8] العدد 308.
ويُمثَّل العدد 0 بـ [0]؛ وفي كل مدخل آخر لا يكون الرقم الأول 0.
حاكِ الجمع العمودي العشري لإضافة 1 إلى هذا العدد، وأعد النتيجة بالصيغة المصفوفية نفسها.
ويمكنك تعديل digits مباشرةً. وإذا ظهر رقم حمل جديد في المقدمة، فيمكنك إعادة مصفوفة أطول.
تلميحات
- ابدأ من الرقم الأخير في المصفوفة، تماماً كما في الجمع العمودي العادي
- إذا كان الرقم الحالي أقل من 9، فأضف واحداً وأعِد النتيجة فوراً
- إذا كان الرقم الحالي 9، فغيّره إلى 0؛ وإذا كانت كل الأرقام 9، فضع 1 في المقدمة
LeetCode{ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }
عكس قائمة مترابطة أحادية
تُعطى العقدة الرأسية head لقائمة مترابطة أحادية. وتحتوي كل عقدة على قيمة ومرجع next إلى العقدة التالية.
استخدم أسلوب التكرار لعكس جميع الروابط بين العقد، وأعد العقدة الرأسية الجديدة. ولا تُنشئ أي عقد جديدة في القائمة المترابطة.
تلميحات
- ارسم أولاً على الورق ثلاث عقد متصلة والمؤشرين prev و cur
- قبل تغيير cur.next، احفظ العقدة التالية الأصلية في nxt
- بعد عكس cur.next، عيّن prev = cur ثم cur = nxt لمواصلة العمل مع العقدة التالية في القائمة الأصلية
LeetCode{ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }