给定一个无序数组arr,找到数组中未出现的最小正整数
例如arr = [-1, 2, 3, 4]。返回1
arr = [1, 2, 3, 4]。返回5
[要求]
时间复杂度为,空间复杂度为
第一行为一个整数N。表示数组长度。
接下来一行N个整数表示数组内的数
输出一个整数表示答案
4 -1 2 3 4
1
4 1 2 3 4
5
#include <bits/stdc++.h> using namespace std; int main(){ int n; cin>>n; int a[n], l=0, r=n-1; for(int i=0;i<n;i++) cin>>a[i]; while(l<r){ if(a[l]==l+1) l++; else if(a[l]<=l || a[l]>r || a[a[l]-1]==a[l]) a[l] = a[--r]; else swap(a[l], a[a[l]-1]); } cout<<l+1<<endl; return 0; }
#include<bits/stdc++.h> using namespace std; int main() { int n; cin>>n; vector<int>num(n); for(int i=0;i<n;i++) cin>>num[i]; int left=0,right=n-1; while(left<right) { if(num[left]==left+1) left++; else if(num[left]<=left||num[left]>right||num[num[left]-1]==num[left]) num[left]=num[--right]; else swap(num[left],num[num[left]-1]); } cout<<left+1; return 0; }
import java.util.*; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); long[] arr = new long[n]; int max = 0; for (int i = 0; i < n; i++) { arr[i] = in.nextLong(); max += arr[i] > 0 ? 1 : 0; } for (int i = 0; i < n; i++) { long cur = arr[i]; while (cur > 0 && cur <= max && arr[(int)(cur-1)] != cur) { long tmp = arr[i]; arr[i] = arr[(int)(cur-1)]; arr[(int)(cur-1)] = tmp; cur = arr[i]; } } int res = max+1; for (int i = 0; i < n; i++) { if (arr[i] != i+1) { res = i+1; break; } } System.out.println(res); } }
def solution(a): n = len(a) i = 0 while i < n: #将a[I]中存储对应的I+1,如果不在[1,n]则进行下一个 temp = a[i] if temp == i+1: i += 1 elif 1<= temp and temp <= n: if a[i] == a[temp-1]: i += 1 else: a[i] = a[temp-1] a[temp-1] = temp else: i += 1 res = n + 1 for i in range(n): if a[i] != i+1: res = i + 1 break return res n = input() a = [int(i) for i in input().split()] print(solution(a))
#include<bits/stdc++.h> using namespace std; const int N = 1e6+10; int a[N]; int main() { int n; scanf ("%d",&n); for (int i=1;i<=n;i++) scanf ("%d",&a[i]); for (int i=1;i<=n;i++) { if (a[i]>=1&&a[i]<=n&&a[i]!=i) swap(a[i],a[a[i]]); } int k=1; for (;k<=n;k++) if (a[k]!=k) break; printf ("%d",k); return 0; }
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n=Integer.parseInt(sc.nextLine().trim()); int[] arr=new int[n]; String[] s = sc.nextLine().trim().split(" "); for (int i = 0; i < n; i++) { arr[i]=Integer.parseInt(s[i]); } int res=new Solution().NotOccurred(arr); System.out.println(res); } } } class Solution { public int NotOccurred(int[] arr){ for (int i = 0; i < arr.length; i++) { if(arr[i]>0) swap(arr,arr[i]-1,i); } for (int i = 0; i < arr.length; i++) { if(arr[i]!=i+1) return i+1; } return arr.length+1; } public void swap(int[] arr,int i,int j){ int temp=arr[i]; arr[i]=arr[j]; arr[j]=temp; } }
#include <bits/stdc++.h> using namespace std; int firstMissingPositive(vector<int>& arr) { for (int i = 0; i < arr.size(); ++i) { while (!(arr[i] < 1 || arr[i] > arr.size()-1 || arr[i] == i+1 || arr[i] == arr[arr[i]-1])) { swap(arr[i], arr[arr[i]-1]); } } for (int i = 0; i < arr.size(); ++i) { if (arr[i] != i+1) return i+1; } return arr.size()+1; } int main() { int n; cin >> n; vector<int> arr(n); for (int i = 0; i < n; ++i) { cin >> arr[i]; } cout << firstMissingPositive(arr); return 0; }
「自然数数组排序」那题先做了会有极大的帮助。此题是自然数数组排序的变形,一边排序、一边筛选不适合的值(负数)或是重複的值,再依序检查遗漏的正整数。
#include<iostream> using namespace std; const int N = 1e6+5; int a[N]; int n; int main() { scanf("%d", &n); for(int i=1;i<=n;++i) { scanf("%d", a+i); } int l= 1,r = n; while(l<r) { if(a[l]==l) { l++; }else if(a[l]<l || a[l]>r || a[l]==a[a[l]] ) { a[l] = a[r--]; }else { swap(a[l],a[a[l]]); } } printf("%d", l); return 0; }
/* * @Description: 数组中未出现的最小正整数 * @Author: * @Date: 2020-11-09 20:30:04 * @LastEditTime: 2020-11-09 20:59:15 * @LastEditors: Please set LastEditors */ #include<iostream> #include<vector> #include<algorithm> using namespace std; int main(){ int n; cin >> n; vector<int> arr(n); for(int i = 0;i < n;i++){//初始的数组 cin >> arr[i]; } int left = 0;//左边的索引,将数组分为[0,left]和[left+1,right] //[0,left]都是满足arr[left] == left + 1 //[left+1,right]表示待处理部分 int right = arr.size() - 1;//表示右边界值 while(left < right){ //1.表示正常情况 if(arr[left] == left + 1){ left++; } //2.表示出现不合法情况 //2.1表示在区间[left+1,right]上的数少了一个,因为当前值出现在了[0,left]上 //2.2表示当前值大于整个区间范围,即不在[0,right]的区间范围 //2.3表示当前值出现了重复,则[left+1,right]上的数少了一个 else if (arr[left] <= left || arr[left] > right || arr[ arr[left] - 1 ] == arr[left]){ right--;//范围缩小,故right需要左移 arr[left] = arr[right];//将最后位置上的数放在位置left上(这步不是很懂哎……) } //3.表示当前值是一个合法的值,但是没有在理想的位置上,需要进行交换处理 else{ swap(arr[ arr[left] - 1 ], arr[left]); } } cout << left + 1 << endl; //system("pause"); return 0; }
#include <iostream> #include <algorithm> using namespace std; int main() { int n; cin >> n; int arr[n]; for (int i = 0;i < n;i++){ cin >> arr[i]; } int l = 0; int r = n -1; while(l < r) { if(arr[l] == l + 1)//在理想的位置 { l++; } else if(arr[l] > r || arr[l] <= l || arr[arr[l] - 1] == arr[l])//不合法的数据 { arr[l] = arr[--r]; } else//合法但是没有在理想的位置上 { swap(arr[l], arr[arr[l] - 1]); } }//while cout << l + 1 << endl; return 0; }
//int a[]= {1,3,4,5}; private static int findnum(int a[]) { int l=0;//l表示已经从1到L已经出现(左边界),l的初值为0。 int r=a.length;//如果一个数字过大(不合法)扔掉,用r表示这个右边界,r初始值长度 while(l<r){ if(a[l]==l+1){//a[0]=1,0-k内合法的数有多少 l++; }else if(a[l]<=l||a[l]>r||a[l]==a[a[l]-1]){//不合法, //a[1]=3 a[a[1]-1]=a[2] a[l] = a[--r];//缩短右边界 }else{//合法但是没有在理想的位置上 swap(a,l,a[l]-1);//交换新数l和已排好的a[l]-1 } } return l+1;//返回a[l]=l+1,0-l为已出现的数,l+1代表未出现的数 } private static void swap(int[] arr, int a,int b){ int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int [] arr = new int[n]; for(int i=0;i<n;i++){ arr[i] = scanner.nextInt(); } int l = 0; int r = n; while(l<r){ if(arr[l]==l+1){ l++; }else if(arr[l]<=l||arr[l]>r||arr[l]==arr[arr[l]-1]){ arr[l] = arr[--r]; }else{ swap(arr,l,arr[l]-1); } } System.out.println(l+1); } public static void swap(int[] arr, int a,int b){ int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } }