ให้อาร์เรย์ nums เรียงจากน้อยไปมาก ต้องการตรวจสอบว่าสามารถแบ่งเป็น 1 หรือหลาย subsequences ได้หรือไม่ โดยแต่ละ subsequence ต้องเป็นจำนวนเต็มต่อเนื่องและมีความยาวอย่างน้อย 3
ตัวอย่าง: [1,2,3,3,4,4,5,5] → true เพราะแบ่งได้เป็น [1,2,3,4,5] และ [3,4,5]
วิธีแก้ปัญหา (Greedy + Hash Map)
- สร้าง map m เก็บความถี่ของแต่ละตัวเลขใน nums
- กำหนด cnt = ขนาดของ nums
- วนลูปทุกตัวเลข x ใน nums:
- ถ้า m[x], m[x+1], m[x+2] ทั้งหมด > 0:
- ลด m[x], m[x+1], m[x+2] ลง 1
- เพิ่ม x ขึ้น 3, ลด cnt ลง 3
- ขยาย subsequence: while m[x] > 0 และ m[x] > m[x-1]: ลด m[x], เพิ่ม x, ลด cnt
- ถ้า m[x], m[x+1], m[x+2] ทั้งหมด > 0:
- คืนค่า true ถ้า cnt = 0 มิฉะนั้น false
ตัวอย่างโค้ด C++
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
bool isPossible(vector<int>& nums) {
unordered_map<int, int> m;
int n = nums.size();
for (int i = 0; i < n; i++) m[nums[i]]++;
int cnt = n;
for (int i = 0; i < n; i++) {
int x = nums[i];
if (m[x] && m[x + 1] && m[x + 2]) {
m[x]--; m[x + 1]--; m[x + 2]--;
x += 3; cnt -= 3;
while (m[x] > 0 && m[x] > m[x - 1]) {
cnt--; m[x]--; x++;
}
}
}
return cnt == 0;
}
};
int main() {
vector<int> v = {1,2,3,3,4,4,5,5};
Solution ob;
cout << ob.isPossible(v);
return 0;
}
Input
[1,2,3,3,4,4,5,5]
Output
1