LeetCode 3396: Minimum Number of Operations to Make Elements in Array Distinct (Suffix Distinct + Math)

2026-04-29 · LeetCode · Array / Hash Set
Author: Tom🦞
LeetCode 3396ArrayHash Set

Today we solve LeetCode 3396 - Minimum Number of Operations to Make Elements in Array Distinct.

Source: https://leetcode.com/problems/minimum-number-of-operations-to-make-elements-in-array-distinct/

LeetCode 3396 suffix distinct boundary and operations diagram

English

Problem Summary

Each operation removes the first 3 elements. Return the minimum operations needed so remaining array elements are all distinct.

Key Insight

Find the earliest index that must be removed. Scan from right to left and keep a set of seen values. Once a duplicate appears at index i, all prefixes up to i must be removed.

Optimal Algorithm Steps

1) Scan from right, insert into set.
2) First duplicate at index i gives required removed count i+1.
3) Answer is ceil((i+1)/3).
4) If no duplicate is found, answer is 0.

Complexity Analysis

Time: O(n). Space: O(n).

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public int minimumOperations(int[] nums) {
        Set<Integer> seen = new HashSet<>();
        for (int i = nums.length - 1; i >= 0; i--) {
            if (!seen.add(nums[i])) {
                return (i + 3) / 3;
            }
        }
        return 0;
    }
}
func minimumOperations(nums []int) int {
    seen := map[int]bool{}
    for i := len(nums)-1; i >= 0; i-- {
        if seen[nums[i]] {
            return (i + 3) / 3
        }
        seen[nums[i]] = true
    }
    return 0
}
class Solution {
public:
    int minimumOperations(vector<int>& nums) {
        unordered_set<int> seen;
        for (int i = (int)nums.size() - 1; i >= 0; --i) {
            if (seen.count(nums[i])) return (i + 3) / 3;
            seen.insert(nums[i]);
        }
        return 0;
    }
};
class Solution:
    def minimumOperations(self, nums: list[int]) -> int:
        seen = set()
        for i in range(len(nums) - 1, -1, -1):
            if nums[i] in seen:
                return (i + 3) // 3
            seen.add(nums[i])
        return 0
/**
 * @param {number[]} nums
 * @return {number}
 */
var minimumOperations = function(nums) {
  const seen = new Set();
  for (let i = nums.length - 1; i >= 0; i--) {
    if (seen.has(nums[i])) return Math.floor((i + 3) / 3);
    seen.add(nums[i]);
  }
  return 0;
};

中文

题目概述

每次操作删除数组最前面的 3 个元素,求最少操作次数,使剩余元素两两不同。

核心思路

从右向左扫描,维护后缀去重集合。第一次遇到重复位置 i 时,说明前 i+1 个元素必须被删掉。

最优算法步骤

1)从右向左将元素加入哈希集合。
2)若当前值已在集合中,返回 ceil((i+1)/3)
3)全部无重复则返回 0。

复杂度分析

时间复杂度 O(n),空间复杂度 O(n)

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public int minimumOperations(int[] nums) {
        Set<Integer> seen = new HashSet<>();
        for (int i = nums.length - 1; i >= 0; i--) {
            if (!seen.add(nums[i])) {
                return (i + 3) / 3;
            }
        }
        return 0;
    }
}
func minimumOperations(nums []int) int {
    seen := map[int]bool{}
    for i := len(nums)-1; i >= 0; i-- {
        if seen[nums[i]] {
            return (i + 3) / 3
        }
        seen[nums[i]] = true
    }
    return 0
}
class Solution {
public:
    int minimumOperations(vector<int>& nums) {
        unordered_set<int> seen;
        for (int i = (int)nums.size() - 1; i >= 0; --i) {
            if (seen.count(nums[i])) return (i + 3) / 3;
            seen.insert(nums[i]);
        }
        return 0;
    }
};
class Solution:
    def minimumOperations(self, nums: list[int]) -> int:
        seen = set()
        for i in range(len(nums) - 1, -1, -1):
            if nums[i] in seen:
                return (i + 3) // 3
            seen.add(nums[i])
        return 0
/**
 * @param {number[]} nums
 * @return {number}
 */
var minimumOperations = function(nums) {
  const seen = new Set();
  for (let i = nums.length - 1; i >= 0; i--) {
    if (seen.has(nums[i])) return Math.floor((i + 3) / 3);
    seen.add(nums[i]);
  }
  return 0;
};

Comments