一道简单的数组遍历题,加上四个条件后感觉无从下手

2024-02-13 13:59

本文主要是介绍一道简单的数组遍历题,加上四个条件后感觉无从下手,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击蓝色“五分钟学算法”关注我哟

加个“星标”,天天中午 12:15,一起学算法

640?wx_fmt=jpeg

作者 | P.yh

来源 | 五分钟学算法

今天分享的题目来源于 LeetCode 第 287 号问题:寻找重复数。

题目描述

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

示例 1:

输入: [1,3,4,2,2]
输出: 2

示例 2:

输入: [3,1,3,4,2]
输出: 3

说明:

  • 不能更改原数组(假设数组是只读的)。

  • 只能使用额外的 O(1) 的空间。

  • 时间复杂度小于 O(n^2) 。

  • 数组中只有一个重复的数字,但它可能不止重复出现一次。

题目解析

题目的限制真多!!!

首先 不能改变数组 导致无法排序,也无法用 index 和元素建立关系;

只能使用 O(1) 的空间 意味着使用哈希表去计数这条路也走不通;

时间复杂度必须小于 O(n^2) 表示暴力求解也不行;

重复的元素可重复多次 这一条加上后,本来可以通过累加求和然后做差 sum(array) - sum(1,2,...,n) 的方式也变得不可行。

本来是非常简单的一道数组遍历的题目,加上了上面这四个条件后感觉有点无从下手

我们说做题要借助算法,而不是空想,因此对于这道题也不例外,我们可以问自己这样一个问题,就是 “什么样的算法可以不使用额外的空间解决数组上面的搜索问题?”

静静的思索一下。

你这时应该隐隐约约知道了,难道是 二分查找

什么?二分查找法?!

二分查找法不是对有序数组才适用么?

这里澄清一个误区,二分法的使用 并不一定 需要在排序好的数组上面进行,不要让常见的例题限制了你的思路,二分法还有一个比较高级的用法叫做 按值二分

这道题目交代的信息很少,我们只需要关注两个东西 - 数组,数组里的元素,利用二分我们需要去思考的是,我们要找符合条件的元素作为答案,那么 比答案小的元素具有什么样的特质,比答案大的元素又具有什么样的特质?,结合题目给我们的例子来看看:

( 说明:下面的  <=  符号表明 小于或者等于。)

例1:

[1,3,4,2,2]                      元素个数
<= 1 的元素:1                       1
<= 2 的元素:1, 2, 2                 3
<= 3 的元素:1, 2, 2, 3              4
<= 4 的元素:1, 2, 2, 3, 4           5

例2:

[3,1,3,4,2]
<= 1 的元素:1                        1
<= 2 的元素:1, 2                     2
<= 3 的元素:1, 2, 3, 3               4
<= 4 的元素:1, 2, 3, 3, 4            5

极端一点的例子 (必须保证数组的长度是 n + 1, 并且元素都在区间[1,n] 上, 有且只有一个重复)

[3,3,3,3,4]
<= 1 的元素:                        0
<= 2 的元素:                        0
<= 3 的元素:3, 3, 3, 3              4
<= 4 的元素:3, 3, 3, 3, 4           5

看完上面几个例子,相信你明白了一个事实:

  • “如果选中的数 小于 我们要找的答案,那么整个数组中小于或等于该数的元素个数必然小于或等于该元素的值;

  • 如果选中的数 大于或等于 我们要找的答案,那么整个数组中小于或等于该数的元素个数必然 大于 该元素的值”

而且你可以看到,我们要找的答案其实就处于一个分界点的位置,寻找边界值,这又是二分的一个应用,而且题目已经告诉我们数组里面的值只可能在 [1, n] 之间,这么一来,思路就是在 [1, n] 区间上做二分,然后按我们之前提到的逻辑去做分割。整个解法的时间复杂度是 O(nlogn),也是满足题目要求的。

上面的解法不是最优的,但是个人觉得是根据现有的知识比较容易想到的。

另外一种 O(n) 的解法借鉴快慢指针找交点的思想,算法非常的巧妙,也非常的有趣,但不太容易想到,这里把代码放上。

动画描述

代码实现一

//二分查找
class Solution {public int findDuplicate(int[] nums) {int len = nums.length;int start = 1;int end = len - 1;while (start < end) {int mid = start + (end - start) / 2;int counter = 0;for (int num:nums) {if (num <= mid) {counter++;}}if (counter > mid) {end = mid;} else {start = mid + 1;}}return start;}
}

代码实现二

//快慢指针
public int findDuplicate(int[] nums) {        int fast = nums[nums[0]];int slow = nums[0];while (fast != slow) {fast = nums[nums[fast]];slow = nums[slow];}slow = 0;while (fast != slow) {fast = nums[fast];slow = nums[slow];}return slow;
}

640?

有热门推荐?

1.【程序员】

2.【GitHub】

3.【算法】

4.【数据结构】

640?wx_fmt=jpeg

▼ 点击『阅读原文』解锁更多图解 LeetCode 题目

这篇关于一道简单的数组遍历题,加上四个条件后感觉无从下手的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/705718

相关文章

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

SpringIntegration消息路由之Router的条件路由与过滤功能

《SpringIntegration消息路由之Router的条件路由与过滤功能》本文详细介绍了Router的基础概念、条件路由实现、基于消息头的路由、动态路由与路由表、消息过滤与选择性路由以及错误处理... 目录引言一、Router基础概念二、条件路由实现三、基于消息头的路由四、动态路由与路由表五、消息过滤

springboot简单集成Security配置的教程

《springboot简单集成Security配置的教程》:本文主要介绍springboot简单集成Security配置的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录集成Security安全框架引入依赖编写配置类WebSecurityConfig(自定义资源权限规则

如何使用Python实现一个简单的window任务管理器

《如何使用Python实现一个简单的window任务管理器》这篇文章主要为大家详细介绍了如何使用Python实现一个简单的window任务管理器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 任务管理器效果图完整代码import tkinter as tkfrom tkinter i

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

使用EasyExcel实现简单的Excel表格解析操作

《使用EasyExcel实现简单的Excel表格解析操作》:本文主要介绍如何使用EasyExcel完成简单的表格解析操作,同时实现了大量数据情况下数据的分次批量入库,并记录每条数据入库的状态,感兴... 目录前言固定模板及表数据格式的解析实现Excel模板内容对应的实体类实现AnalysisEventLis

Java中数组转换为列表的两种实现方式(超简单)

《Java中数组转换为列表的两种实现方式(超简单)》本文介绍了在Java中将数组转换为列表的两种常见方法使用Arrays.asList和Java8的StreamAPI,Arrays.asList方法简... 目录1. 使用Java Collections框架(Arrays.asList)1.1 示例代码1.

Nginx中location实现多条件匹配的方法详解

《Nginx中location实现多条件匹配的方法详解》在Nginx中,location指令用于匹配请求的URI,虽然location本身是基于单一匹配规则的,但可以通过多种方式实现多个条件的匹配逻辑... 目录1. 概述2. 实现多条件匹配的方式2.1 使用多个 location 块2.2 使用正则表达式

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链