0Pricing
Coding Interview Prep · Pelajaran

Mendeteksi Hari Kalender yang Berurutan

Gunakan aritmetika tanggal dan nomor baris untuk menemukan rangkaian hari tanpa jeda.

Mendeteksi Hari Kalender yang Berurutan adalah pelajaran Coding Interview Prep gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Coding Interview Prep, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Coding Interview Prep mencakup 4 pelajaran total.

Persiapan Wawancara

Pewawancara menyukai pertanyaan tentang rentetan karena pertanyaan ini menunjukkan apakah Anda benar-benar memahami fungsi jendela dan aritmetika tanggal. Pertanyaan yang umum: "Diberikan tabel berisi tanggal pengguna masuk, temukan setiap rentetan tak terputus dari hari-hari kalender yang berurutan."

Intuisi naifnya adalah menggunakan gabungan mandiri yang membandingkan setiap baris dengan baris berikutnya, tetapi cara ini menjadi sangat berat pada tabel besar dan sulit dituliskan. Jawaban profesionalnya menggunakan teknik celah dan kelompok. Dalam pelajaran ini, Anda akan belajar mendeteksi hari-hari berurutan dengan rapi menggunakan nomor baris dan pengurangan tanggal.

Data Contoh

Sepanjang pelajaran ini, kita menggunakan tabel logins dengan satu baris untuk setiap pengguna pada setiap hari saat mereka aktif. Duplikasi diasumsikan sudah dihapus (satu kali masuk per hari kalender).

  • user_id — pengguna yang masuk
  • login_date — nilai DATE

Untuk pengguna 1, tanggalnya adalah 1, 2, dan 3 Jan, lalu ada jeda, kemudian 6 dan 7 Jan. Kita mengharapkan dua rentetan: rentetan 3 hari dan rentetan 2 hari.

SELECT * FROM logins ORDER BY user_id, login_date;
-- user_id | login_date
--    1    | 2024-01-01
--    1    | 2024-01-02
--    1    | 2024-01-03
--    1    | 2024-01-06
--    1    | 2024-01-07

Wawasan Inti

Inilah trik yang membuka jalan untuk menyelesaikan setiap masalah hari-hari berurutan. Jika Anda mengurutkan baris berdasarkan tanggal dan memberikan masing-masing nomor baris berurutan, maka dalam setiap rentetan hari berurutan, selisih antara tanggal dan nomor baris tetap konstan.

Mengapa? Baik tanggal maupun nomor baris bertambah tepat 1 pada setiap hari yang berurutan, sehingga selisihnya tidak berubah. Saat muncul jeda, tanggal melompat tetapi nomor baris tidak—nilai konstan pun berubah dan kelompok baru dimulai.

Melihat Perbedaannya

Mari kita telusur secara manual untuk pengguna 1. ROW_NUMBER menghitung 1, 2, 3, 4, 5. Kurangkan nomor baris (dalam satuan hari) dari tanggal, lalu amati hasilnya.

  • 1 Jan − 1 = 31 Des
  • 2 Jan − 2 = 31 Des
  • 3 Jan − 3 = 31 Des
  • 6 Jan − 4 = 2 Jan
  • 7 Jan − 5 = 2 Jan

Tiga baris pertama memiliki nilai 31 Des yang sama; dua baris terakhir memiliki nilai 2 Jan yang sama. Nilai jangkar yang sama itu adalah kunci kelompok kita.

Menambahkan ROW_NUMBER

Langkah konkret pertama adalah menambahkan nomor baris, yang dipartisi per pengguna agar rentetan tidak pernah melewati batas pengguna, lalu diurutkan berdasarkan tanggal.

PARTITION BY user_id mengulang penghitung untuk setiap pengguna; ORDER BY login_date memastikan urutannya mengikuti kalender.

SELECT
  user_id,
  login_date,
  ROW_NUMBER() OVER (
    PARTITION BY user_id
    ORDER BY login_date
  ) AS rn
FROM logins;

Menghitung Jangkar Kelompok

Sekarang kurangkan rn hari dari login_date. Dalam PostgreSQL, Anda dapat langsung mengurangkan jumlah hari berupa bilangan bulat dari suatu tanggal. Hasilnya adalah jangkar konstan yang mengidentifikasi setiap kelompok.

Perhatikan bahwa kita tidak dapat merujuk alias rn dalam SELECT yang sama dengan tempat alias itu didefinisikan—jadi kita harus terlebih dahulu membungkus kueri sebelumnya dalam CTE atau subkueri.

WITH numbered AS (
  SELECT
    user_id,
    login_date,
    ROW_NUMBER() OVER (
      PARTITION BY user_id ORDER BY login_date
    ) AS rn
  FROM logins
)
SELECT
  user_id,
  login_date,
  login_date - rn AS grp
FROM numbered;

Mengelompokkan Kelompok

Dengan adanya jangkar, setiap rentetan berurutan memiliki nilai grp yang sama. Kelompokkan berdasarkan user_id dan grp, lalu lakukan agregasi untuk mendapatkan awal, akhir, dan panjang setiap rentetan.

  • MIN(login_date) — hari pertama rentetan
  • MAX(login_date) — hari terakhir rentetan
  • COUNT(*) — jumlah hari dalam rentetan
WITH numbered AS (
  SELECT user_id, login_date,
    ROW_NUMBER() OVER (
      PARTITION BY user_id ORDER BY login_date
    ) AS rn
  FROM logins
)
SELECT
  user_id,
  MIN(login_date) AS streak_start,
  MAX(login_date) AS streak_end,
  COUNT(*)        AS streak_len
FROM numbered
GROUP BY user_id, login_date - rn
ORDER BY user_id, streak_start;

Perbedaan Dialek

Sintaks aritmetika tanggal berbeda-beda. Sebutkan hal ini dalam wawancara untuk menunjukkan keluasan pemahaman Anda.

  • PostgreSQL: login_date - rn (tanggal dikurangi jumlah hari berupa bilangan bulat)
  • MySQL: DATE_SUB(login_date, INTERVAL rn DAY)
  • SQL Server: DATEADD(day, -rn, login_date)

Logikanya identik; hanya nama fungsinya yang berubah. Model mental portabelnya adalah "geser setiap tanggal mundur berdasarkan posisinya sehingga rentetan yang rapi menyusut menjadi satu nilai konstan."

-- SQL Server version of the anchor
DATEADD(day, -1 * rn, login_date) AS grp

Mengapa Bukan Gabungan Mandiri?

Pewawancara mungkin bertanya mengapa Anda menghindari gabungan mandiri seperti l1.login_date = l2.login_date + 1. Alasan yang dapat Anda berikan:

  • Gabungan mandiri hanya menguji kedekatan, bukan rentetan lengkap—untuk menyusun rentetan utuh tetap diperlukan pengelompokan.
  • Gabungan ini dapat menghasilkan percabangan baris dan memiliki kompleksitas O(n²) tanpa indeks yang baik.
  • Metode nomor baris melakukan satu lintasan berurutan dan jauh lebih mudah diskalakan.

Fungsi jendela merupakan jawaban modern yang diharapkan untuk masalah seperti ini.

Melindungi dari Duplikasi

Seluruh teknik ini mengasumsikan satu baris per pengguna per hari. Jika sumber data memiliki beberapa kali masuk dalam sehari, dua baris pada tanggal yang sama akan mendapatkan nomor baris berbeda, sehingga jangkar menjadi rusak.

Atasi hal ini dengan menghapus duplikasi terlebih dahulu—ubah stempel waktu menjadi tanggal dan gunakan DISTINCT, atau gunakan DENSE_RANK pada tanggal alih-alih ROW_NUMBER agar tanggal yang sama memiliki nomor yang sama.

WITH days AS (
  SELECT DISTINCT user_id, login_ts::date AS login_date
  FROM raw_logins
)
SELECT * FROM days;

Solusi Lengkap

Dengan menggabungkan semua bagian, kita mendapatkan jawaban yang rapi dan siap digunakan dalam wawancara, yang mencantumkan setiap rentetan hari berurutan beserta awal, akhir, dan panjangnya.

Kerangka yang sama—hapus duplikasi, beri nomor, kurangkan, kelompokkan—menyelesaikan hampir semua pertanyaan tentang hari-hari berurutan yang mungkin diberikan kepada Anda.

WITH days AS (
  SELECT DISTINCT user_id, login_ts::date AS login_date
  FROM raw_logins
),
numbered AS (
  SELECT user_id, login_date,
    ROW_NUMBER() OVER (
      PARTITION BY user_id ORDER BY login_date
    ) AS rn
  FROM days
)
SELECT user_id,
  MIN(login_date) AS streak_start,
  MAX(login_date) AS streak_end,
  COUNT(*)        AS streak_len
FROM numbered
GROUP BY user_id, login_date - rn
ORDER BY user_id, streak_start;

Pemeriksaan Singkat

Uji pemahaman Anda tentang trik inti ini.

Rangkuman

Anda telah mempelajari pola dasar hari-hari berurutan:

  • Hapus duplikasi hingga tersisa satu baris per pengguna per hari.
  • ROW_NUMBER yang diurutkan berdasarkan tanggal dan dipartisi berdasarkan pengguna.
  • Kurangkan nomor baris dari tanggal untuk mendapatkan jangkar konstan per rentetan.
  • GROUP BY jangkar tersebut dan lakukan agregasi untuk mendapatkan awal, akhir, dan panjang.

Kerangka celah dan kelompok ini dapat diskalakan dalam satu lintasan dan mengungguli gabungan mandiri. Berikutnya, Anda akan menggunakannya untuk menghitung rentetan terpanjang per pengguna.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Mendeteksi Hari Kalender yang Berurutan” gratis?

Ya — teks lengkap “Mendeteksi Hari Kalender yang Berurutan” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Coding Interview Prep, upgrade ke CoddyKit PRO. Kursus Coding Interview Prep mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Mendeteksi Hari Kalender yang Berurutan”?

Gunakan aritmetika tanggal dan nomor baris untuk menemukan rangkaian hari tanpa jeda. Kamu berlatih Coding Interview Prep dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Coding Interview Prep?

Tidak diperlukan pengalaman sebelumnya. Coding Interview Prep di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.

Berapa lama pelajaran “Mendeteksi Hari Kalender yang Berurutan” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Coding Interview Prep ini?

Ya. Setiap pelajaran Coding Interview Prep menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Mendeteksi Hari Kalender yang Berurutan
  2. Rangkaian Terpanjang per Pengguna
  3. N Baris Berturut-turut yang Memenuhi Kondisi
  4. Rangkaian Aktif Saat Ini hingga Hari Ini
← Kembali ke Coding Interview Prep