当前位置: 首页 > wzjs >正文

58同城推广能免费做网站吗windows优化大师自动下载

58同城推广能免费做网站吗,windows优化大师自动下载,苏州做网站哪里好,数字营销专业学什么课程文章目录 题目标题和出处难度题目描述要求示例数据范围进阶 前言解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 解法三思路和算法代码复杂度分析 题目 标题和出处 标题:寻找重复数 出处:287. 寻找重复数 难度 6 级 题目描述 要…

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
      • 进阶
  • 前言
  • 解法一
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法二
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法三
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:寻找重复数

出处:287. 寻找重复数

难度

6 级

题目描述

要求

给定一个包含 n + 1 \texttt{n} + \texttt{1} n+1 个整数的数组 nums \texttt{nums} nums,每个整数都在范围 [1, n] \texttt{[1, n]} [1, n] 内(包括 1 \texttt{1} 1 n \texttt{n} n)。

数组 nums \texttt{nums} nums 只有一个重复的整数,返回这个重复的数。

要求不修改数组 nums \texttt{nums} nums 且只用常量级的额外空间。

示例

示例 1:

输入: nums = [1,3,4,2,2] \texttt{nums = [1,3,4,2,2]} nums = [1,3,4,2,2]
输出: 2 \texttt{2} 2

示例 2:

输入: nums = [3,1,3,4,2] \texttt{nums = [3,1,3,4,2]} nums = [3,1,3,4,2]
输出: 3 \texttt{3} 3

示例 3:

输入: nums = [3,3,3,3,3] \texttt{nums = [3,3,3,3,3]} nums = [3,3,3,3,3]
输出: 3 \texttt{3} 3

数据范围

  • 1 ≤ n ≤ 10 5 \texttt{1} \le \texttt{n} \le \texttt{10}^\texttt{5} 1n105
  • nums.length = n + 1 \texttt{nums.length} = \texttt{n} + \texttt{1} nums.length=n+1
  • 1 ≤ nums[i] ≤ n \texttt{1} \le \texttt{nums[i]} \le \texttt{n} 1nums[i]n
  • nums \texttt{nums} nums 中的所有整数都只出现一次,除了一个整数出现两次或多次

进阶

  • 如何证明 nums \texttt{nums} nums 中至少存在一个重复的数字?
  • 你可以设计一个线性级时间复杂度的解决方案吗?

前言

由于数组的长度是 n + 1 n + 1 n+1,且最多包含 n n n 个不同的整数。根据抽屉原理(或鸽笼原理)可知,将数组的 n + 1 n + 1 n+1 个位置分配到 n n n 个不同的整数,至少有两个位置分配到同一个整数,即该整数在数组中重复。因此数组中至少存在一个重复的数字。

由于这道题要求不修改数组且空间复杂度是 O ( 1 ) O(1) O(1),因此排序、哈希表等解法都是不允许的,需要使用其他解法寻找重复的数字。

解法一

思路和算法

每个正整数的二进制表示中至少有一位是 1 1 1。对于二进制表示的每一位,分别考虑数组 nums \textit{nums} nums 中的所有整数在该位的 1 1 1 的次数 countArr \textit{countArr} countArr 和范围 [ 1 , n ] [1, n] [1,n] 中的所有整数在该位的 1 1 1 的次数 countNum \textit{countNum} countNum。假设整数 x x x 在数组 nums \textit{nums} nums 中出现超过一次,则 x x x 的二进制表示的每个 1 1 1 所在的位都满足 countArr > countNum \textit{countArr} > \textit{countNum} countArr>countNum。理由如下。

  • 如果 x x x 出现两次,则范围 [ 1 , n ] [1, n] [1,n] 中的所有整数都在数组 nums \textit{nums} nums 中出现,因此对于 x x x 中等于 1 1 1 的每一位都有 countArr > countNum \textit{countArr} > \textit{countNum} countArr>countNum

  • 如果 x x x 出现超过两次,则范围 [ 1 , n ] [1, n] [1,n] 中的部分整数不在数组 nums \textit{nums} nums 中出现,可以看成 x x x 替代了这部分整数。对于 x x x 中等于 1 1 1 的每一位,被替代的整数在相应位的值等于 0 0 0 1 1 1。替代之前有 countArr > countNum \textit{countArr} > \textit{countNum} countArr>countNum,替代之后同样有 countArr > countNum \textit{countArr} > \textit{countNum} countArr>countNum

除了 x x x 的二进制表示的每个 1 1 1 所在的位以外,其余位都不满足 countArr > countNum \textit{countArr} > \textit{countNum} countArr>countNum。因此上述结论的逆命题也成立:假设所有满足 countArr > countNum \textit{countArr} > \textit{countNum} countArr>countNum 的位组成的整数是 x x x,则 x x x 在数组 nums \textit{nums} nums 中出现超过一次。

根据上述分析,可以使用位运算寻找重复数。首先找到 n n n 的二进制表示的最高有效位,即最高位 1 1 1 所在的位数,然后依次遍历最低有效位到最高有效位,对于每一位计算 countArr \textit{countArr} countArr countNum \textit{countNum} countNum,如果 countArr > countNum \textit{countArr} > \textit{countNum} countArr>countNum 则将该位加到重复数中。遍历结束之后即可得到重复数。

代码

class Solution {public int findDuplicate(int[] nums) {int n = nums.length - 1;int highBit = 0;int temp = n;while (temp != 0) {highBit = temp & (-temp);temp -= highBit;}int duplicate = 0;for (int i = 1; i <= highBit; i <<= 1) {int countArr = 0, countNum = 0;for (int num : nums) {int bit = num & i;if (bit != 0) {countArr++;}}for (int j = 1; j <= n; j++) {int bit = j & i;if (bit != 0) {countNum++;}}if (countArr > countNum) {duplicate += i;}}return duplicate;}
}

复杂度分析

  • 时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn),其中 n n n 是数组 nums \textit{nums} nums 的长度减 1 1 1。需要遍历的二进制表示位数是 O ( log ⁡ n ) O(\log n) O(logn),对于每一位都需要 O ( n ) O(n) O(n) 的时间计算该位在重复数中是否等于 1 1 1,时间复杂度是 O ( n log ⁡ n ) O(n \log n) O(nlogn)

  • 空间复杂度: O ( 1 ) O(1) O(1)

解法二

思路和算法

假设有一个长度为 n + 1 n + 1 n+1 的数组 counts \textit{counts} counts,其中 counts [ i ] \textit{counts}[i] counts[i] 表示数组 nums \textit{nums} nums 中的不超过 i i i 的整数个数。以下用 x x x 表示重复数。

如果 x x x 出现两次,则当 i < x i < x i<x counts [ i ] = i \textit{counts}[i] = i counts[i]=i,当 i ≥ x i \ge x ix counts [ i ] = i + 1 > i \textit{counts}[i] = i + 1 > i counts[i]=i+1>i

如果 x x x 出现超过两次,则范围 [ 1 , n ] [1, n] [1,n] 中的部分整数不在数组 nums \textit{nums} nums 中出现,可以看成 x x x 替代了这部分整数,假设只有一个整数被替代,用 j j j 表示被替代的整数,分别考虑 j < x j < x j<x j > x j > x j>x 的情况。

  • 如果 j < x j < x j<x,则对于 i < x i < x i<x,不超过 i i i 的整数个数不变或减少,因此 counts [ i ] ≤ i \textit{counts}[i] \le i counts[i]i,对于 i ≥ x i \ge x ix,不超过 i i i 的整数个数不变,因此 counts [ i ] > i \textit{counts}[i] > i counts[i]>i

  • 如果 j > x j > x j>x,则对于 i < x i < x i<x,不超过 i i i 的整数个数不变,因此 counts [ i ] = i \textit{counts}[i] = i counts[i]=i,对于 i ≥ x i \ge x ix,不超过 i i i 的整数个数不变或增加,因此 counts [ i ] > i \textit{counts}[i] > i counts[i]>i

因此当 i < x i < x i<x counts [ i ] ≤ i \textit{counts}[i] \le i counts[i]i,当 i ≥ x i \ge x ix counts [ i ] > i \textit{counts}[i] > i counts[i]>i。如果被替代的整数有多个,该结论仍成立。

重复数 x x x 是使得 counts [ x ] > x \textit{counts}[x] > x counts[x]>x 成立的最小整数 x x x,可以使用二分查找的方法寻找重复数。

low \textit{low} low high \textit{high} high 分别表示二分查找的下界和上界。由于 x x x 在范围 [ 1 , n ] [1, n] [1,n] 中,因此初始时 low = 1 \textit{low} = 1 low=1 high = n \textit{high} = n high=n

每次查找时,取 mid \textit{mid} mid low \textit{low} low high \textit{high} high 的平均数向下取整,计算数组 nums \textit{nums} nums 中的不超过 mid \textit{mid} mid 的整数个数 counts [ mid ] \textit{counts}[\textit{mid}] counts[mid],执行如下操作。

  • 如果 counts [ mid ] ≤ mid \textit{counts}[\textit{mid}] \le \textit{mid} counts[mid]mid,则重复数 x x x 小于等于 mid \textit{mid} mid,因此在 [ low , mid ] [\textit{low}, \textit{mid}] [low,mid] 中继续查找。

  • 如果 counts [ mid ] > mid \textit{counts}[\textit{mid}] > \textit{mid} counts[mid]>mid,则重复数 x x x 大于 mid \textit{mid} mid,因此在 [ mid + 1 , high ] [\textit{mid} + 1, \textit{high}] [mid+1,high] 中继续查找。

low = high \textit{low} = \textit{high} low=high 时,查找结束,此时 low \textit{low} low 即为重复数 x x x

实现方面,并不需要显性创建数组 counts \textit{counts} counts,而是可以在二分查找的过程中根据当前的 mid \textit{mid} mid 遍历数组 nums \textit{nums} nums 计算不超过 mid \textit{mid} mid 的整数个数,因此空间复杂度是 O ( 1 ) O(1) O(1)

代码

class Solution {public int findDuplicate(int[] nums) {int n = nums.length - 1;int low = 1, high = n;while (low < high) {int mid = low + (high - low) / 2;int count = 0;for (int num : nums) {if (num <= mid) {count++;}}if (count > mid) {high = mid;} else {low = mid + 1;}}return low;}
}

复杂度分析

  • 时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn),其中 n n n 是数组 nums \textit{nums} nums 的长度减 1 1 1。需要执行 O ( log ⁡ n ) O(\log n) O(logn) 次二分查找,每次二分查找需要 O ( n ) O(n) O(n) 的时间遍历数组 nums \textit{nums} nums 计算不超过特定值的整数个数,时间复杂度是 O ( n log ⁡ n ) O(n \log n) O(nlogn)

  • 空间复杂度: O ( 1 ) O(1) O(1)

解法三

思路和算法

将数组看成有向图,范围 [ 0 , n ] [0, n] [0,n] 中的每个整数是一个结点,对于 0 ≤ i ≤ n 0 \le i \le n 0in 的每个下标 i i i,存在一条从 i i i 指向 nums [ i ] \textit{nums}[i] nums[i] 的有向边。对于重复数 x x x,存在至少两条指向 x x x 的边,因此有向图中存在环。

这道题可以看成在有向图中寻找环的入口,可以使用「环形链表 II」的快慢指针做法。以下只说明使用快慢指针寻找重复数的做法,正确性证明见「环形链表 II 的题解」。

寻找重复数分成两步。

第一步是使用快慢指针遍历有向图寻找相遇点。

初始时,快指针和慢指针都位于整数 0 0 0。每次将快指针移动两步,慢指针移动一步,在至少移动一次的情况下,当快指针和慢指针相遇时,相遇的位置为相遇点。

第二步是将两个指针分别从起点和相遇点开始遍历有向图寻找重复数。

初始时,两个指针分别位于整数 0 0 0 和相遇点。每次将两个指针各移动一步,两个指针相遇的整数即为重复数。

代码

class Solution {public int findDuplicate(int[] nums) {int fast = 0, slow = 0;int meet = -1;while (meet < 0) {fast = nums[nums[fast]];slow = nums[slow];if (fast == slow) {meet = fast;}}int pointer1 = 0, pointer2 = meet;while (pointer1 != pointer2) {pointer1 = nums[pointer1];pointer2 = nums[pointer2];}return pointer1;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度减 1 1 1。快慢指针的时间复杂度是 O ( n ) O(n) O(n)

  • 空间复杂度: O ( 1 ) O(1) O(1)

http://www.dtcms.com/wzjs/202016.html

相关文章:

  • 现在外国有哪个网站可以做卖东西windows优化大师功能
  • 做网站插入音乐用什么下载网络优化工程师是干什么的
  • wordpress网站关键词如何做seo优化
  • 扶贫工作网站怎么做无锡seo优化公司
  • 黑客如何攻击网站怎样自己做网站
  • html5做的网站处理器优化软件
  • 政府网站规划彼亿营销
  • php能开发大型网站视频号怎么付费推广
  • 网站 服务器 域名制作网站教程
  • 做期货网站违法的吗软文代发
  • 深圳网站建设大公司好企业推广策划书
  • 自助建站平台哪家好网上引流推广怎么做
  • 四川省建设厅职业注册中心网站品牌推广策略
  • 做六级真题的网站百度网站推广价格
  • 中国建设监理业协会网站百度销售岗位怎么样
  • 南昌网站建设费用百度关键词推广公司
  • 国外做ae模板网站大全网站seo排名优化
  • 江苏省住房和城乡建设委员会官方网站长沙网站se0推广优化公司
  • 建网站手机软件淘宝摄影培训推荐
  • windows 做网站服务器吗在百度上怎么打广告
  • 怎样设计网站模板百度pc网页版登录入口
  • 车子网站旺道seo推广有用吗
  • 哈尔滨seo网站排名网站的优化公司
  • 装修公司展厅布置方案谷歌seo是什么意思
  • 天河手机网站建设百度地图导航
  • 有域名有网站怎么解决办法谷歌引擎搜索
  • 内蒙建设信息网站常州网络推广哪家好
  • 仁怀网站建设不好出手英文外链平台
  • 跟业务合作做网站给多少提成免费域名申请网站
  • 电商网站开发的目的是中国职业培训在线官网