zoukankan      html  css  js  c++  java
  • 《剑指offer》第四十题:最小的k个数

    // 面试题40:最小的k个数
    // 题目:输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8
    // 这8个数字,则最小的4个数字是1、2、3、4。
    
    #include <cstdio>
    #include "Array.h"
    
    #include <set>
    #include <vector>
    #include <iostream>
    #include <functional>
    
    using namespace std;
    
    // ====================方法1====================
    // 基于随机快速排序算法, 
    void GetLeastNumbers_Solution1(int* input, int n, int* output, int k)
    {
        if (input == nullptr || output == nullptr || n < k || n <= 0 || k <= 0)
            return;
    
        int start = 0;
        int end = n - 1;
        int index = Partition(input, n, start, end);
        while (index != k - 1) //只要随机排序的数字是第k个数字就跳出
        {
            if (index > k - 1)
            {
                end = index - 1;
                index = Partition(input, n, start, end);
            }
            else
            {
                start = index + 1;
                index = Partition(input, n, start, end);  //index指的是在input里的
            }
        }
        for (int i = 0; i <= index; ++i)
            output[i] = input[i];
    }
    
    // ====================方法2====================
    typedef multiset<int, std::greater<int> >            intSet;
    typedef multiset<int, std::greater<int> >::iterator  setIterator;
    
    void GetLeastNumbers_Solution2(const vector<int>& data, intSet& leastNumbers, int k)
    {
        leastNumbers.clear();
        
        if (k < 1 || data.size() < k)
            return;
    
        vector<int>::const_iterator iter = data.begin();  //数据迭代器
        for (; iter != data.end(); ++iter)
        {
            if (leastNumbers.size() < k)  //堆未满
                leastNumbers.insert(*iter);
            else
            {
                setIterator iterGreatest = leastNumbers.begin();  //堆迭代器
    
                if (*iter < *(leastNumbers.begin()))  //查看当前数是否小于堆中最大数
                {
                    leastNumbers.erase(iterGreatest);  //擦除最大数
                    leastNumbers.insert(*iter);  //插入当前数
                }
            }
        }
    }
    // ====================测试代码====================
    void Test(const char* testName, int* data, int n, int* expectedResult, int k)
    {
        if (testName != nullptr)
            printf("%s begins: 
    ", testName);
    
        vector<int> vectorData;
        for (int i = 0; i < n; ++i)
            vectorData.push_back(data[i]);
    
        if (expectedResult == nullptr)
            printf("The input is invalid, we don't expect any result.
    ");
        else
        {
            printf("Expected result: 
    ");
            for (int i = 0; i < k; ++i)
                printf("%d	", expectedResult[i]);
            printf("
    ");
        }
    
        printf("Result for solution1:
    ");
        int* output = new int[k];
        GetLeastNumbers_Solution1(data, n, output, k);
        if (expectedResult != nullptr)
        {
            for (int i = 0; i < k; ++i)
                printf("%d	", output[i]);
            printf("
    ");
        }
    
        delete[] output;
    
        printf("Result for solution2:
    ");
        intSet leastNumbers;
        GetLeastNumbers_Solution2(vectorData, leastNumbers, k);
        printf("The actual output numbers are:
    ");
        for (setIterator iter = leastNumbers.begin(); iter != leastNumbers.end(); ++iter)
            printf("%d	", *iter);
        printf("
    
    ");
    }
    
    // k小于数组的长度
    void Test1()
    {
        int data[] = { 4, 5, 1, 6, 2, 7, 3, 8 };
        int expected[] = { 1, 2, 3, 4 };
        Test("Test1", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int));
    }
    
    // k等于数组的长度
    void Test2()
    {
        int data[] = { 4, 5, 1, 6, 2, 7, 3, 8 };
        int expected[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
        Test("Test2", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int));
    }
    
    // k大于数组的长度
    void Test3()
    {
        int data[] = { 4, 5, 1, 6, 2, 7, 3, 8 };
        int* expected = nullptr;
        Test("Test3", data, sizeof(data) / sizeof(int), expected, 10);
    }
    
    // k等于1
    void Test4()
    {
        int data[] = { 4, 5, 1, 6, 2, 7, 3, 8 };
        int expected[] = { 1 };
        Test("Test4", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int));
    }
    
    // k等于0
    void Test5()
    {
        int data[] = { 4, 5, 1, 6, 2, 7, 3, 8 };
        int* expected = nullptr;
        Test("Test5", data, sizeof(data) / sizeof(int), expected, 0);
    }
    
    // 数组中有相同的数字
    void Test6()
    {
        int data[] = { 4, 5, 1, 6, 2, 7, 2, 8 };
        int expected[] = { 1, 2 };
        Test("Test6", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int));
    }
    
    // 输入空指针
    void Test7()
    {
        int* expected = nullptr;
        Test("Test7", nullptr, 0, expected, 0);
    }
    
    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();
        Test6();
        Test7();
    
        return 0;
    }
    测试代码

    分析:大师,我悟了。

    时间复杂度O(n)。

    class Solution {
        void Swap(vector<int> &input, int index1, int index2)
        {
            int temp = input[index1];
            input[index1] = input[index2];
            input[index2] = temp;
        }
        int Partition(vector<int> &input, int n, int start, int end)
        {
            int index = rand() % (end - start + 1) + start;
            Swap(input, index, end);
            
            int small = start - 1;
            for (index = start; index < end; ++index)
            {
                if (input[index] < input[end])
                {
                    ++ small;
                    if (small != index)
                        Swap(input, small, index);
                }
            }
            ++small;
            Swap(input, small, end);
            return index;
        }
    public:
        vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
            
            int n = (int)input.size();
            vector<int> leastNumber;
            
            if (n < k || n <= 0 || k <= 0)
                return leastNumber;
            
            int start = 0;
            int end = n - 1;
            int index = Partition(input, n, start, end);
            while (index != k - 1)
            {
                if (index > k - 1)
                {
                    end  = index - 1;
                    index = Partition(input, n, start, end);
                }
                else
                {
                    start  = index + 1;
                    index = Partition(input, n, start, end);
                }
            }
            for (int i = 0; i <= index; ++i)
                leastNumber.push_back(input[i]);
            return leastNumber;
        }
    };
    牛客网提交代码
  • 相关阅读:
    Yii框架2.0 数据库操作初接触
    Yii框架2.0的视图和widgets表单的使用
    Yii框架2.0的安装过程
    监控之snmpd 服务
    在HTML里面HEAD部分的META元素要表达的内容是什么
    被table单元格colspan属性折磨了
    excel模版从xp复制到win7系统后出现错误 运行时错误 '429' ActiveX 部件不能创建对象
    oracle左连接连表查询
    Nginx 关闭防火墙
    左连接不能与or否则in连用
  • 原文地址:https://www.cnblogs.com/ZSY-blog/p/12631074.html
Copyright © 2011-2022 走看看