【算法】组中元素全是1~n之间的整数问题
来源:互联网 发布:利驰软件怎么样 编辑:程序博客网 时间:2024/05/21 19:44
数组中数全是1~n的范围内的题
这部分之前是在LeetCode的好题总结里的,不过在打算给类似问题专题化之后,就单独把这部分拿了来了,然后又新加了一些总结和解法。
长度为n的数组,其中元素全部为1~n,则这种题有一个通用的解法:
循环替换 num[num[i]] = num[i]
直到不能替换为止。然后再继续。具体操作上,可以不断的做swap(num[i],num[num[i]])
这样写起来代码更短,更方便。
还有一种比较trick的思路就是,nums[i]的数组,将其在nums[nums[i]]这个位置坐上一些标记。
对于这类数组一个最经典的两个问题就是:
- 给定一个长度为n的数组,数组中元素是1~n之间的数乱序排列,将其用O(n)时间复杂度排序
- 给定一个长度为n-1的数组,数组中元素是1~n之间的数乱序排列,但少了一个数,让O(n)的时间内找出这个缺少的这个数。
对于第一个问题,就直接采用上面说的办法,不断轮换,就可以了。【其实难道不是直接输出从1~n不就好了吗,更方便,笑】
对于第二个问题,也是采用上面的方法,不断轮换,然后再遍历一遍,发现num[i]位置上是否是i+1如果不是则说明这个元素就是的了。其实还有一个别的解法,就是将数组中所有元素都给异或一遍,然后再跟1~n都给异或一遍,则最后剩下的那个值就是缺失的元素了。
LeetCode 上关于这种数组有以下三道题:
448. Find All Numbers Disappeared in an Array这道题是在1~n数组中全部找到其中消失的元素。
Input:
[4,3,2,7,8,2,3,1]
Output:
[5,6]
vector<int> findDisappearedNumbers(vector<int>& nums) { vector<int> res; for(int i=0;i<nums.size();i++){ while(nums[i] != nums[nums[i]-1]) swap(nums[i],nums[nums[i]-1]); } for(int i=0;i<nums.size();i++) if(nums[i]-1 != i) res.push_back(i+1); return res; }
442. Find All Duplicates in an Array
找一个数组中(数组中全是1~n的数,但是有重复的),找出其中全部的重复元素。
Input:
[4,3,2,7,8,2,3,1]
Output:
[2,3]
其实这道题和上面那道题是一样的,如果采用不断swap的方法,最后缺失的位置上会剩下重复的元素。如果采用轮换替换的方法,则会变得麻烦。
vector<int> findDuplicates(vector<int>& nums) { vector<int> res; for(int i=0;i<nums.size();i++){ while(nums[i] != nums[nums[i]-1]) swap(nums[i],nums[nums[i]-1]); } for(int i=0;i<nums.size();i++) if(nums[i]!=i+1) res.push_back(nums[i]); return res; }
这道题呢,还有一个办法,可以改变原来的数组【其实也是改变了,只不过最后又修复了】,就是每次找到nums[i]这个元素了,把nums[nums[i]]标记为原来的相反数,如果nums[nums[i]]就已经是复数了,则说明这个元素重复了。然后最后再把所有元素取一个绝对值,就修复了。代码如下
vector<int> findDuplicates(vector<int>& nums) { vector<int> res; for(int i=0;i<nums.size();i++){ if(nums[abs(nums[i])-1] <0) res.push_back(abs(nums[i])); else nums[abs(nums[i])-1] = -nums[abs(nums[i])-1]; } for(auto &i:nums) i = abs(i); return res; }
41. First Missing Positive找出一列数中,假如将其排序的话,缺失的第一个正整数(即不包括0)
Given [1,2,0] return 3,
and [3,4,-1,1] return 2.
还是用上面的解法,不过注意这道题有个tricky的地方在于nums[i]是换nums[nums[i]-1]
还是换nums[nums[i]]
因为题目中要求找出缺失的第一个正整数,所以需要换nums[nums[i]-1]
,因为这样保证如果1就应该出现在第一个位置,如果没有出现则说明缺少了1。如果题目中要求找出确实的第一个自然数(包括0)则需要换nums[nums[i]]
;同理类比可得如果要找从2开始缺失的数,则需要换nums[nums[i]-2]
int firstMissingPositive(vector<int>& nums) { for(int i=0;i<nums.size();i++){ while(nums[i]>0 && nums[i]<=nums.size()&&nums[i] != nums[nums[i]-1]) swap(nums[i],nums[nums[i]-1]); } for(int i=0;i<nums.size();i++) if(nums[i]!=i+1) return i+1; return nums.size()+1; }
- 【算法】组中元素全是1~n之间的整数问题
- n个元素的全排列算法
- 一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1
- 给你一个由n-1个整数组成的未排序的序列,其元素都是1到n中的不同的整数。请写出一个寻找序列中缺失整数的线性时间算法。
- 从N个整数中找了(n-1)个元素乘积最大的那一组
- 整数n的全排列
- 生成n个元素全排列的算法
- 1-n之间的整数之和为指定数sum问题(百度之星往年试题)
- 计算1~n之间的所有十进制整数中1的出现次数
- 15、一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。
- N个元素中取M个的全组合
- 【编程之美】读书笔记:求1到N之间整数中出现1的个数
- 求1到N之间整数中出现1的个数
- 去除数组维数n,元素为1--n的任意整数的重复整数
- 1到n之间的所有整数的立方
- 1到整数N,求其中某一位是7的数
- 整数中1出现的次数(从1到n整数中1出现的次数)(算法)
- 每天学习一算法系列(28)(输入一个整数n,求从1 到n 这n 个整数的十进制表示中1 出现的次数)
- 我的第一篇博客
- Java并发包中的线程池的种类和特性介绍
- 函数作为参数
- POJ 1835 宇航员 中文
- Real adaboost
- 【算法】组中元素全是1~n之间的整数问题
- ajax(四)
- 【蓝桥杯题解】矩阵翻硬币
- ARM体系结构(一)
- 【zabbix】利用LLD自动发现功能监控多Memcached实例
- 随笔
- 爬取微博用户的原创微博
- linux查看进程启动时间
- Gym - 101147H H. Commandos DAG