การพิมพ์ข้อความในรูปแบบซิกแซก
โจทย์
กำหนดสตริงและจำนวนเต็มหนึ่งค่า เขียนโปรแกรมที่จะแปลงสตริงนั้นให้อยู่ในรูปแบบซิกแซกตามจำนวนแถวที่กำหนด สตริงจะถูกอ่านทีละแถวเพื่อสร้างสตริงที่แปลงแล้ว โปรแกรมควรรับสตริงและจำนวนเต็มเป็นอินพุต สตริงควรถูกจัดเรียงให้อยู่ในรูปแบบซิกแซกข้ามแถวตามจำนวนแถวที่กำหนด เช่น หากกำหนดสตริงเป็น “PAYPALISHIRING” และ numRows = 3
| Input | Output |
|---|---|
| PAYPALISHIRING 3 | PAHNAPLSIIGYIR |
โค้ด
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String text = scanner.nextLine();
int rows = scanner.nextInt();
if (rows == 1) {
System.out.println(text);
} else {
for (int i = 0; i < rows; i++) {
int spacer = rows - i;
int n = 0;
int extractIndex = i;
while (extractIndex < text.length()) {
char c = text.charAt(extractIndex);
System.out.print(c);
n++;
extractIndex = (i == 0 || i == rows - 1) ? extractIndex + rows + 1 : spacer * n + 1;
}
}
}
}
}คำอธิบาย
ขั้นตอนที่ 1: การเริ่มต้นโปรแกรม
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);- โค้ดเริ่มต้นด้วยการ import คลาส
Scannerซึ่งเป็นเครื่องมือที่ช่วยให้เราสามารถรับข้อมูลจากผู้ใช้ได้ - เราสร้างคลาสชื่อ
Mainและกำหนดเมธอดmainซึ่งเป็นจุดเริ่มต้นของโปรแกรม - เราสร้างตัวแปร
scannerเพื่อใช้รับข้อมูลจากผู้ใช้
ขั้นตอนที่ 2: การรับข้อมูลจากผู้ใช้
String text = scanner.nextLine();
int rows = scanner.nextInt();- เราใช้
scanner.nextLine()เพื่อรับข้อความจากผู้ใช้ และเก็บไว้ในตัวแปรtext - เราใช้
scanner.nextInt()เพื่อรับจำนวนแถวจากผู้ใช้ และเก็บไว้ในตัวแปรrows
ขั้นตอนที่ 3: การตรวจสอบกรณีพิเศษ
if (rows == 1) {
System.out.println(text);
} else {
// โค้ดสำหรับกรณีที่มีมากกว่า 1 แถว
}- ถ้าจำนวนแถวเป็น 1 เราแค่แสดงข้อความเดิมออกมา เพราะไม่ต้องจัดรูปแบบใหม่
- ถ้าไม่ใช่ เราจะดำเนินการจัดรูปแบบซิกแซก
ขั้นตอนที่ 4: การจัดรูปแบบซิกแซก
for (int i = 0; i < rows; i++) {
int spacer = rows - i;
int n = 0;
int extractIndex = i;
while (extractIndex < text.length()) {
char c = text.charAt(extractIndex);
System.out.print(c);
n++;
extractIndex = (i == 0 || i == rows - 1) ? extractIndex + rows + 1 : spacer * n + 1;
}
}นี่คือส่วนหลักของโปรแกรม ที่ทำการจัดรูปแบบซิกแซก:
- เราวนลูปตามจำนวนแถว (
rows) - สำหรับแต่ละแถว:
- เราคำนวณ
spacerซึ่งเป็นระยะห่างระหว่างตัวอักษรในแถวนั้นๆ - เราใช้
extractIndexเพื่อเก็บตำแหน่งของตัวอักษรที่จะดึงออกมา - เราวนลูปภายในเพื่อดึงตัวอักษรจากข้อความเดิม:
- ดึงตัวอักษรและแสดงผล
- คำนวณตำแหน่งถัดไปที่จะดึงตัวอักษร:
- สำหรับแถวแรกและแถวสุดท้าย: ข้ามไป
rows + 1ตำแหน่ง - สำหรับแถวอื่นๆ: ใช้สูตร
spacer * n + 1
- สำหรับแถวแรกและแถวสุดท้าย: ข้ามไป
- เราคำนวณ
ทำไมต้องใช้ extractIndex?
extractIndex เป็นตัวแปรสำคัญในการแปลงข้อความเป็นรูปแบบซิกแซก มันทำหน้าที่เป็น “ตัวชี้” ที่บอกว่าเราควรดึงตัวอักษรจากตำแหน่งใดในข้อความต้นฉบับ การใช้ extractIndex ช่วยให้เราสามารถ:
- เลือกตัวอักษรที่ถูกต้องสำหรับแต่ละตำแหน่งในรูปแบบซิกแซก
- ข้ามตัวอักษรที่ไม่ควรอยู่ในแถวปัจจุบัน
- สร้างรูปแบบซิกแซกโดยไม่ต้องสร้างตารางจริงๆ ซึ่งประหยัดหน่วยความจำ
วิธีการทำงานของ extractIndex
extractIndex = (i == 0 || i == rows - 1) ? extractIndex + rows + 1 : spacer * n + 1;นี่คือส่วนสำคัญที่คำนวณ extractIndex ถัดไป มาดูวิธีการทำงานกัน:
กรณีที่ 1: แถวแรกและแถวสุดท้าย (i == 0 หรือ i == rows - 1)
สำหรับแถวแรกและแถวสุดท้าย เราใช้:
extractIndex = extractIndex + rows + 1- ทำไม? เพราะในแถวแรกและแถวสุดท้าย ตัวอักษรจะห่างกันเท่าๆ กันเสมอ
- ระยะห่างนี้เท่ากับ
rows + 1เพราะ: rowsคือจำนวนแถวทั้งหมด+1เพราะเราต้องนับรวมตัวอักษรในแถวปัจจุบันด้วย
ตัวอย่าง: ถ้า rows = 3 ตัวอักษรในแถวแรกจะห่างกัน 4 ตำแหน่ง (3 + 1)
กรณีที่ 2: แถวกลาง (i ไม่ใช่ 0 และไม่ใช่ rows - 1)
สำหรับแถวกลาง เราใช้:
extractIndex = spacer * n + 1spacer = rows - iคือระยะห่างระหว่างตัวอักษรในแถวนั้นๆnเป็นตัวนับว่าเรากำลังหาตัวอักษรตัวที่เท่าไหร่ในแถวนั้น+1เพื่อปรับให้ตรงกับตำแหน่งจริงในข้อความ (เพราะข้อความเริ่มที่ตำแหน่ง 0)
ทำไมต้องใช้สูตรนี้? เพราะในแถวกลาง ตัวอักษรจะสลับระหว่าง “ลงมา” และ “ขึ้นไป” ในรูปแบบซิกแซก
ตัวอย่างการทำงาน
สมมติว่าเรามีข้อความ “PAYPALISHIRING” และ rows = 3
- แถวที่ 1 (i = 0):
- ตัวอักษร: P _ _ A _ _ H _ _ N
- extractIndex: 0, 4, 8, 12 (ห่างกัน 4 ตำแหน่ง)
- แถวที่ 2 (i = 1):
- ตัวอักษร: A _ P _ L _ S _ I _ G
- extractIndex: 1, 3, 5, 7, 9, 11, 13 (สลับระหว่างห่าง 2 และ 4 ตำแหน่ง)
- แถวที่ 3 (i = 2):
- ตัวอักษร: Y _ _ I _ _ R
- extractIndex: 2, 6, 10 (ห่างกัน 4 ตำแหน่ง)