วิธีการ Reverse สตริงใน Java โดยใช้การเรียกซ้ำ
⚡ สรุปอย่างชาญฉลาด
Revการส่งสตริงใน Java การเรียกซ้ำทำงานโดยการตัดอักขระตัวแรกออก กลับด้านส่วนที่เหลือ และเพิ่มอักขระตัวแรกนั้นต่อท้าย สตริงว่างจะหยุดการเรียกและคลายสแต็ก
ในโปรแกรมตัวอย่างนี้ เราจะย้อนกลับสตริงที่ผู้ใช้ป้อน
เราจะสร้างฟังก์ชันเพื่อย้อนกลับสตริง Later เราจะเรียกฟังก์ชันนี้ซ้ำไปเรื่อยๆ จนกว่าตัวอักษรทั้งหมดจะกลับด้าน การเรียกซ้ำเหมาะสมกับปัญหานี้ เพราะสตริงที่กลับด้านแล้วก็คือส่วนท้ายของสตริงเดิมที่ถูกกลับด้าน โดยมีตัวอักษรตัวแรกของสตริงเดิมติดอยู่ที่ท้าย ซึ่งก็คือปัญหาเดียวกันแต่ลดจำนวนตัวอักษรลงหนึ่งตัว
เขียนถึง Java โปรแกรมไป Reverse เชือก
คลาสข้างล่างนี้ประกาศตัวแปรอินพุตในเมธอด main() ส่งต่อไปยังเมธอด reverseString() และพิมพ์สิ่งที่ได้กลับมา การเรียกใช้ println() สองครั้งภายในเมธอดทำให้แต่ละขั้นตอนของการเรียกซ้ำปรากฏให้เห็นในคอนโซล
package com.guru99; public class ReverseString { public static void main(String[] args) { String myStr = "Guru99"; //create Method and pass and input parameter string String reversed = reverseString(myStr); System.out.println("The reversed string is: " + reversed); } //Method take string parameter and check string is empty or not public static String reverseString(String myStr) { if (myStr.isEmpty()){ System.out.println("String in now Empty"); return myStr; } //Calling Function Recursively System.out.println("String to be passed in Recursive Function: "+myStr.substring(1)); return reverseString(myStr.substring(1)) + myStr.charAt(0); } }
Code Output:
แต่ละบรรทัดของผลลัพธ์คือการเรียกซ้ำหนึ่งครั้ง ตัวอักษรส่วนท้ายที่พิมพ์ในแต่ละบรรทัดจะสั้นกว่าบรรทัดด้านบนหนึ่งตัว และบรรทัดสุดท้ายจะแสดงผลลัพธ์ที่กลับด้าน
String to be passed in Recursive Function: uru99 String to be passed in Recursive Function: ru99 String to be passed in Recursive Function: u99 String to be passed in Recursive Function: 99 String to be passed in Recursive Function: 9 String to be passed in Recursive Function: String in now Empty The reversed string is: 99uruG
วิธีการใช้การเรียกซ้ำ Reversal ทำงานทีละขั้นตอน
เมธอดทั้งหมดถูกประมวลผลด้วยโค้ดเพียงสองบรรทัด กรณีพื้นฐาน if (myStr.isEmpty()) จะทำให้การเรียกซ้ำหยุดลงที่จุดใดจุดหนึ่ง บรรทัดที่เรียกซ้ำ return reverseString(myStr.substring(1)) + myStr.charAt(0) จะแบ่งการทำงานออกเป็นสองส่วน: substring(1) คือทุกอย่างหลังจากอักขระตัวแรก และ charAt(0) คืออักขระตัวแรกที่ต่อท้าย หลังจาก เศษเหลือที่กลับด้าน
Tracการป้อนข้อมูล Guru99 ทำให้ลำดับชัดเจนขึ้น Java ส่งเฟรมหนึ่งเฟรมต่อการเรียกแต่ละครั้งก่อนที่จะมีการรวมเฟรมเกิดขึ้น:
| โทร | มายสตร | โอนสายไปยังสายถัดไป | นิพจน์ที่รอการเสร็จสิ้น |
|---|---|---|---|
| 1 | Guru99 | uru99 | reverseString(“uru99”) + G |
| 2 | uru99 | ru99 | reverseString(“ru99”) + u |
| 3 | ru99 | u99 | reverseString(“u99”) + r |
| 4 | u99 | 99 | reverseString(“99”) + u |
| 5 | 99 | 9 | reverseString(“9”) + 9 |
| 6 | 9 | (ว่าง) | reverseString(“”) + 9 |
| 7 | (ว่าง) | กรณีพื้นฐานบรรลุแล้ว | ส่งคืนสตริงว่าง |
จากนั้นสแต็กจะคลายตัวจากล่างขึ้นบน และแต่ละเฟรมจะเพิ่มอักขระที่บันทึกไว้เข้าไป: สตริงว่างจะกลายเป็น 9 จากนั้น 99 จากนั้น 99u, 99ur, 99uru และสุดท้าย 99uruG. เพราะ Java สตริงไม่สามารถเปลี่ยนแปลงได้ ค่ากลางเหล่านี้จะไม่เขียนทับค่าก่อนหน้า การเชื่อมต่อแต่ละครั้งจะสร้างอ็อบเจ็กต์ String ใหม่ขึ้นมา
มีรายละเอียดสองอย่างในเอาต์พุตคอนโซลที่ควรกล่าวถึง บรรทัดที่หกจบลงโดยไม่มีอะไรอยู่หลังเครื่องหมายโคลอน เนื่องจาก substring(1) บนสตริงที่มีอักขระเดียวจะคืนค่าสตริงว่างแทนที่จะเป็นค่า null ข้อความที่ตามมาอ่านว่า “String in now Empty” ในโปรแกรมต้นฉบับ ซึ่งเป็นคำที่พิมพ์ผิด ควรจะเป็น “String is now empty” และไม่ได้แก้ไข เพื่อให้โค้ดและเอาต์พุตด้านบนยังคงตรงกันทุกบรรทัด
วิธีอื่นๆ Reverse สตริงใน Java
การเรียกซ้ำเป็นวิธีที่ชัดเจนที่สุดในการ เห็น การกลับทิศทางเกิดขึ้นได้ แต่แทบจะไม่เกิดขึ้นในรูปแบบที่โค้ดใช้งานจริงทำกัน มีสามทางเลือกที่ครอบคลุมเกือบทุกกรณีในโลกแห่งความเป็นจริง
1. StringBuilder.reverse() เป็นวิธีที่สั้นที่สุดและเร็วที่สุด คลาสนี้มีเมธอด reverse() ในตัว ดังนั้นงานทั้งหมดจึงสามารถทำได้ในบรรทัดเดียว:
String reversed = new StringBuilder(myStr).reverse().toString();
2. ลูป for ที่ใช้ charAt() โค้ดนี้จะไล่ดูสตริงย้อนหลังตั้งแต่ดัชนีสุดท้ายไปจนถึงศูนย์ ผู้สัมภาษณ์มักขอโค้ดเวอร์ชันนี้ เพราะมันแสดงให้เห็นถึงตรรกะ แทนที่จะเป็นการมอบหมายงานให้ผู้อื่นทำ:
String reversed = ""; for (int i = myStr.length() - 1; i >= 0; i--) { reversed = reversed + myStr.charAt(i); }
3. การสลับตัวชี้สองตัวไปยัง toCharArray() แปลงสตริงเป็นอาร์เรย์อักขระ จากนั้นสลับอักขระด้านนอกสุดเข้ามาด้านในจนกระทั่งตัวชี้มาบรรจบกันตรงกลาง:
char[] chars = myStr.toCharArray(); int left = 0; int right = chars.length - 1; while (left < right) { char temp = chars[left]; chars[left] = chars[right]; chars[right] = temp; left++; right--; } String reversed = new String(chars);
เทคนิคการจัดเรียงแบบเดียวกันนี้สามารถกลับลำดับตัวเลขหรือชุดข้อมูลที่เรียงลำดับอื่นๆ ได้ ซึ่งเป็นเหตุผลว่าทำไมจึงปรากฏอยู่ใน... Java แถว แบบฝึกหัดเหล่านี้ทำบ่อยพอๆ กับแบบฝึกหัดที่ใช้เครื่องสาย
ความซับซ้อนด้านเวลาและพื้นที่ของแต่ละแนวทาง
ทั้งสี่เวอร์ชันมีต้นทุนไม่เท่ากัน สูตรกำลังสองทั้งสองสูตรด้านล่างมีสาเหตุร่วมกันอย่างหนึ่งคือ มันสร้างสตริงใหม่เอี่ยมในทุกขั้นตอน และการคัดลอกอักขระ n ตัว n ครั้งนั้นเท่ากับงาน n กำลังสอง
| เข้าใกล้ | เวลา | พื้นที่พิเศษ | ทำไม |
|---|---|---|---|
| การเรียกซ้ำด้วย substring() | โอ(n²) | โอ(n²) | ฟังก์ชัน substring() จะคัดลอกอักขระที่เหลือในทุกครั้งที่เรียกใช้ และจะเก็บเฟรมสแต็กหนึ่งเฟรมต่ออักขระหนึ่งตัว |
| ลูป for ที่มี charAt() และ + | โอ(n²) | โอ(n²) | การเชื่อมต่อแต่ละครั้งจะสร้างสตริงใหม่และคัดลอกทุกสิ่งที่รวบรวมไว้จนถึงขณะนั้น |
| StringBuilder.reverse() | O (n) | O (n) | บัฟเฟอร์ที่เปลี่ยนแปลงได้หนึ่งตัว การประมวลผลหนึ่งรอบ และคู่ตัวแทนจะยังคงอยู่เหมือนเดิม |
| ตัวชี้สองตัวไปยัง toCharArray() | O (n) | O (n) | คัดลอกอาร์เรย์หนึ่งครั้ง จากนั้นสลับ n/2 ครั้งโดยไม่มีการจัดสรรเพิ่มเติม |
เลือกใช้เวอร์ชันแบบเรียกซ้ำเพื่อเรียนรู้หรือสาธิตวิธีการทำงานของสแต็กการเรียก เลือกใช้เวอร์ชันอาร์เรย์อักขระเมื่อผู้สัมภาษณ์ขอให้แสดงตรรกะด้วยตนเอง และใช้ StringBuilder.reverse() ในทุกสิ่งที่นำไปใช้งานจริง การแลกเปลี่ยนระหว่างวิธีแก้ปัญหาเพื่อการสอนและวิธีแก้ปัญหาเพื่อการใช้งานจริงนั้นปรากฏให้เห็นในแบบฝึกหัดคลาสสิกต่างๆ ตั้งแต่ เรียงฟอง และ ชุดฟีโบนักชี ไปยัง การตรวจสอบจำนวนเฉพาะแต่ละอย่างล้วนคุ้มค่าแก่การฝึกฝน Java ทั้งสองทาง
