To Lower Case
لديك سلسلة نصية s. أعد سلسلة نصية جديدة يُستبدل فيها كل حرف إنجليزي كبير، من A إلى Z، بحرفه الصغير. يبقى كل حرف آخر، مثل الحروف الصغيرة أو الأرقام أو الرموز، كما هو تمامًا.
الدالة
- sstring
- النص المراد تحويله
- تُرجعstring
- s مع تحويل كل حرف كبير إلى حرف صغير
القيود
1 ≤ s.length ≤ 104- كل حرف من
sهو حرف إنجليزي أو رقم أو أحد الرموز!#$%&()*+-./:;<=>?@[]^_`{|}~.
أمثلة
- المدخلات
- s = "Hello-World!"
- المخرجات
- "hello-world!"
- الشرح
- يتحول الحرفان الكبيران
HوWإلىhوw. أما-و!فليسا حرفين، لذا يبقيان في موضعيهما.
- المدخلات
- s = "coddy_2026"
- المخرجات
- "coddy_2026"
- الشرح
- لا يوجد حرف كبير لتغييره. تعود الأحرف الصغيرة و
_والأرقام دون تغيير.
- المدخلات
- s = "SQL"
- المخرجات
- "sql"
- الشرح
- الأحرف الثلاثة كلها كبيرة، لذا يتحول كلٌّ منها إلى الحرف الصغير المقابل له.
+15 اختبارات مخفية عند الإرسال
سؤال إضافي
هل يمكنك كتابة toUpperCase باستخدام الحلقة نفسها، وشرح سبب اختلاف A عن a ببتّ واحد فقط من رمز الحرف؟
تلميحات
افتحها واحدًا تلو الآخر. كل تلميح يكشف أكثر قليلًا.
يخزّن الكمبيوتر كل محرف كرقم. ما العلاقة بين الرقمين الخاصين بـ
Aوa؟تقابل
AإلىZالرموز من 65 إلى 90، وتقابلaإلىzالرموز من 97 إلى 122. كل حرف كبير أقل من الحرف الصغير المقابل له بـ 32 بالضبط.مرّ على الأحرف واحدًا تلو الآخر. عندما يكون الرمز بين 65 و90، أضف 32؛ وإلا فأبقِ الحرف كما هو. اجمع النتائج ووصلها لتكوين الإجابة.
الحل
توفّر كل لغة دالةً لتحويل الأحرف إلى أحرف صغيرة، وينبغي استدعاؤها في الشيفرة المستخدمة في بيئة الإنتاج. يطرح المحاورون هذه المسألة لمعرفة ما إذا كنت تعرف ما تفعله تلك الدالة: فالحرف رقم، وفي ASCII يقع رمز كل حرف كبير أقل بـ 32 بالضبط من رمز حرفه الصغير. تحقّق مما إذا كان الرمز يقع بين 'A' و'Z'، وأضف 32 إذا كان كذلك.
استدعِ الدالة المدمجة lowercase
الفكرة
تُنجز lower() في Python وtoLowerCase() في JavaScript وdowncase في Ruby وما يقابلها في كل لغة أخرى هذه المهمة بالفعل. توفّر C وC++ الدالة tolower لحرف واحد، لذا تستدعيها ضمن حلقة. يُفحَص كل حرف مرة واحدة، لذا يكون زمن العمل O(n)، وتتطلب السلسلة الجديدة مساحة O(n).
تتبع بعض هذه الدوال إعدادات اللغة في الجهاز. ففي اللغة التركية، الحرف الصغير المقابل لـ I هو ı بلا نقطة، وليس i. لهذا السبب تطلب نسختا Java وC# قاعدة ثابتة باستخدام Locale.ROOT وToLowerInvariant، حتى لا تتغير النتيجة من حاسوب إلى آخر.
هذه هي الإجابة الصحيحة في العمل. لكنها غالبًا لا تُقبل في مقابلة، لأنها تخفي الفكرة التي يدور حولها السؤال.
الخوارزمية
- استدعِ دالة تحويل الأحرف إلى أحرف صغيرة في لغتك على
s، أو استدعِtolowerعلى كل محرف في C وC++. - اطلب قاعدة ثابتة مستقلة عن اللغة حيثما توفر الدالة ذلك.
- أعِد النتيجة.
def toLowerCase(s):
return s.lower()إزاحة الرموز الرقمية للأحرف الكبيرة
الفكرة
يُخزَّن كل محرف على هيئة رقم. في ASCII، تمثّل الرموز من A إلى Z القيم من 65 إلى 90، وتمثّل الرموز من a إلى z القيم من 97 إلى 122. كلا التسلسلين مرتّب أبجديًا، والفرق بين بدايتيهما 32، لذا فإن الرمز الصغير لأي حرف كبير يساوي قيمته زائد 32: قيمة H هي 72، وقيمة h هي 104.
لذا مرّ على السلسلة مرة واحدة. إذا كانت قيمة المحرف بين 65 و90، فأضف 32؛ وإلا فانسخ المحرف كما هو. التحقق من النطاق مهم: تقع الرموز [ و^ و_ بين Z وa، ويقع @ مباشرةً قبل A. إن اختبار code < 97 فقط سيحوّل _ إلى رمز مختلف.
يُفحَص كل محرف مرة واحدة، وهذا يعني زمنًا قدره O(n). والنتيجة سلسلة جديدة بالطول نفسه، ومساحة قدرها O(n). إن كتابة 'a' - 'A' بدلًا من 32 تعبّر عن الشيء نفسه وتوضح مصدر هذا الرقم.
الخوارزمية
- انسخ
sإلى مصفوفة من الأحرف أو الرموز. - اقرأ رمز الحرف في كل موضع.
- إذا كان الرمز بين
'A'(65) و'Z'(90)، فأضف 32. - حوّل المصفوفة مرة أخرى إلى سلسلة وأعِدها.
def toLowerCase(s):
# Every capital letter sits 32 codes below its small letter: 'A' is 65, 'a' is 97.
shift = ord("a") - ord("A")
chars = []
for ch in s:
if "A" <= ch <= "Z":
ch = chr(ord(ch) + shift)
chars.append(ch)
return "".join(chars)
أخطاء شائعة وحالات حدّية
الحلقة قصيرة، لذا تكمن الأخطاء في التحقق من النطاق وفي طريقة إنشاء الإجابة.
- إضافة 32 إلى كل محرف ليس حرفًا صغيرًا. ستتغير الأرقام والرموز أيضًا: سيصبح
1هوQ. - التحقق من أحد طرفي النطاق فقط. يتحقق
code < 'a'أيضًا من[و_و@، كما يتحققcode >= 'A'أيضًا من كل حرف صغير. - استخدام
<بدلًا من<=عند النهايتين، ما يُبقيAأوZبحرف كبير. - إنشاء الإجابة باستخدام
result = result + chعلى سلسلة غير قابلة للتغيير. تنسخ كل خطوة كل ما تم إنشاؤه حتى تلك اللحظة، وهذا يؤدي إلى تعقيد تربيعي عندn = 10^4. - في C، الكتابة فوق المدخل أو نسيان
'\0'المنهي. خصّصn + 1بايت للنسخة.
أسئلة شائعة4
كيف تحوّل سلسلة نصية إلى أحرف صغيرة دون استخدام دالة مضمّنة؟
كرّر المرور على الأحرف وانظر إلى رمز كل حرف. إذا كان الرمز بين 65 (A) و90 (Z)، فأضف 32 للحصول على الحرف الصغير؛ واترك كل الأحرف الأخرى كما هي. اجمع الأحرف مجددًا في سلسلة نصية.
لماذا يكون الفرق بين الأحرف الكبيرة والصغيرة 32؟
يضع ASCII الأحرف الكبيرة عند الرموز من 65 إلى 90، والأحرف الصغيرة من 97 إلى 122، مع ستة رموز بينهما. الأبجدّيتان بالترتيب نفسه، لذا تفصل 97 - 65 = 32 بين كل زوج من الأحرف. والعدد 32 يمثّل بتًا واحدًا، لذا فإن ضبط هذا البت يحوّل الحرف الكبير إلى نظيره الصغير.
هل يمكنك تغيير حالة الأحرف باستخدام عملية بتّية؟
نعم. بالنسبة إلى حرف كبير، فإن code | 32 يضبط البت الذي يميّز بين حالتي الأحرف ويعطي الحرف الصغير، بينما code & ~32 يمسحه مجددًا. ما زلت بحاجة إلى التحقق من النطاق أولًا، لأن حيلة البت نفسها ستغيّر الأرقام والرموز أيضًا.
ما هو التعقيد الزمني لتحويل سلسلة نصية إلى أحرف صغيرة؟
يكون التعقيد O(n) لسلسلة طولها n، لأن كل محرف يُفحَص مرة واحدة. تستغرق السلسلة الجديدة مساحة O(n). إذا أمكنك تغيير مصفوفة المحارف في مكانها، تنخفض المساحة الإضافية إلى O(1).
مسائل مشابهة
مسائل تعتمد على الأفكار نفسها. حلّ اثنتين أو ثلاث منها يثبّت النمط.
Python
def toLowerCase(s):
# اكتب الكود هناالحالة 1
الحالة 2
الحالة 3
المدخلات
s = "Hello-World!"
المتوقع
"hello-world!"