请设计一个高效算法,查找数组中未出现的最小正整数。
给定一个整数数组A和数组的大小n,请返回数组中未出现的最小正整数。保证数组大小小于等于500。
[-1,2,3,4],4
返回:1
/*分析:
* 最小的没有出现的正整数
* 如果1没有出现 那么最小结果为1
* 如果1到n都出现那么最下的结果为n+1
* 因此结果的范围1~n+1
* 数据范围最大500 数据不是很大 可以考虑以空间换时间的做法
* 定义一个数组res[n] 遍历数组A 如果A[i]>n抛弃 不会是结果 如果A[i]<n res[A[i]]=1;
* 遍历res 为0的输出下标 即为结果*/
public int findArrayMex(int[] A, int n) {
int[] res = new int[n];
for (int i = 0; i < n; i++) {
if (A[i]>0&&A[i]<=n){
res[A[i]-1]=1;
}
}
for (int i = 0; i < n; i++) {
if (res[i]==0){
return i+1;
}
}
return n+1;
}
class ArrayMex { public: int findArrayMex(vector<int> A, int n) { // write code here for(int i = 0; i < n; ++ i) while(A[i] > 0 && A[i] <= n && A[A[i] - 1] != A[i]) swap(A[i], A[A[i] - 1]); for(int i = 0; i < n; ++ i) if(A[i] != i + 1) return i + 1; return n + 1; } };
/*竟然和高票方法差不多,很简单,时间和空间复杂度都是O(n), 看到的人麻烦点赞一下,让更多的人看到。不用排序,最多500个数据,最差的情况是 1-500都有,那么就返回501,否则返回第一个值为0的数组坐标就好。*/import java.util.*; public class ArrayMex { public int findArrayMex(int[] A, int n) { int j=1; int[] arr =new int[n+1]; for(int i=0;i<n;i++){ if(A[i]>0&&A[i]<=n){ arr[A[i]]++; } } for( j=1;j<arr.length;j++){ if(arr[j]==0) return j; } return j+1; } }
import java.util.*; public class ArrayMex { public int findArrayMex(int[] A, int n) { // write code here HashMap<Integer,Integer> hashMap=new HashMap<Integer,Integer>(); for(int i=0;i<n;i++){ hashMap.put(A[i],1); } for(int i=1;i>0;i++){ if(hashMap.get(i)==null){ return i; } } return 1; } }
//一次遍历解决问题,复杂度为O(n) import java.util.*; public class ArrayMex { public int findArrayMex(int[] A, int n) { // write code here Arrays.sort(A); int i = 0,j = 0; while(i < n){ //除去非正数 if(A[i] <= 0){ i++; j++; continue; } //第一个整数如果大于1,就返回1; if(A[j] > 1){ return 1; } //到达边界 if(i + 1 == n){ return A[n -1] + 1; } //中间部分 if(A[i+1] - A[i] > 1){ return A[i] + 1; } i++; } return 1; } }
时间复杂度为o(n^2),还可以接受,方法比较简单。
public class ArrayMex { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int a[] = { 1, 5, 3, 0, 6, 6, 6 }; new ArrayMex().findArrayMex(a, 7); } public int findArrayMex(int[] A, int n) { // write code here int min = 0; for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (A[j] > A[j + 1]) { int temp = A[j]; A[j] = A[j + 1]; A[j + 1] = temp; } } } int result = 1; for (int i = 0; i < n; i++) { if (A[i] == result) { i = 0; result++; } } return result; } }
import java.util.*; public class ArrayMex { public int findArrayMex(int[] A, int n) { // write code here TreeSet<Integer> tr=new TreeSet<>(); //去重 for(int elem: A) tr.add(elem); int[] B=new int[tr.size()]; //将去重后的数据重新赋值一个数组中 int k=0; for(int elem: tr) B[k++]=elem; int index=0; while(index<B.length && B[index]<=0) //找到数组B中,第一个为整数的下标 index++; int i=1; while(index<B.length && B[index]==i){ //返回数组中未出现的最小正整数i index++; i++; } return i; } }
解题思路:
因为输入不会超过500个数据,那么使用哈希表的想法,以空间换时间。
生成一个hash[500]的数组,初始化为0。从头遍历A,如果A[i]的值大于0,则相应hash[i-1]++。当遍历完整个数组后,hash[i]的值代表i+1这个数字在A中出现过的次数。
举例:
A={4,1,5,2,-1,4}
num 1 2 3 4 5
index 0 1 2 3 4
hash(前五个) 1 1 0 2 1
发现hash中index=2,num=3时为0,意味着最小的正整数没出现过。
时间和空间复杂度为O(n)。
#include <vector>
using namespace std;
class ArrayMex {
public:
int findArrayMex(vector<int> A, int n) {
// write code here
vector<int> hash(500,0);
for(int i=0;i<n;++i)
{
if(A[i]<=0)
continue;
++hash[A[i]-1];
}
for(int i=0;i<500;++i)
{
if(hash[i]==0)
return i+1;
}
return -1;
}
};
class ArrayMex { public: int findArrayMex(vector<int> A, int n) { // write code here sort(A.begin(),A.end()); A.erase(unique(A.begin(),A.end()),A.end()); if(A.empty()||n<=0)return 1; if(A[0]>1) return A[0]-1; if(A[n-1]<1) return 1; for(int i=0;i<n-1;i++) { if(A[i+1]!=A[i]+1) return A[i]+1; } return A[n-1]+1; } };
代码写的不够简洁! #include <iostream> #include <cstdio> #include <string> #include <algorithm> #include <cstdio> #include <vector> #include <set> using namespace std; //首先去掉重复的, 然后考虑各个情况!可以参考测试数据 int findArrayMex(vector<int> A, int n) { vector<int> B; for(int i = 0; i < n; i++) { if(A[i] > 0) { B.push_back(A[i]); } } sort(B.begin(), B.end()); if(B.empty()) return 1; else if(B[0] > 1) return 1; else if(B.size()== 1) return 2; for(int i = 1; i < (int)B.size(); i++) { if(B[i-1]+1 < B[i]) { return B[i-1]+1; } } return B[B.size()-1]+1; } int main() { //int arr[] = {-1,2,3,4}; //int arr[] = {-2,-1,0,1}; //int arr[] = {-2,-1,0,1, 3}; // int arr[] = {-2,-1,0,1, 2}; //int arr[] = {-1,2,3,4}; //int arr[] = {2, 3, 4, 5}; // int arr[] = {1, 2, 3, 4, 5}; int arr[] = {-1, 0, 1, 1, 2, 2, 2, 4, 4, 5}; int len = sizeof(arr)/sizeof(int); vector<int> A(arr, arr+len); int res = findArrayMex(A, A.size()); cout << res << endl; return 0; }
class ArrayMex { public: int findArrayMex(vector<int> A, int n) { // write code here vector<int> tmp(n,0); for(auto val:A) { if(val>=0 && val<=n)//记录0到n范围内的数 tmp[val]=1; } for(int i=1;i<n;++i)//从1开始处理(剩个0,后续处理) { if(tmp[i]==0) return i; } return tmp[0]==1?n:n+1;//判断数组是否从0开始 } };
import java.util.*; public class ArrayMex { public int findArrayMex(int[] A, int n) { int max = A[0]; for(int i=0;i<n;i++) if(max<A[i]) max=A[i]; int[] a = new int[max+1]; for(int i=0;i<n;i++){ if(A[i]<=0) continue; else a[A[i]]++; } for(int i=1;i<=max;i++) if(a[i]==0) return i; return max+1; } }
class ArrayMex: def findArrayMex(self, A, n): i = 0 items = A for j in xrange(n): if n >= items[j] > 0: items[i] = items[j] i += 1 for k in xrange(i): v = abs(items[k]) items[v - 1] = - abs(items[v - 1]) for w in xrange(i): if items[w] > 0: return w + 1 return i + 1
//先排序N*log(N),然后找到第一个整数的位置,后面依次寻找 //总的复杂度是 N*log(N) class ArrayMex { public: int findArrayMex(vector<int> A, int n) { // write code here sort(A.begin(),A.end()); int j; for(j=0;j<A.size();j++) { if(A[j]>0)break; } int i=1; int c=j; while(c<n) { if(c==j && A[c]!=i)break; else if(c>j && A[c] != A[c-1] && A[c]!=i)break; else if(c>j && A[c] == A[c-1] && A[c]!=i){c++;} else {c++;i++;} } return i; } };
提交了才发现原来数字还有重复的,果断用了set。本人愚笨,只会用库,轻喷。classArrayMex {public:intfindArrayMex(vector<int> A, intn) {// write code here//排序并拷贝到set中去除重复的元素:std::sort(A.begin(),A.end());std::set<int> iset(A.begin(),A.end());//从大于0的数字开始,逐个和1、2、3、4。。。比较,有未出现的即输出;int j = 1;for(auto it = iset.begin(); it != iset.end(); ++it){if(*it > 0)if(*it == j)j++;elsebreak;elsecontinue;}returnj;}};
class ArrayMex {
public:
int findArrayMex(vector<int> A, int n) {
int hash[10000]={0};
for(int i=0;i<n;i++){
if(A[i]>0){
hash[A[i]]=1;}
}
int number = 1;
while(hash[number++]);//找到第一个没有出现的number,即hash[number]=0,跳出循环。
return number-1;//因为最后找到时number+1了,所以返回number-1。
}
};
//大家好,这个题目和今年网易内推的一个题目(重考的题目)解法一样; class ArrayMex { public: int findArrayMex(vector<int> vec, int n) { // write code here sort(vec.begin(),vec.end()); int i; int res=1;//最小正整数为1 if(vec[0]>=2) return res; for(i=0;i<n-1;i++) { if(vec[i+1]-vec[i]>1) { if(vec[i]<=0 && vec[i+1]>1) { res=1; break; } else if(vec[i]>=0) { res=vec[i]+1; break; } else { continue; } } } if(i>=n-2) res=vec[n-1]+1; return res; } };