在有限空间的数组中查找不同值的数量

时间:2014-07-15 16:54:51

标签: arrays algorithm sorting

如果在 HDD = {1,1,5,7,8,1,6,10,20,1}上分配了一个非常大的数组,我们需要找出有多少不同价值存在。所提到的阵列的解决方案是总共7个,7个不同的数字{1,5,6,7,6,10,20}。没有必要保存数字。

给出了一些提示,我需要在HDD和RAM上工作。但是,HDD明显大于RAM。因此,当所有值都不同时,不能保留哈希表和链表。根据我的理解,我需要分配K个固定大小的数组(每个m个元素)。之后,我需要填充所有k个数组,将每个数组排序。然后比较它们并计算不同的部分并再次填充它们直到完成HDD上分配的所有值。我的问题是最后一部分,一旦数组排序后我需要做什么?

编辑:rutime示例,HDD可能包含10 ^ 10条记录,RAM可能只包含10 ^ 5, 并且K = 10,M = 10.对于每个处理的数组,需要读取该特定数组的下一个M值。

应该只有一个计数器,说明不同值的数量。最大的数字可能是N

感谢

1 个答案:

答案 0 :(得分:0)

这是我的解决方案。我定义了2个向量,第一个向量表示Hdd数据,另一个向量表示Hdd向量内的偏移。

   #include <iostream>
    #include <fstream>
    #include <vector>
    #include <algorithm>
    #include <stdio.h>
    #include <stdlib.h>
    #include <iterator>
    #include <direct.h>

    #define FILE_NAME "\\data.txt"
    #define ROWS        10
    #define MAX_LINE    100
    #define ARRSIZE(arr) sizeof(arr) / sizeof(arr[0])

    class CPair
    {
    public:
        CPair(__int64 nOffset) : m_llOffset(nOffset), m_llCurOffset(nOffset), m_bChecked(0)
        { }

        __int64 m_llOffset;
        __int64 m_llCurOffset;
        bool    m_bChecked;
    };

    std::vector<long>       vecHDD;
    std::vector<CPair>  vecOffsets;

    long RetrieveValueFromHDD(__int64& i64Offset)
    {
        return vecHDD[(long)i64Offset];
    }

    void FindDistinct()
    {
        // calculate how many fragments within the HDD we've got
        long nFragments = (vecHDD.size() / ROWS);
        long nCount     = 0;

        while(nFragments > 0)
        {
            long nMinimum = INT_MAX;
            for(int i = 0; i < (int)vecOffsets.size(); i++)
            { // find the minimum number
                if((false == vecOffsets[i].m_bChecked) && (RetrieveValueFromHDD(vecOffsets[i].m_llCurOffset) < nMinimum))
                    nMinimum = vecHDD[(int)vecOffsets[i].m_llCurOffset];
            }

            // start changing indices for values equivalent to nMinimum
            for(int i = 0; i < (int)vecOffsets.size(); i++)
            {
                bool bKeepChanging  = true;
                for(int j = 0; j < ROWS && (true == bKeepChanging) && ((vecOffsets[i].m_llCurOffset - vecOffsets[i].m_llOffset) < ROWS); j++)
                {
                    if(RetrieveValueFromHDD(vecOffsets[i].m_llCurOffset) == nMinimum)
                        vecOffsets[i].m_llCurOffset++;
                    else // terminate correct fragment
                        bKeepChanging = false; 
                }

                if  ((vecOffsets[i].m_llCurOffset - vecOffsets[i].m_llOffset) >= ROWS && (false == vecOffsets[i].m_bChecked))
                {
                    vecOffsets[i].m_bChecked = true;
                    nFragments--;
                }
            }

            std::cout << "distinct number:" << nMinimum << '\n';
            nCount++;
        }

        std::cout << "total distinctive numbers: " << nCount;
    }

    void main()
    {
        FILE*       pf;
        std::string str;
        long        nCount          = 0;
        long        arr[ROWS]       = { 0 };
        __int64     i64Offset       = 0;
        char        pDirectoryPath[256 * 2];

        // get current location
        _getcwd(pDirectoryPath, ARRSIZE(pDirectoryPath));
        strcat_s(pDirectoryPath, FILE_NAME);
        fopen_s(&pf, pDirectoryPath, "r");
        if (pf == NULL)
            return;

        std::vector<CPair>      vecPos;
        char                    pLine[MAX_LINE];
        while (0 != fgets(pLine, MAX_LINE, pf))
        {
            arr[nCount] = atoi(pLine);
            nCount++;
            if (nCount == ROWS)
            {
                // create the offset array, save the start of each fragment
                vecOffsets.push_back(CPair(i64Offset));
                std::vector<long> vec(arr, arr + ARRSIZE(arr));
                std::sort(vec.begin(), vec.end());

                // continue creating the HDD array, it will hold sorted fragments.
                vecHDD.insert(vecHDD.end(), vec.begin(), vec.end());
                i64Offset   += nCount;
                nCount      = 0;
            }
        }

        FindDistinct();
        fclose(pf);
    }