【趣味算法题】找到缺失的最小正整数

【题目描述】

有一个随机序列的数组,找到其中缺失的最小正整数

举例如下,在[1,  2,  0] 中,该最小正整数应为3

在[3,  4,  -1,  1]中,该最小正整数应该为2

【解题思路】

如果允许开辟任意大小的空间,易得用桶的思想可以解决这题

简单的说,开辟一个数组,从1扫过来如果不存在那么break输出即可

如果对空间的要求是O(1) ,利用桶排序接下来有一个非常漂亮的解决方法:

我们可以把每个数字放在其该放的地方。什么意思呢?

比如 A[0] = 1, A[1] = 2, A[2] = 3, 诸如此类

然后放好之后从1扫过来如果不存在那么break输出即可

关键就是在于,如何将每个数字放在其该放的地方呢

方法如下:

如果 A[i] 是合法的数 (合法的意思是 A[i] > 0 && A[i] < n)

那么A[i] 应该放的位置为 A[A[i] - 1] 才对。

如果当然的 A[i] 不在 A[A[i] - 1] 的话,那么swap (A[i], A[A[i] - 1]) 即可

这到题目就是利用这个思路解决,如果碰到重复出现的数字也是可以解决 :)

【算法效率分析】

O(1) space, and O(n) time

My Source Code:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        bucket_sort (nums);

        for (int i = 0; i < nums.size (); ++i) {
            if (nums[i] != i + 1) {
                return i + 1;
            }
        }

        return nums.size () + 1;
    }

    void bucket_sort (vector <int> & nums) {
        for (int i = 0; i < nums.size (); ++i) {
            while (nums[i] != i + 1) {
                if (nums[i] < 0 || nums[i] > nums.size () ||                     nums[i] == nums[nums[i] - 1]) {
                        break;
                    }
                cout << "i = " << i << "\t" << nums[i] << "\t" << nums[nums[i] - 1] << endl;
                swap (nums[i], nums[nums[i] - 1]);
                cout << "\t";
                for (int j = 0; j < nums.size (); ++j) {
                    cout << nums[j] << " ";
                }
                cout << endl << endl;
            }
        }
    }
};

int main () {

    Solution sl;
    vector <int> vc;
    vc.push_back (3);
    vc.push_back (-4);
    vc.push_back (2);
    vc.push_back (1);
    vc.push_back (5);

    cout << sl.firstMissingPositive (vc);

    return 0;
}

推荐阅读文章:

三种线性排序算法 计数排序、桶排序与基数排序

https://www.byvoid.com/blog/sort-radix/

时间: 2024-11-06 07:27:50

【趣味算法题】找到缺失的最小正整数的相关文章

FCC 中级算法题 找到缺失的字母

Missing letters 从传递进来的字母序列中找到缺失的字母并返回它. 如果所有字母都在序列中,返回 undefined. String.charCodeAt() String.fromCharCode() 思路: (1)直接将字符串转化为数字按顺序放入数组arr中; (2)如果没有缺失的字母,数组的最大值减最小值加1应该等于数组的长度,利用这一特点,创建这样一个理想的没有缺失的数组newArr; (3)从newArr中剔除与数组arr相同的元素,这样就找到了丢失字母的数字,由于可能不止

【趣味算法题】在数组中,对于所有元素,找出比当前元素大的下一个元素

在数组中,对于所有元素,找出比当前元素大的下一个元素 意思就是,eg.  数组为 3 1 2 5 4 6 7 那么我们需要得到的结果应该是  5 2 5 6 6 7 -1 解决方法如下: 暴力匹配: O (n ^ 2 ) 的效率对所有元素匹配过去,效率非常的低 经过提示, 我想到的一种 O ( nlg n ) 效率的算法 只需要对数组扫描一次,我们用一个 Priority_queue 来得到当前最小的元素 Prority_queue 存放的数据结构为: struct sc { int key,

《剑指Offer》算法题——“旋转数组”的最小数字

题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个非递减序列的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. //这里说的非递减并不是乱序的,也是递增的,只不过递增的过程中可以有相同数字而已 #include <iostream> #include <vector> using namespace std; class Solution { public: int minNu

趣味Java算法题(附答案)

[程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? //这是一个菲波拉契数列问题 public class lianxi01 { public static void main(String[] args) { System.out.println("第1个月的兔子对数:    1"); System.out.println("第2个月的兔子对数:    1"

笔试算法题(55):快速排序实现之非递归实现,最小k值选择(non-recursive version, Minimal Kth Selection of Quick Sort)

议题:快速排序实现之五(非递归实现,短序列优先处理,减少递归栈大小) 分析: 算法原理:此算法实现适用于系统栈空间不足够快速排序递归调用的需求,从而使用非递归实现快速排序算法:使用显示下推栈存储快速排序中的每一次划分结果 (将left和right都压入堆栈),并且首先处理划分序列较短的子序列(也就是在得到一次划分的左右部分时,首先将长序列入栈,然后让段序列入栈), 这样可以保证当快速排序退化的线性效率的时候,栈大小仍旧在㏒N范围内.算法策略类似于最小子树优先遍历规则: 弱势:当序列已经就绪,每次

数组中未出现的最小正整数(算法)

1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 int s[100]; 5 int main() 6 { 7 int l,r; 8 int n; 9 while(scanf("%d",&n),n) 10 { 11 for(int i=0;i<n;i++) 12 scanf("%d",s+i); 13 l=0; 14 r=n; 15 while

第一部分:趣味算法入门;第八题:冒泡排序(并与选择排序对比)

100个不同类型的python语言趣味编程题 在求解的过程中培养编程兴趣,拓展编程思维,提高编程能力. 第一部分:趣味算法入门:第八题: 8.冒泡排序:对N个整数(数据由键盘输入)进行升序排序 冒泡排序的思想:首先从表头开始往后扫描数组,在扫描的过程中逐对比较相邻的俩个元素的大小.若相邻的两个元素中,前面的元素大于后面的元素,则将它们互换,称之为消去了一个逆序,在扫描的过程中不断的将两相邻元素中的大者往后移动,最后就将数组中的最大者换到了表的最后,然后在剩下的数组元素中(n-1)个元素重复上面的

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

[算法]数组中未出现的最小正整数

题目: 给定一个无序整型数组arr,找到数组中未出现的最小正整数. 例如: arr=[-1,2,3,4].返回1. arr=[1,2,3,4].返回5. 要求时间复杂度为O(N),空间复杂度为O(1). 解答: 在遍历arr之前先生成两个变量.变量l表示遍历到目前为止,数组arr已经包含的正整数范围是[1,l],所以在没有开始之前l=0,表示arr没有包含任何正整数.变量r表示遍历到目前为止,在后续出现最优状况的情况下,arr可能包含的正整数范围是[1,r],所以在没有开始之前,令r=N,r同时