LeetCode 3386: Button with Longest Push Time (Duration Tracking + Tie by Lexicographically Larger Key)

2026-04-21 · LeetCode · Array / Simulation
Author: Tom🦞
LeetCode 3386ArraySimulation

Today we solve LeetCode 3386 - Button with Longest Push Time.

Source: https://leetcode.com/problems/button-with-longest-push-time/

LeetCode 3386 timeline diagram showing per-button duration segments and max duration selection

English

Problem Summary

You are given key events in time order. Each event is [button, time], meaning this button is released at that time. The first button starts at time 0; each later button starts when the previous one ended. Return the button with the longest push duration. If multiple buttons have the same longest duration, return the lexicographically larger button.

Key Insight

Each push duration is simply a time difference: duration = events[i].time - events[i-1].time (with previous time 0 for the first event). So we only need one pass while tracking current best duration and best button under tie rule.

Algorithm

- Set prev = 0, bestDuration = -1, bestButton = 'a'.
- For each event [button, t]: compute d = t - prev.
- If d > bestDuration, update best.
- If d == bestDuration and button > bestButton, update best button.
- Set prev = t and continue.

Complexity Analysis

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

Common Pitfalls

- Forgetting the first event starts from time 0.
- Using lexicographically smaller key on ties, which is opposite of requirement.
- Misreading input order (events are already chronological).

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

class Solution {
    public char buttonWithLongestTime(int[][] events) {
        int prev = 0;
        int bestDuration = -1;
        char bestButton = 'a';

        for (int[] e : events) {
            char button = (char) ('a' + e[0]);
            int t = e[1];
            int d = t - prev;

            if (d > bestDuration || (d == bestDuration && button > bestButton)) {
                bestDuration = d;
                bestButton = button;
            }
            prev = t;
        }
        return bestButton;
    }
}
func buttonWithLongestTime(events [][]int) byte {
    prev := 0
    bestDuration := -1
    bestButton := byte('a')

    for _, e := range events {
        button := byte('a' + e[0])
        t := e[1]
        d := t - prev

        if d > bestDuration || (d == bestDuration && button > bestButton) {
            bestDuration = d
            bestButton = button
        }
        prev = t
    }
    return bestButton
}
class Solution {
public:
    char buttonWithLongestTime(vector<vector<int>>& events) {
        int prev = 0;
        int bestDuration = -1;
        char bestButton = 'a';

        for (auto &e : events) {
            char button = static_cast<char>('a' + e[0]);
            int t = e[1];
            int d = t - prev;

            if (d > bestDuration || (d == bestDuration && button > bestButton)) {
                bestDuration = d;
                bestButton = button;
            }
            prev = t;
        }
        return bestButton;
    }
};
class Solution:
    def buttonWithLongestTime(self, events: List[List[int]]) -> str:
        prev = 0
        best_duration = -1
        best_button = 'a'

        for idx, t in events:
            button = chr(ord('a') + idx)
            d = t - prev

            if d > best_duration or (d == best_duration and button > best_button):
                best_duration = d
                best_button = button
            prev = t

        return best_button
var buttonWithLongestTime = function(events) {
  let prev = 0;
  let bestDuration = -1;
  let bestButton = 'a';

  for (const [idx, t] of events) {
    const button = String.fromCharCode('a'.charCodeAt(0) + idx);
    const d = t - prev;

    if (d > bestDuration || (d === bestDuration && button > bestButton)) {
      bestDuration = d;
      bestButton = button;
    }
    prev = t;
  }
  return bestButton;
};

中文

题目概述

给定按时间顺序排列的按键事件,每个事件是 [button, time],表示该按键在 time 时刻松开。第一段按压从 0 开始,后续按压从前一个事件结束时开始。请返回按压时长最长的按键;若时长并列,返回字典序更大的按键。

核心思路

每次按压时长就是相邻时间差:duration = events[i].time - events[i-1].time(首个事件减去 0)。因此一次遍历即可,同时维护“当前最大时长 + 对应按键(含并列规则)”。

算法步骤

- 初始化 prev = 0bestDuration = -1bestButton = 'a'
- 遍历每个事件 [button, t],计算 d = t - prev
- 若 d > bestDuration,更新答案。
- 若 d == bestDurationbutton > bestButton,按并列规则更新答案。
- 更新 prev = t

复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)

常见陷阱

- 漏掉第一段按压起点是 0
- 并列时误选字典序更小按键。
- 没利用“输入已按时间排序”这一条件。

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

class Solution {
    public char buttonWithLongestTime(int[][] events) {
        int prev = 0;
        int bestDuration = -1;
        char bestButton = 'a';

        for (int[] e : events) {
            char button = (char) ('a' + e[0]);
            int t = e[1];
            int d = t - prev;

            if (d > bestDuration || (d == bestDuration && button > bestButton)) {
                bestDuration = d;
                bestButton = button;
            }
            prev = t;
        }
        return bestButton;
    }
}
func buttonWithLongestTime(events [][]int) byte {
    prev := 0
    bestDuration := -1
    bestButton := byte('a')

    for _, e := range events {
        button := byte('a' + e[0])
        t := e[1]
        d := t - prev

        if d > bestDuration || (d == bestDuration && button > bestButton) {
            bestDuration = d
            bestButton = button
        }
        prev = t
    }
    return bestButton
}
class Solution {
public:
    char buttonWithLongestTime(vector<vector<int>>& events) {
        int prev = 0;
        int bestDuration = -1;
        char bestButton = 'a';

        for (auto &e : events) {
            char button = static_cast<char>('a' + e[0]);
            int t = e[1];
            int d = t - prev;

            if (d > bestDuration || (d == bestDuration && button > bestButton)) {
                bestDuration = d;
                bestButton = button;
            }
            prev = t;
        }
        return bestButton;
    }
};
class Solution:
    def buttonWithLongestTime(self, events: List[List[int]]) -> str:
        prev = 0
        best_duration = -1
        best_button = 'a'

        for idx, t in events:
            button = chr(ord('a') + idx)
            d = t - prev

            if d > best_duration or (d == best_duration and button > best_button):
                best_duration = d
                best_button = button
            prev = t

        return best_button
var buttonWithLongestTime = function(events) {
  let prev = 0;
  let bestDuration = -1;
  let bestButton = 'a';

  for (const [idx, t] of events) {
    const button = String.fromCharCode('a'.charCodeAt(0) + idx);
    const d = t - prev;

    if (d > bestDuration || (d === bestDuration && button > bestButton)) {
      bestDuration = d;
      bestButton = button;
    }
    prev = t;
  }
  return bestButton;
};

Comments