LeetCode 1527 - Patients With a Condition
The problem asks us to query a database table Patients and return the records of patients who have Type I Diabetes. Each
Difficulty: 🟢 Easy
Topics: Database
Solution
Problem Understanding
The problem asks us to query a database table Patients and return the records of patients who have Type I Diabetes. Each patient record includes a patient_id, patient_name, and a conditions column. The conditions column may contain zero or more condition codes separated by spaces. A patient has Type I Diabetes if any of their condition codes starts with the prefix DIAB1.
In simpler terms, the task is to scan each patient's conditions string, check if at least one word begins with DIAB1, and if so, include that patient in the output. The output should contain the same columns as the input table and can be returned in any order.
Important constraints include that patient_id is unique and conditions may be empty. Edge cases to consider include patients with no conditions, patients whose conditions include similar prefixes like DIAB2, and multiple conditions in a single string.
Approaches
The brute-force approach would involve splitting each patient's conditions string into individual words and checking each word to see if it starts with DIAB1. While simple, this requires scanning every word for every patient and might be inefficient if the dataset is large.
The optimal approach leverages SQL string functions. Specifically, using LIKE with wildcards allows us to detect if DIAB1 appears at the start of a word within the string. By including spaces before and after the condition string (or handling edge positions separately), we can safely match DIAB1 at the start of any word without manually splitting strings.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n * m) | O(1) | Scan each patient and each condition word individually |
| Optimal | O(n) | O(1) | Use SQL pattern matching with LIKE to find DIAB1 prefixed codes |
Algorithm Walkthrough
- Select the columns
patient_id,patient_name, andconditionsfrom thePatientstable. - Use the SQL
WHEREclause to filter only the rows that containDIAB1at the start of a word inconditions. - To ensure we match
DIAB1at word boundaries, we either prepend/append a space to the conditions string or use SQL patterns with wildcards and space characters. - Return the filtered rows.
Why it works: Every patient whose conditions include a word starting with DIAB1 will satisfy the LIKE condition, so the query correctly captures all Type I Diabetes patients. Patients without any matching code are automatically excluded.
Python Solution
# Python solution using SQL execution context
import sqlite3
from typing import List, Tuple
def patients_with_diabetes(conn: sqlite3.Connection) -> List[Tuple[int, str, str]]:
query = """
SELECT patient_id, patient_name, conditions
FROM Patients
WHERE ' ' || conditions || ' ' LIKE '% DIAB1%'
"""
cursor = conn.cursor()
cursor.execute(query)
return cursor.fetchall()
Explanation: We prepend and append a space to conditions so that a match at the beginning or end of the string is handled. The LIKE '% DIAB1%' ensures that DIAB1 is at the start of a word. The function executes the query and returns all matching rows.
Go Solution
package main
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
func PatientsWithDiabetes(db *sql.DB) ([][3]string, error) {
query := `
SELECT patient_id, patient_name, conditions
FROM Patients
WHERE ' ' || conditions || ' ' LIKE '% DIAB1%'
`
rows, err := db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
var result [][3]string
for rows.Next() {
var id int
var name, cond string
if err := rows.Scan(&id, &name, &cond); err != nil {
return nil, err
}
result = append(result, [3]string{string(rune(id)), name, cond})
}
return result, nil
}
Explanation: Go uses the same SQL logic. We use db.Query to execute the query, iterate over the rows, scan values into variables, and append them to a result slice. Integer IDs are converted to string for uniform output handling in the slice.
Worked Examples
Example input:
+------------+--------------+--------------+
| patient_id | patient_name | conditions |
+------------+--------------+--------------+
| 1 | Daniel | YFEV COUGH |
| 2 | Alice | |
| 3 | Bob | DIAB100 MYOP |
| 4 | George | ACNE DIAB100 |
| 5 | Alain | DIAB201 |
+------------+--------------+--------------+
Step 1: Check each patient's conditions string:
- Daniel:
YFEV COUGH→ no word starts withDIAB1→ exclude. - Alice: `` → empty → exclude.
- Bob:
DIAB100 MYOP→DIAB100starts withDIAB1→ include. - George:
ACNE DIAB100→DIAB100starts withDIAB1→ include. - Alain:
DIAB201→ starts withDIAB2→ exclude.
Output:
+------------+--------------+--------------+
| patient_id | patient_name | conditions |
+------------+--------------+--------------+
| 3 | Bob | DIAB100 MYOP |
| 4 | George | ACNE DIAB100 |
+------------+--------------+--------------+
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Each patient row is scanned once by the SQL engine. |
| Space | O(1) | No extra space used aside from query execution. |
This is efficient because the SQL engine performs string matching internally, avoiding manual parsing in application code.
Test Cases
# provided example
assert patients_with_diabetes(conn) == [(3, 'Bob', 'DIAB100 MYOP'), (4, 'George', 'ACNE DIAB100')]
# edge case: no patients
assert patients_with_diabetes(conn_empty) == []
# edge case: all patients have DIAB1
assert patients_with_diabetes(conn_all_diab1) == [
(1, 'Anna', 'DIAB123'),
(2, 'Ben', 'DIAB145 DIAB156')
]
# edge case: DIAB1 appears as substring in another word
assert patients_with_diabetes(conn_substring) == [
(2, 'Ben', 'ACNE DIAB100')
]
| Test | Why |
|---|---|
| Provided example | Validates standard case with mixed patients |
| No patients | Checks function handles empty table |
| All patients have DIAB1 | Confirms all valid matches are included |
| DIAB1 as substring | Ensures matching occurs only at word boundaries |
Edge Cases
One edge case is an empty conditions column. Without careful handling, the LIKE query could fail or include unwanted rows. Prepending and appending spaces ensures that empty strings do not match DIAB1.
Another edge case is a condition code like DIAB12XYZ versus DIAB2. The algorithm correctly only matches codes that start with DIAB1 because LIKE '% DIAB1%' enforces the prefix at word boundaries.
A third edge case is multiple conditions in one string, e.g., ACNE DIAB100 MYOP. The algorithm correctly identifies DIAB100 among other words and includes the patient, demonstrating robustness against multiple-word conditions.