1.StringBuilder/StringBuffer
الطريقة الأكثر شيوعًا وبساطة هي استخدام StringBuilder/StringBuffer :public static String reverseString(String str) {
return new StringBuilder(str).reverse().toString();
}
الحل الأفضل = الأبسط. عندما سئل عن كيفية عكس سلسلة في جافا، هذا هو أول ما يجب أن يتبادر إلى الذهن. لكننا تحدثنا عن الخوارزميات سابقًا، أليس كذلك؟ دعونا نلقي نظرة على الحلول التي ليست خارج الصندوق.
2. حل المصفوفة
public static String reverseString(String str) {
char[] array = str.toCharArray();
String result = "";
for (int i = array.length - 1; i >= 0; i--) {
result = result + array[i];
}
return result;
}
نقوم بتحويل السلسلة الخاصة بنا إلى مصفوفة باستخدام طريقة toCharArray . لنقم بتشغيل حلقة for خلال هذه المصفوفة من نهايتها، مع إضافة أحرف إلى السلسلة الناتجة على طول الطريق.
3. الحل مع charAt
public static String reverseString(String str) {
String result = "";
for (int i = 0; i < str.length(); i++) {
result = str.charAt(i) + result;
}
return result;
}
في هذه الحالة، لا نحتاج حتى إلى تقسيم السلسلة إلى مصفوفة، لأننا نستخرج كل حرف باستخدام طريقة فئة السلسلة - charAt (حلقة for، مرة أخرى، تكون عكسية، مما يسمح لنا بأخذ الأحرف بشكل تسلسلي إلى الوراء).
4. الحل مع المكدس
لم يستخدم أحد فئة Stack لفترة طويلة، وتعتبر قديمة، ولكن مع ذلك، كمرجع، سيكون من المفيد النظر في الحل باستخدامها:public static String reverseString(String str) {
Stack<Character> stack = new Stack<>();
String result = "";
for (Character character : str.toCharArray()) {
stack.add(character);
}
while (!stack.isEmpty()) {
result = result + stack.pop();
}
return result;
}
هنا مرة أخرى نستخدم toCharArray لتقسيم السلسلة إلى مصفوفة ووضعها كلها في المكدس الخاص بنا باستخدام نوع عام Character . بعد ذلك، نبدأ في أخذ العناصر من أعلى المكدس. نظرًا لطبيعة المكدس كبنية LIFO - L ast I n F first O ut (أولًا يدخل وآخر يخرج)، سيتم أخذ العناصر إلى الوراء وسيتم تخزين النتيجة في الصف الناتج.
5. الحل عن طريق العودية
يمكن حل كل مشكلة خوارزمية تقريبًا باستخدام التكرار. وهنا أيضًا لا يمكننا الاستغناء عنها. أو حتى بدونهم. بعد كل شيء، اليوم سننظر ليس فقط في طريقة واحدة لحل العودية، ولكن في عدة طرق.-
الطريقة الأولى
public static String reverseString(String str) { String rightStr; String leftStr; int length = str.length(); if (length <= 1) { return str; } leftStr = str.substring(0, length / 2); rightStr = str.substring(length / 2, length); return reverseString(rightStr) + reverseString(leftStr); }
نستخدم متغيرات rightStr و leftStr لتقسيم السلسلة الواردة إلى جزأين متساويين. بعد ذلك، باستخدام هذا التقسيم، قمنا بتقسيم السلسلة إلى أصغر أجزاء قابلة للقسمة (حرف واحد). بعد ذلك، تبدأ عملية التكرار في الانهيار، مما يؤدي إلى إرجاع الأحرف بالترتيب المعاكس (تم وضع الأحرف التي كانت على اليمين على اليسار، وتلك التي كانت على اليسار تم وضعها على اليمين)
يجب ألا ننسى أن كل تكرار هو استدعاء متعدد لطريقة ما، ونتيجة لذلك، يستهلك قدرًا كبيرًا من الموارد. حسنًا، إذا كنا نتحدث عن التكرار مع حالة خروج غير قابلة للتحقيق، فهذا هو الطريق إلى اللانهاية وإلى StackOverflowError.
-
الطريقة الثانية
نحتاج هنا إلى وسيطة إضافية في الطريقة - Index.
عند تشغيل هذه الطريقة، يتم إعطاء سلسلة بطول -1:
String str = "JavaRush forever"; System.out.println(reverseString(str, str.length()-1));
والطريقة نفسها:
public static String reverseString(String str, int index) { if(index == 0){ return str.charAt(0) + ""; } char letter = str.charAt(index); return letter + reverseString(str, index-1); }
يعمل فهرسنا كمؤشر لعنصر الصف الذي سنستخدمه الآن (وسوف نستخدم العناصر من النهاية).
لذلك، قمنا بتعيين شروط الخروج عندما يصل الفهرس إلى العنصر الأول.
- الطريقة الثالثة
public static String reverseString(String str) { if (str.length() <= 1) { return str; } return reverseString(str.substring(1)) + str.charAt(0); }
هذه الطريقة هي في الأساس أبسط الطرق العودية. وكما نتذكر، بسيط = الأفضل.
أثناء كل تشغيل، نحدد نفس السلسلة، ولكن بدون العنصر الأول. عند الوصول إلى حالة الخروج (عندما يتبقى لدينا حرف واحد)، تبدأ عملية التكرار في الانهيار، وسيتم إضافة الحرف السابق غير المستخدم إلى كل نتيجة لاحقة.
نقوم بإضافة القيم التي تم الحصول عليها باستخدام فهرس الحروف مع نتيجة التنفيذ السابق للطريقة وإرجاع النتيجة.
6. استخدام XOR
XOR هي عملية منطقية للبت. في حالة وجود متغيرين، تكون نتيجة العملية صحيحة إذا وفقط إذا كانت إحدى الوسيطتين صحيحة والأخرى خاطئة.أ | ب | ي |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
(A XOR B) XOR B = A
(A XOR B) XOR A = B
كيف ستبدو الطريقة:
public static String reverseString(String str) {
char[] arr = str.toCharArray();
int low = 0;
int high = arr.length - 1;
String result = "";
while (low < high) {
arr[low] = (char) (arr[low] ^ arr[high]);
arr[high] = (char) (arr[low] ^ arr[high]);
arr[low] = (char) (arr[low] ^ arr[high]);
low++;
high--;
}
for (int i = 0; i < arr.length; i++) {
result = result + arr[i];
}
return result;
}
دعونا معرفة ما يحدث هنا. نقوم بإنشاء مصفوفة من السلسلة الواردة. نقوم بإنشاء متغيرين، low و high ، لتخزين الفهارس لاجتياز المصفوفة. وفقا لذلك، سوف ينتقل المرء من البداية إلى النهاية - قمنا بتعيين القيمة 0 لها، والثاني - من النهاية إلى البداية، قمنا بتعيينها arr.length - 1 . ندخل في حلقة يتم تشغيلها طالما أن ارتفاع المؤشر أكبر من انخفاضه . هذا هو المكان الذي تبدأ فيه الأشياء الممتعة - استخدام OR الحصري. دعونا ننظر إلى x و y كمثال . لنفترض أن arr[high] = 'x'; سيكون رمزه الثنائي 1 1 1 1 0 0 0 في هذا الوقت arr[high] = 'n'; الكود الثنائي - 1 1 0 1 1 1 0 ما سيكون لدينا في عمليات XOR في الحلقة:
-
arr[low] = (char) (arr[low] ^ arr[high]);
arr[low] = 1 1 0 1 1 1 0 arr[high] =1 1 1 1 0 0 0 arr[low] = 0 0 1 0 1 1 0
-
arr[high] = (char) (arr[low] ^ arr[high]);
arr[low] = 0 0 1 0 1 1 0 arr[high] = 1 1 1 1 0 0 0 arr[high] = 1 1 0 1 1 1 0
-
arr[low] = (char) (arr[low] ^ arr[high]);
arr[low] = 0 0 1 0 1 1 0 arr[high] = 1 1 0 1 1 1 0 arr[low] = 1 1 1 1 0 0 0
GO TO FULL VERSION