Reason about complexity
Begin with arrays, strings and hash maps. For each solution, describe input size and count the dominant operations. Contrast a nested search with a hash-based lookup, including the memory tradeoff. Test empty input, duplicates and large inputs rather than checking only the happy path.
Learn patterns through examples
Practice two pointers on a sorted array, sliding windows on contiguous ranges and binary search on a monotonic condition. State the invariant that remains true after each step. Avoid choosing a pattern from keywords without checking whether its assumptions hold.
Add linked and hierarchical structures
Implement a stack and queue, then traverse a tree with depth-first and breadth-first approaches. Use a visited set when traversing a graph with cycles. Explain why recursive depth can become a practical limit and when an explicit stack is appropriate.
Connect DSA to application work
Build an autocomplete prototype or dependency traversal tool. Compare a straightforward baseline with your improved approach using the same data. Submit code, tests and complexity notes. DSA supports developer interviews and reasoning, while application skills still require APIs, databases, debugging and projects.
DSA lab: compare duplicate detection approaches
Implement duplicate detection once with a pairwise comparison and once with a set. Use the same test inputs: an empty array, a single value, repeated values at different positions and a long array without duplicates. Explain the dominant operations and extra space in each approach. Measure several runs if you benchmark, and keep input generation separate from timing. A faster result on one tiny input does not prove better asymptotic behaviour.
Check your progress
Keep your working files, test cases and notes together. Explain one design decision, demonstrate a failure case and list what you would improve next. These concrete outputs make it easier to identify the next skill to practice.