บทความนี้แสดงวิธีการ Reverse (ย้อนกลับ) อาร์เรย์/ลิสต์ แค่ส่วนแรกจนถึงตำแหน่งที่กำหนด เช่น กำหนด n=5 ให้ย้อนกลับ Index 0-4 เท่านั้น ส่วนที่เหลือคงเดิม
โจทย์
Input: arr = [1, 2, 3, 4, 5, 6, 7, 8, 9], n = 5 Output: [5, 4, 3, 2, 1, 6, 7, 8, 9]
วิธีที่ 1: Two-Pointer Swap (Classic Algorithm)
สลับค่าระหว่าง Index i และ n-i-1 จนถึงกึ่งกลาง
def reverse_up_to(arr, n):
# ตรวจสอบเงื่อนไข
if n > len(arr) or n <= 0:
raise ValueError(f"n ต้องอยู่ระหว่าง 1 ถึง {len(arr)}")
# สลับค่า Two-pointer
for i in range(n // 2):
arr[i], arr[n - i - 1] = arr[n - i - 1], arr[i]
return arr
# ทดสอบ
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(reverse_up_to(arr, 5)) # [5, 4, 3, 2, 1, 6, 7, 8, 9]
วิธีที่ 2: Python Slicing (Pythonic Way)
ใช้ Slicing [n-1::-1] (ย้อนกลับจาก n-1 ถึง 0) + [n:] (ส่วนที่เหลือ)
def reverse_up_to_slicing(arr, n):
if n > len(arr) or n <= 0:
raise ValueError(f"n ต้องอยู่ระหว่าง 1 ถึง {len(arr)}")
# arr[n-1::-1] = จาก index n-1 ถึง 0 (step -1)
# arr[n:] = จาก index n ถึงสุด
return arr[n-1::-1] + arr[n:]
# ทดสอบ
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(reverse_up_to_slicing(arr, 5)) # [5, 4, 3, 2, 1, 6, 7, 8, 9]
วิธีที่ 3: ใช้ reversed() และ itertools.chain
from itertools import chain
def reverse_up_to_itertools(arr, n):
if n > len(arr) or n <= 0:
raise ValueError(f"n ต้องอยู่ระหว่าง 1 ถึง {len(arr)}")
return list(chain(reversed(arr[:n]), arr[n:]))
การทดสอบกรณีขอบ (Edge Cases)
# ทดสอบกรณีต่างๆ
test_cases = [
([1,2,3,4,5], 1), # n=1: ไม่เปลี่ยนแปลง
([1,2,3,4,5], 5), # n=len: ย้อนทั้งลิสต์
([1,2,3,4,5], 3), # n=3: ย้อน 3 ตัวแรก
([], 0), # Empty list
]
for arr, n in test_cases:
try:
result = reverse_up_to_slicing(arr.copy(), n)
print(f"arr={arr}, n={n} -> {result}")
except ValueError as e:
print(f"arr={arr}, n={n} -> Error: {e}")
ผลลัพธ์
arr=[1, 2, 3, 4, 5], n=1 -> [1, 2, 3, 4, 5] arr=[1, 2, 3, 4, 5], n=5 -> [5, 4, 3, 2, 1] arr=[1, 2, 3, 4, 5], n=3 -> [3, 2, 1, 4, 5] arr=[], n=0 -> Error: n ต้องอยู่ระหว่าง 1 ถึง 0
Complexity Analysis
| วิธี | Time Complexity | Space Complexity | In-place? |
|---|---|---|---|
| Two-Pointer Swap | O(n) | O(1) | ✅ ใช่ |
| Slicing | O(n) | O(n) | ❌ ไม่ (สร้างลิสต์ใหม่) |
| itertools.chain | O(n) | O(n) | ❌ ไม่ |
สรุป
- In-place (ประหยัดหน่วยความจำ): ใช้ Two-Pointer Swap
- Pythonic/สั้นที่สุด: ใช้ Slicing
arr[n-1::-1] + arr[n:] - Functional Style: ใช้
itertools.chain(reversed(arr[:n]), arr[n:])