AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79596954
Accepted
CodeCrusader
CodeCrusader
Asked: 2025-04-29 00:52:43 +0800 CST2025-04-29 00:52:43 +0800 CST 2025-04-29 00:52:43 +0800 CST

找到相邻 diff 小于 2 的子序列的最大长度

  • 772

问题陈述:

给定一个大小为 n 的整数数组 arr。

选择一个整数子序列并重新排列它们以形成一个循环序列,使得任意两个相邻整数(包括最后一个和第一个)之间的绝对差最多为 1。

找出可以选择的最大整数数。

笔记:

子序列是通过删除零个或多个元素而不改变剩余元素的顺序而形成的。

选定的整数可以按任意顺序重新排列。

该序列是循环的——最后一个整数和第一个整数被视为相邻的。

限制:

1 <= n <= 2 × 10^5

0 <= arr[i] <= 10^9

例子:

Input: arr = [4, 3, 5, 1, 2, 2, 1]
Output: 5
Explanation: maximum length subsequence is : [3, 1, 2, 2, 1], it can be rearranged to seq : [2, 1, 1, 2, 3] of length 5, note that the condition must be satisfied in circular also, means abs(seq[0] - seq[seq.length-1]) means abs(2-3) <= 0 

Input: arr = [3, 7, 5, 1, 5]
Output: 2
Explanation: maximum length subsequence is : [5,5] of length 2

Input: arr = [2, 2, 3, 2, 1, 2, 2]
Output: 7
Explanation: maximum length subsequence is : [2,2,3,2,1,2,2] of length 7

Input: arr = [1,2,3,4,5]
Output = 2
Explanation: maximum length subsequence is : [1,2] or [2,3] or [3,4] or [4,5], so length is 2. 

请注意,子序列也应该满足循环条件这是我的代码:

import java.util.*;

class Main {
    public static int solve(int[] arr) {
        Map<Integer, Integer> freq = new HashMap<>();
        for (int num : arr) {
            freq.put(num, freq.getOrDefault(num, 0) + 1);
        }

        int max = 0;
        for (int num : freq.keySet()) {
            int count = freq.get(num);
            int countWithNext = freq.getOrDefault(num + 1, 0);
            int countWithPrev = freq.getOrDefault(num - 1, 0);
            max = Math.max(max, countWithPrev + count + countWithNext);
        }

        return max;
    }

    public static void main(String[] args) {
        System.out.println(solve(new int[]{4,3,5,1,2,2,1})); // Expected: 5
        System.out.println(solve(new int[]{3,7,5,1,5})); // Expected: 2
        System.out.println(solve(new int[]{2,2,3,2,1,2,2})); // Expected: 7
        System.out.println(solve(new int[]{1,2,3,4,5})); // Expected: 2
    }
}

我能够找到最大长度子序列,但无法找到如何满足循环条件,因此对于测试用例 [1,2,3,4,5],我的代码返回 5 而不是 2。

此外,正如 John Bollinger 所评论的,该方法本身对于输入 [1,2,3,4,3,2] 失败

用较少的时间复杂度来解决这个问题的正确方法是什么?

java
  • 2 2 个回答
  • 109 Views

2 个回答

  • Voted
  1. John Bollinger
    2025-04-29T03:46:14+08:002025-04-29T03:46:14+08:00

    用较少的时间复杂度来解决这个问题的正确方法是什么?

    请注意评论中@btilly 的提示:

    您的子序列有一个最小值,有一个最大值,并且它们之间的每个值都必须出现 2 次以上。

    这几乎是一个可以匹配的指纹,但在将其扩展为这样的指纹之前,让我们首先考虑一下为什么会这样。

    考虑一个连续循环序列中的成员s n,它既不是序列的最小值,也不是最大值。现在假设我们从s n开始遍历该循环。在返回s n之前,我们将遍历序列的最小值和最大值。由于序列是连续排列的,因此在这两个元素之间,我们必须遍历另一个与s n值相同的元素。因此,序列中每个既不是最小值也不是最大值的成员都必须出现至少两次。

    然而,最小值和最大值并非如此。其中一个或两个可能出现多次,但我们仍然可以形成一个只包含一个的循环。在最简单的情况下,单个数字出现一次就满足条件,但最小值和最大值可以各出现一次,并且元素总数可以是任意的,而不是恰好3。

    现在假设我们有一组连续的数字,顺序任意,每个数字至少出现两次,除了其中的最小值和最大值。我们可以先将它们按升序排列,然后从每个既不是最小值也不是最大值的数字中取出一个,并按降序将它们移到末尾,从而形成一个循环序列。例如,

    • 从2, 4, 3, 2, 3, 1, 3, 5, 5, 4开始,
    • 我们排序得到1, 2, 2, 3, 3, 3, 4, 4, 5, 5
    • 然后我们将一个 4、一个 3 和一个 2 移到最后,得到1, 2, 3, 3, 4, 5, 5, 4, 3, 2,满足要求

    因此,对于适合形成所需循环序列的数字集合,以下条件既是必要条件,也是充分条件:(i) 它们是连续的,并且 (ii) 每个既不是最小值也不是最大值的数字至少出现两次。

    现在你有了你的指纹。最坏情况下,可以在 O( nlogn )步内找到具有该指纹的最大序列,但具体细节留给你自己去解决。

    • 3
  2. Best Answer
    trincot
    2025-04-29T04:19:43+08:002025-04-29T04:19:43+08:00

    你的代码只根据直接“邻居”(按排序顺序)的频率来确定计数。当正确答案涉及超过3个不同的数字时,这将导致错误的结果。

    计算频率是一个好方法,但扫描范围不应仅限于当前值的直接相邻值。只有当您确定自己处于潜在范围的低端时,才查找相邻值也会很有帮助——这样您只需按升序扫描值即可。当一个值的频率为 1 或该值在负 1 的范围内不存在时,该值即为“低”。

    以下是循环(获得频率后)的工作方式:

            int max = 0;
            for (int num : freq.keySet()) {
                int count = freq.get(num);
                if (count != 1 && freq.containsKey(num-1)) continue;
                // We're at a low end of a range
                int groupCount = count;
                do {
                    num++;
                    count = freq.getOrDefault(num, 0);
                    groupCount += count;
                } while (count > 1);
                max = Math.max(max, groupCount);
            }
            return max;
    

    假设哈希映射上的get和put操作的摊销时间复杂度为 O(1),则该算法的时间复杂度为 O(𝑛),其中 𝑛 是输入数组的大小。

    • 2

相关问题

  • Lock Condition.notify 抛出 java.lang.IllegalMonitorStateException

  • 多对一微服务响应未出现在邮递员中

  • 自定义 SpringBoot Bean 验证

  • Java 套接字是 FIFO 的吗?

  • 为什么不可能/不鼓励在服务器端定义请求超时?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve