数据结构王道考研书顺序表统考真题 --- 找出数组中的未出现的最小正整数

题目描述:给定一个含n(n≥1)个整数的数组,请设计一个时间上尽可能高效的算法,找出数组中未出现的最小正整数。例如,数组{-5,3,2,3}中未出现的最小正整数是1;数组{1,2,3}中未出现的最小正整数是4。

答案的方法是用空间换时间,时间复杂度O(n),空间复杂度O(n),答案很清晰,我是想记录一下自己的另一种思路。

思路一

  1. 设一个k,初始值为1,然后就去数组中遍历查找是否有与k相等的元素,如果找到了,则++k,并且此时把 i重置为0(因为数组是无序的,还是需要从头开始查找)
  2. 如果整个数组都没有找到k,则未出现的正整数就是k
  3. 时间复杂度是O(n^2),空间复杂度为O(1)

具体代码如下(可运行):

#include<stdio.h>

// 查找未出现的最小正整数的函数
int find(int a[],int n){
    
    
	int k,i,c;
	k = 1;
	for(i=0;i<n;i++) {
    
    
		if(a[i] == k){
    
    
				++k;
				i=0;// 其实每次找到后a[i]后,将i重置为0,也就相当于多了一层循环
		}
	}
	return k;
}

int main() {
    
    
	int a[100],i,n,res;
	printf("请输入数组个数:");
	scanf("%d",&n);
	printf("请输入每个元素的值:\n");
	for(i=0;i<n;i++){
    
    
		scanf("%d",&a[i]);
	} 
	
	res = find(a,n);
	printf("最大正整数是: %d\n",res);
	return 0;
}

思路二

  1. 思路二和思路一大体是一样的,只是加上了快速排序,先让数组有序
  2. 使用快速排序,就可以使数组有序了,这样就不需要向上面的思路一样每次找到元素后要重置i
  3. 时间复杂度是O(nlogn),空间复杂度为O(1)
#include<stdio.h>

// 快速排序
void QuickSort(int arr[], int low, int high)
{
    
    
    if (low < high)
    {
    
    
        int i = low;
        int j = high;
        int k = arr[low];
        while (i < j)
        {
    
    
            while(i < j && arr[j] >= k)     // 从右向左找第一个小于k的数
            {
    
    
                j--;
            }
 
            if(i < j)
            {
    
    
                arr[i++] = arr[j];
            }
 
            while(i < j && arr[i] < k)      // 从左向右找第一个大于等于k的数
            {
    
    
                i++;
            }
 
            if(i < j)
            {
    
    
                arr[j--] = arr[i];
            }
        }
 
        arr[i] = k;
 
        // 递归调用
        QuickSort(arr, low, i - 1);     // 排序k左边
        QuickSort(arr, i + 1, high);    // 排序k右边
    }
}

// 查找未出现的最小正整数的函数
int find(int a[],int n){
    
    
	int k,i,c;
	k = 1;
	QuickSort(a, 0, n-1);
	for(i=0;i<n;i++) {
    
    
		if(a[i] == k){
    
    
				k++;
			} else {
    
    
				break;
			}
		}
	c = k;
	return c;
}

int main() {
    
    
	int a[100],i,n,res;
	printf("请输入数组个数:");
	scanf("%d",&n);
	printf("请输入每个元素的值:\n");
	for(i=0;i<n;i++){
    
    
		scanf("%d",&a[i]);
	} 
	
	res = find(a,n);
	printf("最大正整数是: %d\n",res);
	return 0;
}

其实可以看出,当数组是有序的时候,会使得题目简单很多,而时间复杂度也就是排序的时间复杂度。(包括写其他题目的时候也有这样的感觉)。大一学数据结构的时候不明白为什么排序那么重要,而现在明白了,不断地改进排序的算法,使得时间复杂度尽可能小是有它的道理的!

猜你喜欢

转载自blog.csdn.net/weixin_47505105/article/details/123459971