Skip to main content

Capital Gain/Loss - Solution & Explanation

MediumDatabase10 min readAsked at: Meta, Robinhood
Practice this problem

Problem Statement

Table: Stocks

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| stock_name    | varchar |
| operation     | enum    |
| operation_day | int     |
| price         | int     |
+---------------+---------+
(stock_name, operation_day) is the primary key (combination of columns with unique values) for this table.
The operation column is an ENUM (category) of type ('Sell', 'Buy')
Each row of this table indicates that the stock which has stock_name had an operation on the day operation_day with the price.
It is guaranteed that each 'Sell' operation for a stock has a corresponding 'Buy' operation in a previous day. It is also guaranteed that each 'Buy' operation for a stock has a corresponding 'Sell' operation in an upcoming day.

 

Write a solution to report the Capital gain/loss for each stock.

The Capital gain/loss of a stock is the total gain or loss after buying and selling the stock one or many times.

Return the result table in any order.

The result format is in the following example.

 

Example 1:

Input: 
Stocks table:
+---------------+-----------+---------------+--------+
| stock_name    | operation | operation_day | price  |
+---------------+-----------+---------------+--------+
| Leetcode      | Buy       | 1             | 1000   |
| Corona Masks  | Buy       | 2             | 10     |
| Leetcode      | Sell      | 5             | 9000   |
| Handbags      | Buy       | 17            | 30000  |
| Corona Masks  | Sell      | 3             | 1010   |
| Corona Masks  | Buy       | 4             | 1000   |
| Corona Masks  | Sell      | 5             | 500    |
| Corona Masks  | Buy       | 6             | 1000   |
| Handbags      | Sell      | 29            | 7000   |
| Corona Masks  | Sell      | 10            | 10000  |
+---------------+-----------+---------------+--------+
Output: 
+---------------+-------------------+
| stock_name    | capital_gain_loss |
+---------------+-------------------+
| Corona Masks  | 9500              |
| Leetcode      | 8000              |
| Handbags      | -23000            |
+---------------+-------------------+
Explanation: 
Leetcode stock was bought at day 1 for 1000$ and was sold at day 5 for 9000$. Capital gain = 9000 - 1000 = 8000$.
Handbags stock was bought at day 17 for 30000$ and was sold at day 29 for 7000$. Capital loss = 7000 - 30000 = -23000$.
Corona Masks stock was bought at day 1 for 10$ and was sold at day 3 for 1010$. It was bought again at day 4 for 1000$ and was sold at day 5 for 500$. At last, it was bought at day 6 for 1000$ and was sold at day 10 for 10000$. Capital gain/loss is the sum of capital gains/losses for each ('Buy' --> 'Sell') operation = (1010 - 10) + (500 - 1000) + (10000 - 1000) = 1000 - 500 + 9000 = 9500$.

Approach Overview

Problem Overview: Each stock has multiple buy and sell operations recorded with a price. The goal is to compute the final capital gain or loss per stock by subtracting the total buy price from the total sell price. The result is returned per stock_name.

Approach 1: Using a Dictionary to Track Buys and Sells (O(n) time, O(n) space)

Iterate through all stock operations and track the running profit for each stock using a hash map. When you see a Buy operation, subtract the price from that stock’s total. When you see a Sell operation, add the price. The key insight: capital gain is simply sum(sell) - sum(buy), so you can update the balance incrementally as you process rows. This avoids storing every transaction and only maintains a single integer per stock. The approach relies on constant-time hash lookups using a hash table, making it efficient for large datasets.

This strategy works well when transaction order does not affect the result and you only care about aggregate profit. Each row is processed exactly once, resulting in O(n) time complexity and O(n) space complexity for the dictionary storing per-stock profit.

Approach 2: Sorting and Calculating Gains/Losses (O(n log n) time, O(1) extra space)

Another approach sorts transactions by stock_name and optionally by operation_day. After sorting, iterate through the records sequentially and accumulate buy and sell totals for the current stock. When the stock changes, compute total_sell - total_buy and store the result before resetting counters for the next stock.

The sorting step groups related transactions together, making the computation straightforward with a single pass afterward. This approach uses a sorting step followed by linear aggregation. Time complexity becomes O(n log n) due to sorting, while the processing pass is O(n). Extra space can remain O(1) if sorting is done in place.

This method is useful when the dataset is not grouped by stock and you want deterministic ordering for processing or debugging. It also mirrors how results would be computed using GROUP BY style aggregation in many database queries.

Recommended for interviews: The dictionary/hash map solution is typically preferred. It demonstrates that you recognized the problem as a simple aggregation and optimized it with constant-time updates. The sorting solution shows solid reasoning but introduces unnecessary overhead compared to the direct hash-based accumulation.

Approach 1: Approach 1: Using a Dictionary to Track Buys and Sells

In this approach, we utilize a dictionary (or map) to store the net capital gain/loss for each stock. We iterate through the provided data, performing operations as follows:
  1. When encountering a 'Buy', simply append the price to a list for that stock.
  2. When encountering a 'Sell', pair it with the earliest 'Buy' found in the list and calculate the gain or loss by subtracting the buy price from the sell price.
  3. Update the total capital gain/loss for that stock in the dictionary.
This approach ensures that we maintain accurate running totals per stock by matching sells with the earliest buys (FIFO - First In, First Out) pattern.
In the Python solution, we create a dictionary `gains` keyed by `stock_name`. Each key holds a list of prices under the `'prices'` key and a running total `'net'` gain/loss. We iterate over each row in the `stocks` list: for each 'Buy' operation, we append the price to the price list; for each 'Sell' operation, we calculate the gain/loss using the first price in the list (FIFO), remove it, and update the net gain/loss.

Code

Python

Java

Complexity

Time Complexity is O(n), where n is the number of rows in the stock table, as we iterate through the list once and perform constant-time operations per row. Space Complexity is O(m), where m is the number of unique stocks in the list, since we maintain a list of prices for each stock.
Try this approach in the editor β†’

Approach 2: Approach 2: Sorting and Calculating Gains/Losses

In this approach, we first sort the operations based on the operation day. Then, we iterate through the sorted list and calculate the cumulative gain/loss for each stock. Here's a step-by-step breakdown:
  1. Sort the operations by `operation_day` to ensure we process the transactions in order.
  2. As we iterate through the sorted list, maintain a running tally of buy and sell transactions per stock.
  3. Use a dictionary to accumulate the total gain/loss for each stock as we encounter sell operations.
This approach benefits from leveraging the sorted order of operations to systematically apply transactions in a straightforward manner.
The C++ solution first utilizes a sorting function `compare` to order the vector of stocks by the `operation_day`. As we iterate through this sorted list, two maps track buy prices and net gains. 'Buy' operations add to a queue, and 'Sell' operations calculate profits by dequeuing the matched buy price, updating the net gains cumulatively. This structure ensures that we handle first-in, first-out price matching efficiently using `std::deque`. After processing, results are collected in a vector for return.

Code

C++

JavaScript

Complexity

Time Complexity is O(n log n) due to the sorting of the stocks by their operation day, followed by O(n) processing time. Space Complexity is O(m) where m refers to the distinct stocks, as we maintain data structures for each stock's price history.
Try this approach in the editor β†’

Approach 3: GROUP BY + SUM(IF())

We use GROUP BY to group the buy and sell operations of the same stock, and then use SUM(IF()) to calculate the capital gains and losses of each stock.

Code

MySQL

Try this approach in the editor β†’

Complexity Comparison

ApproachComplexity
Approach 1: Using a Dictionary to Track Buys and SellsTime Complexity is O(n), where n is the number of rows in the stock table, as we iterate through the list once and perform constant-time operations per row. Space Complexity is O(m), where m is the number of unique stocks in the list, since we maintain a list of prices for each stock.
Approach 2: Sorting and Calculating Gains/LossesTime Complexity is O(n log n) due to the sorting of the stocks by their operation day, followed by O(n) processing time. Space Complexity is O(m) where m refers to the distinct stocks, as we maintain data structures for each stock's price history.
GROUP BY + SUM(IF())β€”

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Dictionary to Track Buys and SellsO(n)O(n)Best general solution when processing transactions directly and aggregating profit per stock
Sorting and AggregationO(n log n)O(1)Useful when transactions must be grouped or processed in sorted order

Video Solution

LeetCode Medium 1393 Interview SQL Question with Detailed Explanation | Practice SQL β€’ Everyday Data Science β€’ 9,342 views views

Watch 9 more video solutions β†’

Frequently Asked Questions

Is Capital Gain/Loss easy or hard?
Capital Gain/Loss is considered a medium difficulty problem mainly because it tests recognition of aggregation logic. Once you realize the result is simply total sells minus total buys per stock, the implementation becomes straightforward with linear time complexity.
Capital Gain/Loss Python/Java solution
Python solutions typically use a dictionary to accumulate profit per stock, updating values during a single pass through the data. Java implementations use a HashMap with the same logic: subtract price for Buy operations and add price for Sell operations.
How to solve Capital Gain/Loss in O(n)?
Maintain a hash map where the key is the stock name and the value is the accumulated profit. For each transaction, subtract the price if the operation is Buy and add the price if it is Sell. After processing all rows, the map directly stores the capital gain or loss for every stock.
What is the best approach for Capital Gain/Loss?
The hash map (dictionary) aggregation approach is the most efficient. Iterate through transactions and update a running balance per stock: subtract prices for Buy operations and add prices for Sell operations. This computes the final capital gain or loss in O(n) time with O(n) space.
Is Capital Gain/Loss asked at Google/Amazon/Meta?
Database aggregation problems like Capital Gain/Loss appear frequently in interviews at companies that test SQL and data processing skills. Variations involving transaction aggregation, profit calculations, and GROUP BY logic are common in backend and data engineering interviews.
What data structure is used in Capital Gain/Loss?
The most common data structure is a hash map (dictionary) keyed by stock name. It allows constant-time updates for each transaction while tracking cumulative buy and sell totals needed to compute the final gain or loss.
What is the time complexity of Capital Gain/Loss?
The optimal solution runs in O(n) time where n is the number of stock transactions. Each record is processed once and updates a hash map entry in constant time. Space complexity is O(n) in the worst case if every transaction belongs to a different stock.

Ready to solve this problem?

Practice Capital Gain/Loss with our built-in code editor and test cases.

Practice on FleetCode