287. 寻找重复数

简介: 笔记

题意


20.png


解一


二分答案

简单解释,官解也很详细。


定义:dp[i] 表示nums[i] 中 < = i 的数的个数。


看这样一个序列:

nums:3 1 3 4 2

dp: 1 2 4 5


性质:自重复的数起,之后所有dp[i] 都 >i ,之前都 <=i。


在看这样一个序列:

nums:3 1 3 4 3

dp: 1 1 4 5


尽管重复了多次,但是还是满足上面的性质。


那么我们二分答案,统计<=mid 的数的个数,如果个数>mid ,说明是在右侧,可能是答案,r=mid,否则l=mid+1。

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int n = nums.size();
        int l = 1, r = n;
        while(l < r) {
            int mid = (l + r) >> 1;
            auto f = [=](int x){
                int res = 0;
                for (int i = 0; i < n; i++)
                    if(nums[i] <= x) res += 1;
                return res <= x;
            };
            if(f(mid)) l = mid + 1;
            else r = mid;
        }
        return r;
    }
};
/* 一旦加上了重复的数,那么之后一定更大
// 二分check,更小就不要,说明在答案左,l向右调整。
    nums: 1 3 2 4 2
    [1234]: 1 3 4 5
        mid: 3 -> res = 4, r = 3
        mid: 2 -> res = 3, r = 2
        mid: 1 -> res = 1, l = 2
        l == r = 2
    nums: 1 3 2 3 4 3
    [1234]: 1 2 5 6
        mid: 3 -> res = 5, r = 3
        mid: 2 -> res = 2, l = 3
        l == r = 3
*/


解二


二进制


重复一次:


重复的数为x,[1,n] 都各出现一次,外加x 多出现一次。

统计二进制下 1 的个数,原序列相比[1,n] 序列,多出的 1 都是由 x产生。

重复多次:


重复的数为 x ,x 代替 [1,n] 中没出现的数 y ,外加 x多出现一次。


四种情况:00、01、10、11(以下x,y表示某一位为1或0)


x=0,y=0:<=

x=0,y=1:<=

y=0x=1,y=0:>

x=1,y=1:>

所以,对于 > 的情况,将该位 1 加上即可。

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int n = nums.size();
        int res = 0;
        for (int i = 0; i < 31; i++) {
            int x = 0, y = 0;
            for (int j = 0; j < n; j++) {
                if(nums[j] & (1 << i)) x += 1;
            }
            for (int j = 1; j < n; j++) {
                if(j & (1 << i)) y += 1;
            }
            if(x > y) res |= (1 << i);
        }
        return res;
    }
};

解三


快慢指针

n+1个数,[1,n] 范围内。每个位置 i  连边 i−>nums[i]。


3 1 3 4 2

0 1 2 3 4


建边:0->3, 1->1, 2->3, 3->4, 4->2



明显重复的 3  是环的入口。


又点 0 只可能有出边,不可能自环。所以定义快慢指针 l , r都从 0开始。


然后就是环形链表找入口的常规解法:


慢一步、快二步

慢置为 0 00

慢一步、快一步

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int l = 0, r = 0;
        do {
            l = nums[l];
            r = nums[nums[r]];
        } while(l != r);
        l = 0;
        while(l != r) {
            l = nums[l];
            r = nums[r];
        }
        return l;
    }
};


相关文章
|
6月前
|
机器学习/深度学习 人工智能 自然语言处理
人人都能读懂的大模型入门指南 - Transformer与Attention机制
人人都能读懂的大模型入门指南 - Transformer与Attention机制
139 5
人人都能读懂的大模型入门指南 - Transformer与Attention机制
|
网络协议 网络性能优化 网络架构
运输层---概述
运输层---概述
212 2
Flyway Validate failed: Migration checksum mismatch for migration version 1.0.0.01 错误
在运行系统的时候出现错误: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resour...
3053 0
|
9月前
|
机器学习/深度学习 Serverless 索引
分类网络中one-hot编码的作用
在分类任务中,使用神经网络时,通常需要将类别标签转换为一种合适的输入格式。这时候,one-hot编码(one-hot encoding)是一种常见且有效的方法。one-hot编码将类别标签表示为向量形式,其中只有一个元素为1,其他元素为0。
302 2
|
11月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化2
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
151 6
|
12月前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
1048 3
|
jenkins 测试技术 持续交付
Jenkins 在多分支项目中的应用
【8月更文第31天】在现代软件开发实践中,分支管理是一项至关重要的策略,它允许开发团队在不同的功能开发、修复bug或进行实验时不会干扰主干代码。随着项目的复杂度增加,维护多个分支并确保它们的质量变得越来越具有挑战性。Jenkins 作为一款流行的持续集成(CI)和持续部署(CD)工具,提供了强大的功能来支持多分支项目的自动化测试和部署。本文将探讨 Jenkins 如何帮助管理多分支项目,并提供具体的代码示例。
302 0
|
11月前
|
消息中间件 网络协议 安全
C# 一分钟浅谈:WebSocket 协议应用
【10月更文挑战第6天】在过去的一年中,我参与了一个基于 WebSocket 的实时通信系统项目,该项目不仅提升了工作效率,还改善了用户体验。本文将分享在 C# 中应用 WebSocket 协议的经验和心得,包括基础概念、C# 实现示例、常见问题及解决方案等内容,希望能为广大开发者提供参考。
698 0
|
机器学习/深度学习 人工智能 算法
【专家系统】系统地掌握专家系统的基本概念、技术原理、实现方法以及应用实践。
专家系统是一种人工智能程序,它利用专家知识和推理能力来解决特定领域中的复杂问题,系统地掌握专家系统的基本概念、技术原理、实现方法以及应用实践。
1125 1
|
存储 JSON 测试技术
Python中最值得学习的第三方JSON库
Python中最值得学习的第三方JSON库
309 0