โจทย์: กำหนดอาร์เรย์ A หา permutation ที่เล็กกว่า A น้อยที่สุด (lexicographically largest but smaller) ที่ทำได้ด้วยการสลับ 2 ตัวเลขครั้งเดียว หาไม่ได้คืนค่าเดิม
ตัวอย่าง
Input: [3,2,1]
Output: [3,1,2] (สลับ 2 และ 1)
อัลกอริทึม
- หา
leftตัวสุดท้ายที่ A[left] > A[left+1] (scan จากขวา) - หา
rightตัวที่ A[right] < A[left] และมากที่สุด (closest smaller) - สลับ A[left] และ A[right]
ตัวอย่างโค้ด Python
class Solution(object):
def prevPermOpt1(self, A):
n = len(A)
# หา left: จุดที่เริ่มลดลงจากขวา
left = -1
for i in range(n - 2, -1, -1):
if A[i] > A[i + 1]:
left = i
break
if left == -1:
return A # เรียงเพิ่มอยู่แล้ว ไม่มี permutation ก่อนหน้า
# หา right: ค่าที่ < A[left] และมากที่สุด
max_val = -1
right = -1
for i in range(left + 1, n):
if A[i] < A[left] and A[i] > max_val:
max_val = A[i]
right = i
# สลับ
A[left], A[right] = A[right], A[left]
return A
# ทดสอบ
ob = Solution()
print(ob.prevPermOpt1([4,2,3,1,3])) # Output: [4, 2, 1, 3, 3]
ตัวอย่าง Input/Output
Input: [4,2,3,1,3] Output: [4, 2, 1, 3, 3]
ความซับซ้อน: Time O(n), Space O(1)