一个Google的面试题

转自:http://www.mitbbs.com/article_t/JobHunting/32604553.html


Given a list of words, find two strings S & T such that:

    a. S & T have no common character

    b. S.length() * T.length() is maximized



没想到什么比O(n^2)好的方法,毕竟是partially order, 不是total order
但到不了O(n^2*l), 只是O(n^2 + nl).只需要过一遍string计算sign就可以了,另外将
数组按长度从大到小排列,提前剪枝也可以优化一些,但复杂度还是O(n^2)

const int INT_BITS = sizeof(int) * 8;
const int DATA_LEN = 256/INT_BITS;
class Int256 {
    
    vector<int> data;
public:
    Int256(): data(DATA_LEN, 0) {
    }
    Int256(string s): data(DATA_LEN, 0) {
        for (auto c: s) {
            Set((unsigned char)c);
        }
    }
    void Set(int l) {
        data[l/INT_BITS] |= 1 << (l%INT_BITS);
    }
    bool IsZero() const {
        for (int i = 0; i < DATA_LEN; ++i) {
            if (data[i]) return false;
        }
        return true;
    }
    Int256 BitAnd(const Int256& rhs) {
        Int256 results;
        for (int i = 0; i < DATA_LEN; ++i) {
            results.data[i] = data[i] & rhs.data[i];
        }
        return results;
    }
    bool operator==(const Int256& rhs) {
        for (int i = 0; i < DATA_LEN; ++i) {
            if (data[i] != rhs.data[i]) return false;
        }
        return true;
    }
};

struct Node {
    string s;
    Int256 sign;
    Node(string s1):s(s1), sign(s1){};
};
bool CompareNodes(const Node& lhs, const Node& rhs) {
    return lhs.s.size() > rhs.s.size();
}
int NoOverlapMultply(vector<string> ss) {
    vector<Node> nodes;
    for (string s: ss) {
        nodes.push_back(Node(s));
    }
    sort(nodes.begin(), nodes.end(), CompareNodes); 
    int curMax = 0;
    for (int i = 0; i < nodes.size(); ++i) {
        int iLen = nodes[i].s.size();
        Int256 iSign = nodes[i].sign;
        for (int j = i + 1; j < nodes.size(); ++j) {
            if (nodes[j].s.size() * iLen <= curMax) break;
            Int256 andSign = iSign.BitAnd(nodes[j].sign);
            if (andSign.IsZero()) {
                curMax = nodes[j].s.size() * iLen;
                break;
            }
        }
    }
    return curMax;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值