← Back to blog ZipRecruiter OA Experience Review: New Grad SWE 2026 | Algorithm + System Design
ZipRecruiter

ZipRecruiter OA Experience Review: New Grad SWE 2026 | Algorithm + System Design

2026-05-12

ZipRecruiter is a leading online employment marketplace connecting millions of job seekers with employers. Their SWE OA tests standard algorithm skills with a focus on string processing, matching algorithms, and data structure design — reflecting the core challenges of building a job recommendation platform.

OA Overview

Aspect Details
Platform HackerRank
Duration 90 minutes
Questions 3 coding problems
Difficulty Easy-Medium
Focus Strings, Arrays, Graphs, Matching

Question Type 1: String Matching & Processing

Problem: Resume Keyword Matcher

Given a job description with required keywords and a list of resumes, rank resumes by keyword match score.

def rank_resumes(job_keywords, resumes):
    """
    job_keywords: list of required keywords (case-insensitive)
    resumes: list of (resume_id, resume_text)
    Returns: list of (resume_id, score) sorted by score desc
    """
    results = []
    keywords_lower = set(k.lower() for k in job_keywords)
    
    for resume_id, text in resumes:
        words = set(text.lower().split())
        score = len(keywords_lower & words)
        results.append((resume_id, score))
    
    results.sort(key=lambda x: (-x[1], x[0]))
    return results

Problem: Job Title Normalization

Normalize job titles by removing common suffixes and mapping abbreviations.

def normalize_titles(titles):
    abbreviations = {
        'sr': 'senior', 'jr': 'junior', 'mgr': 'manager',
        'eng': 'engineer', 'dev': 'developer', 'swe': 'software engineer'
    }
    suffixes_to_remove = ['i', 'ii', 'iii', 'iv', 'v']
    
    normalized = []
    for title in titles:
        words = title.lower().strip().split()
        
        # Remove level suffixes
        while words and words[-1] in suffixes_to_remove:
            words.pop()
        
        # Expand abbreviations
        words = [abbreviations.get(w, w) for w in words]
        
        normalized.append(' '.join(words))
    
    return normalized

Question Type 2: Graph-Based Recommendation

Problem: Job Recommendation via Skill Graph

Build a skill-based recommendation system. If a user has skills A and B, and job X requires skills A, B, C — recommend jobs where the user matches at least 70% of required skills.

from collections import defaultdict

def recommend_jobs(user_skills, jobs, threshold=0.7):
    """
    user_skills: set of skills the user has
    jobs: list of (job_id, required_skills_set)
    threshold: minimum match ratio
    """
    recommendations = []
    
    for job_id, required_skills in jobs:
        if not required_skills:
            continue
        
        match_count = len(user_skills & required_skills)
        match_ratio = match_count / len(required_skills)
        
        if match_ratio >= threshold:
            recommendations.append({
                'job_id': job_id,
                'match_ratio': match_ratio,
                'missing_skills': required_skills - user_skills
            })
    
    recommendations.sort(key=lambda x: -x['match_ratio'])
    return recommendations

Problem: Company Connection Graph

Find the shortest path between two companies through shared employees (people who worked at both).

from collections import deque, defaultdict

def shortest_company_path(employees, company_a, company_b):
    """
    employees: list of (employee_id, [company1, company2, ...])
    Find shortest connection path between company_a and company_b
    """
    graph = defaultdict(set)
    
    for emp_id, companies in employees:
        for i in range(len(companies)):
            for j in range(i + 1, len(companies)):
                graph[companies[i]].add(companies[j])
                graph[companies[j]].add(companies[i])
    
    # BFS
    queue = deque([(company_a, [company_a])])
    visited = {company_a}
    
    while queue:
        current, path = queue.popleft()
        
        if current == company_b:
            return path
        
        for neighbor in graph[current]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append((neighbor, path + [neighbor]))
    
    return []

Question Type 3: Data Structure Design

Problem: Job Application Tracker

Design a system to track job applications with status updates and analytics.

from collections import defaultdict
from datetime import datetime

class ApplicationTracker:
    def __init__(self):
        self.applications = {}
        self.user_apps = defaultdict(list)
        self.company_apps = defaultdict(list)
        self.app_id = 0
    
    def apply(self, user_id, company_id, job_id, timestamp):
        self.app_id += 1
        app = {
            'id': self.app_id,
            'user_id': user_id,
            'company_id': company_id,
            'job_id': job_id,
            'status': 'APPLIED',
            'applied_at': timestamp,
            'history': [('APPLIED', timestamp)]
        }
        self.applications[self.app_id] = app
        self.user_apps[user_id].append(self.app_id)
        self.company_apps[company_id].append(self.app_id)
        return self.app_id
    
    def update_status(self, app_id, new_status, timestamp):
        if app_id not in self.applications:
            return False
        self.applications[app_id]['status'] = new_status
        self.applications[app_id]['history'].append((new_status, timestamp))
        return True
    
    def get_user_stats(self, user_id):
        apps = [self.applications[aid] for aid in self.user_apps[user_id]]
        stats = defaultdict(int)
        for app in apps:
            stats[app['status']] += 1
        return dict(stats)
    
    def get_response_rate(self, company_id):
        apps = [self.applications[aid] for aid in self.company_apps[company_id]]
        if not apps:
            return 0.0
        responded = sum(1 for a in apps if a['status'] != 'APPLIED')
        return responded / len(apps)

Preparation Tips


FAQ

How difficult is the ZipRecruiter OA?

ZipRecruiter OA is on the easier side — mostly LeetCode Easy to Medium. The focus is on writing clean, correct code rather than complex algorithms. Good for candidates who prefer practical problems over competitive programming.

What is ZipRecruiter's full interview process?

Typical flow: OA → Technical Phone Screen (1 round) → Onsite (3-4 rounds including coding, system design, and behavioral). The process is relatively fast, usually 3-4 weeks total.

What tech stack does ZipRecruiter use?

ZipRecruiter primarily uses Python, Ruby on Rails, and React. Backend services use microservices architecture. ML/recommendation systems are a core part of the platform.

What's the compensation for ZipRecruiter New Grad?

New Grad SWE total compensation is typically $130K-$170K (base + bonus + equity), depending on location and experience.


Preparing for ZipRecruiter OA?

oavoservice provides professional OA/VO assistance for tech companies of all sizes.

👉 Contact WeChat: Coding0201 | Get assistance


Contact

Email: [email protected]
Telegram: @OAVOProxy