Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Contains Duplicate III ใน C++: หาคู่ค่าที่ใกล้เคียงกันภายในช่วงดัชนีและค่า

โจทย์

กำหนดอาร์เรย์จำนวนเต็ม ตรวจสอบว่ามีดัชนี i และ j ที่ต่างกันทำให้:

  • |nums[i] - nums[j]| <= t (ความต่างค่าสัมบูรณ์ ≤ t)
  • |i - j| <= k (ความต่างดัชนีสัมบูรณ์ ≤ k)

ตัวอย่าง: nums = [1,2,3,1], k = 3, t = 0 → คืน true เพราะ nums[0] และ nums[3] เท่ากันและห่างกัน 3 ดัชนี

แนวคิด: Sliding Window + Ordered Set (multiset)

รักษาช่วงเลื่อนขนาด k ด้วย multiset เพื่อค้นหาค่าที่ใกล้เคียงได้ใน O(log k)

ขั้นตอน

  1. สร้าง multiset<int> s
  2. ลูป i = 0 ถึง n-1:
    • หา x = s.lower_bound(nums[i]) (ค่าแรก ≥ nums[i])
    • ถ้า x != s.end() && *x <= nums[i] + t → คืน true
    • ถ้า x != s.begin() → ตรวจค่าก่อนหน้า prev(x) ว่า *prev(x) + t >= nums[i]
    • เพิ่ม nums[i] ลง set
    • ถ้า i >= k → ลบ nums[i-k] ออก (รักษาขนาดหน้าต่าง)
  3. คืน false ถ้าไม่พบ

ตัวอย่างโค้ด C++

#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        multiset<long long> s; // ใช้ long long ป้องกัน overflow
        int n = nums.size();
        
        for (int i = 0; i < n; i++) {
            auto x = s.lower_bound((long long)nums[i]);
            if (x != s.end() && *x - nums[i] <= t) return true;
            if (x != s.begin()) {
                auto prev_x = prev(x);
                if (nums[i] - *prev_x <= t) return true;
            }
            s.insert(nums[i]);
            if (i >= k) s.erase(s.find(nums[i - k]));
        }
        return false;
    }
};

int main() {
    Solution ob;
    vector<int> v = {1,2,3,1};
    cout << ob.containsNearbyAlmostDuplicate(v, 3, 0); // 1 (true)
    return 0;
}

อินพุต / เอาต์พุต

Input: [1,2,3,1] 3 0

Output: 1 (true)

ความซับซ้อน

  • Time: O(n log k) - แต่ละรอบ insert/erase/lower_bound ใช้ log k
  • Space: O(k) - เก็บได้สูงสุด k องค์ประกอบ