Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
Table: activity
+--------------+---------+ | Column Name | Type | +--------------+---------+ | user_id | int | | action_date | date | | action | varchar | +--------------+---------+ (user_id, action_date, action) is the primary key (unique value) for this table. Each row represents a user performing a specific action on a given date.
Write a solution to identify behaviorally stable users based on the following definition:
5 consecutive days such that:
Return the result table ordered by streak_length in descending order, then by user_id in ascending order.
The result format is in the following example.
Example:
Input:
activity table:
+---------+-------------+--------+ | user_id | action_date | action | +---------+-------------+--------+ | 1 | 2024-01-01 | login | | 1 | 2024-01-02 | login | | 1 | 2024-01-03 | login | | 1 | 2024-01-04 | login | | 1 | 2024-01-05 | login | | 1 | 2024-01-06 | logout | | 2 | 2024-01-01 | click | | 2 | 2024-01-02 | click | | 2 | 2024-01-03 | click | | 2 | 2024-01-04 | click | | 3 | 2024-01-01 | view | | 3 | 2024-01-02 | view | | 3 | 2024-01-03 | view | | 3 | 2024-01-04 | view | | 3 | 2024-01-05 | view | | 3 | 2024-01-06 | view | | 3 | 2024-01-07 | view | +---------+-------------+--------+
Output:
+---------+--------+---------------+------------+------------+ | user_id | action | streak_length | start_date | end_date | +---------+--------+---------------+------------+------------+ | 3 | view | 7 | 2024-01-01 | 2024-01-07 | | 1 | login | 5 | 2024-01-01 | 2024-01-05 | +---------+--------+---------------+------------+------------+
Explanation:
login from 2024-01-01 to 2024-01-05 on consecutive daysclick for only 4 consecutive daysview for 7 consecutive daysThe Results table is ordered by streak_length in descending order, then by user_id in ascending order
Problem summary: Table: activity +--------------+---------+ | Column Name | Type | +--------------+---------+ | user_id | int | | action_date | date | | action | varchar | +--------------+---------+ (user_id, action_date, action) is the primary key (unique value) for this table. Each row represents a user performing a specific action on a given date. Write a solution to identify behaviorally stable users based on the following definition: A user is considered behaviorally stable if there exists a sequence of at least 5 consecutive days such that: The user performed exactly one action per day during that period. The action is the same on all those consecutive days. If a user has multiple qualifying sequences, only consider the sequence with the maximum length. Return the result table ordered by streak_length in descending order, then by user_id in ascending order. The result format is in the following
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: General problem-solving
{"headers":{"activity":["user_id","action_date","action"]},"rows":{"activity":[[1,"2024-01-01","login"],[1,"2024-01-02","login"],[1,"2024-01-03","login"],[1,"2024-01-04","login"],[1,"2024-01-05","login"],[1,"2024-01-06","logout"],[2,"2024-01-01","click"],[2,"2024-01-02","click"],[2,"2024-01-03","click"],[2,"2024-01-04","click"],[3,"2024-01-01","view"],[3,"2024-01-02","view"],[3,"2024-01-03","view"],[3,"2024-01-04","view"],[3,"2024-01-05","view"],[3,"2024-01-06","view"],[3,"2024-01-07","view"]]}}Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3832: Find Users with Persistent Behavior Patterns
// Auto-generated Java example from py.
class Solution {
public void exampleSolution() {
}
}
// Reference (py):
// # Accepted solution for LeetCode #3832: Find Users with Persistent Behavior Patterns
// import pandas as pd
//
//
// def find_behaviorally_stable_users(activity: pd.DataFrame) -> pd.DataFrame:
// activity['action_date'] = pd.to_datetime(activity['action_date'])
//
// # Filter users with only a single action per day
// df = activity.assign(
// cnt=activity.groupby(['user_id', 'action_date'])['action'].transform('count')
// )
// df = df[df['cnt'] == 1].sort_values(['user_id', 'action', 'action_date'])
//
// # Identify consecutive intervals
// df['rn'] = df.groupby(['user_id', 'action'])['action_date'].rank(method='first')
// df['grp'] = df['action_date'] - pd.to_timedelta(df['rn'], unit='D')
//
// # Aggregate streaks
// streaks = (
// df.groupby(['user_id', 'action', 'grp'])
// .agg(
// streak_length=('action_date', 'count'),
// start_date=('action_date', 'min'),
// end_date=('action_date', 'max'),
// )
// .reset_index()
// )
//
// # Filter and get the longest streak for each user
// res = streaks[streaks['streak_length'] >= 5].sort_values(
// ['streak_length', 'user_id'], ascending=[False, True]
// )
//
// return res.groupby('user_id').head(1)[
// ['user_id', 'action', 'streak_length', 'start_date', 'end_date']
// ]
// Accepted solution for LeetCode #3832: Find Users with Persistent Behavior Patterns
// Auto-generated Go example from py.
func exampleSolution() {
}
// Reference (py):
// # Accepted solution for LeetCode #3832: Find Users with Persistent Behavior Patterns
// import pandas as pd
//
//
// def find_behaviorally_stable_users(activity: pd.DataFrame) -> pd.DataFrame:
// activity['action_date'] = pd.to_datetime(activity['action_date'])
//
// # Filter users with only a single action per day
// df = activity.assign(
// cnt=activity.groupby(['user_id', 'action_date'])['action'].transform('count')
// )
// df = df[df['cnt'] == 1].sort_values(['user_id', 'action', 'action_date'])
//
// # Identify consecutive intervals
// df['rn'] = df.groupby(['user_id', 'action'])['action_date'].rank(method='first')
// df['grp'] = df['action_date'] - pd.to_timedelta(df['rn'], unit='D')
//
// # Aggregate streaks
// streaks = (
// df.groupby(['user_id', 'action', 'grp'])
// .agg(
// streak_length=('action_date', 'count'),
// start_date=('action_date', 'min'),
// end_date=('action_date', 'max'),
// )
// .reset_index()
// )
//
// # Filter and get the longest streak for each user
// res = streaks[streaks['streak_length'] >= 5].sort_values(
// ['streak_length', 'user_id'], ascending=[False, True]
// )
//
// return res.groupby('user_id').head(1)[
// ['user_id', 'action', 'streak_length', 'start_date', 'end_date']
// ]
# Accepted solution for LeetCode #3832: Find Users with Persistent Behavior Patterns
import pandas as pd
def find_behaviorally_stable_users(activity: pd.DataFrame) -> pd.DataFrame:
activity['action_date'] = pd.to_datetime(activity['action_date'])
# Filter users with only a single action per day
df = activity.assign(
cnt=activity.groupby(['user_id', 'action_date'])['action'].transform('count')
)
df = df[df['cnt'] == 1].sort_values(['user_id', 'action', 'action_date'])
# Identify consecutive intervals
df['rn'] = df.groupby(['user_id', 'action'])['action_date'].rank(method='first')
df['grp'] = df['action_date'] - pd.to_timedelta(df['rn'], unit='D')
# Aggregate streaks
streaks = (
df.groupby(['user_id', 'action', 'grp'])
.agg(
streak_length=('action_date', 'count'),
start_date=('action_date', 'min'),
end_date=('action_date', 'max'),
)
.reset_index()
)
# Filter and get the longest streak for each user
res = streaks[streaks['streak_length'] >= 5].sort_values(
['streak_length', 'user_id'], ascending=[False, True]
)
return res.groupby('user_id').head(1)[
['user_id', 'action', 'streak_length', 'start_date', 'end_date']
]
// Accepted solution for LeetCode #3832: Find Users with Persistent Behavior Patterns
// Rust example auto-generated from py reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (py):
// # Accepted solution for LeetCode #3832: Find Users with Persistent Behavior Patterns
// import pandas as pd
//
//
// def find_behaviorally_stable_users(activity: pd.DataFrame) -> pd.DataFrame:
// activity['action_date'] = pd.to_datetime(activity['action_date'])
//
// # Filter users with only a single action per day
// df = activity.assign(
// cnt=activity.groupby(['user_id', 'action_date'])['action'].transform('count')
// )
// df = df[df['cnt'] == 1].sort_values(['user_id', 'action', 'action_date'])
//
// # Identify consecutive intervals
// df['rn'] = df.groupby(['user_id', 'action'])['action_date'].rank(method='first')
// df['grp'] = df['action_date'] - pd.to_timedelta(df['rn'], unit='D')
//
// # Aggregate streaks
// streaks = (
// df.groupby(['user_id', 'action', 'grp'])
// .agg(
// streak_length=('action_date', 'count'),
// start_date=('action_date', 'min'),
// end_date=('action_date', 'max'),
// )
// .reset_index()
// )
//
// # Filter and get the longest streak for each user
// res = streaks[streaks['streak_length'] >= 5].sort_values(
// ['streak_length', 'user_id'], ascending=[False, True]
// )
//
// return res.groupby('user_id').head(1)[
// ['user_id', 'action', 'streak_length', 'start_date', 'end_date']
// ]
// Accepted solution for LeetCode #3832: Find Users with Persistent Behavior Patterns
// Auto-generated TypeScript example from py.
function exampleSolution(): void {
}
// Reference (py):
// # Accepted solution for LeetCode #3832: Find Users with Persistent Behavior Patterns
// import pandas as pd
//
//
// def find_behaviorally_stable_users(activity: pd.DataFrame) -> pd.DataFrame:
// activity['action_date'] = pd.to_datetime(activity['action_date'])
//
// # Filter users with only a single action per day
// df = activity.assign(
// cnt=activity.groupby(['user_id', 'action_date'])['action'].transform('count')
// )
// df = df[df['cnt'] == 1].sort_values(['user_id', 'action', 'action_date'])
//
// # Identify consecutive intervals
// df['rn'] = df.groupby(['user_id', 'action'])['action_date'].rank(method='first')
// df['grp'] = df['action_date'] - pd.to_timedelta(df['rn'], unit='D')
//
// # Aggregate streaks
// streaks = (
// df.groupby(['user_id', 'action', 'grp'])
// .agg(
// streak_length=('action_date', 'count'),
// start_date=('action_date', 'min'),
// end_date=('action_date', 'max'),
// )
// .reset_index()
// )
//
// # Filter and get the longest streak for each user
// res = streaks[streaks['streak_length'] >= 5].sort_values(
// ['streak_length', 'user_id'], ascending=[False, True]
// )
//
// return res.groupby('user_id').head(1)[
// ['user_id', 'action', 'streak_length', 'start_date', 'end_date']
// ]
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.