落单元素查找

描述

整型数组中除一个元素外其它元素都重复出现 n 次,找出落单的元素,需保证时间复杂度在 O(n) 以内。

考虑 n = 2, n = 3 的情形;
考虑除了一个元素出现 m 次,其它元素出现 n 次的情形, 其中 m != n。

示例:

给定数组 array = [1, 1, 1, 11, 11, 3, 3, 3, 4, 4, 4], 所以 m=2, n=3, 查找到目标元素为 11。

Delphi 算法

/*
 * @param array 目标数组
 * @param len 数组元素个数
 * @param n 普通元素出现次数
 * @return 查找到的特殊出现次数的元素值
 * */
int find(int array[], int len, int n)
{
    int ret = 0;

    for (int i=0, tmp = 0; i<32; ++i, tmp=0)
    {
        for (int j=0; j<len; ++j)
        {
            tmp += (array[j] >> i) & 0x01;
        }

        ret |= !!(tmp % n) << i;
    }
    
    return ret;
}

原理

将目标数组分解为二进制矩阵后进行组合。

image.png

==> 数组中各元素 [0-31] 位累加

image.png

==> 累加和取余普通元素出现次数

image.png

==> 非0值转化为1

image.png

==> 转换为 int
11

栈实现及最小元素获取

描述:

初始问题:实现一个栈;
扩展问题1:添加一个操作 min(),获取当前栈中最小元素值;
扩展问题2:min() 的时间复杂度是否最优?为什么?
扩展问题3:整体空间复杂度是否最优?为什么?

方法一:借助辅助数据结构

template<typename T>
class stack
{
public:
    void push(const T &obj)
    {
        m_mainList.push_front(obj);

        if ((m_minList.size() == 0) || (obj < m_minList.front()))
            m_minList.push_back(obj);
        else
            m_minList.push_back(m_mainList.front());
    }

    T top() const
    {
        return m_mainList.back();
    }

    void pop()
    {
        m_mainList.pop_back();
        m_minList.pop_back();
    }

    T min() const
    {
        return m_minList.back();
    }

    size_t size() const
    {
        return m_mainList.size();
    }

private:
    list<T> m_mainList;
    list<T> m_minList;
};
min() 时间复杂度:O(1)
min() 空间复杂度:O(n) [辅助链表]

方法二:仅适用于整形元素

template<int MAX>
class stack_int
{
public:
    void push(const int v)
    {
        int d = m_min - v;

        m_list.push_back(d);

        if (d > 0)
            m_min = v;
    }

    int top()
    {
        int ret = 0;
        int d = m_list.back();

        if (d < 0)
        {
            ret = m_min - d;
        }
        else
        {
            ret = m_min;
            m_min = m_min + d;
        }

        return ret;
    }

    void pop()
    {
        int d = m_list.back();

        if (d > 0)
        {
            m_min = m_min + d;
        }

        m_list.pop_back();
    }

    int min() const
    {
        return m_min;
    }

    size_t size() const
    {
        return m_list.size();
    }

private:
    list<int> m_list;
    int m_min = MAX;
};
min() 时间复杂度:O(1)
min() 空间复杂度:O(1)

此算法仅适用于整形元素(char,short,int,long 等);
浮点型元素的计算及存储是不精确的,因此无法使用此数据结构。


TianSong
734 声望138 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧