楼主: EddieStallworth
跳转到指定楼层
上一主题 下一主题
收起左侧

请教一道国内面试算法题,很短,没做出来

🔗
empy 2017-10-29 06:49:44 | 只看该作者
全局:
yanshuo619 发表于 2017-10-29 06:40
要求只是返回长度 所以并不需要知道具体是哪个没出现。有了input长度直接可以算出来每个长度应该有多少组合 ...

set长度最高为log4(n),所以遍历每个元素时遍历log4(n)次,总的时间复杂度为nlog4(n)。
回复

使用道具 举报

🔗
chowhound 2017-10-29 06:58:46 | 只看该作者
全局:
empy 发表于 2017-10-29 06:49
set长度最高为log4(n),所以遍历每个元素时遍历log4(n)次,总的时间复杂度为nlog4(n)。

每个元素只是跟前一个状态合起来仍set里,为啥会需要遍历呢
回复

使用道具 举报

🔗
empy 2017-10-29 07:10:04 | 只看该作者
全局:
yanshuo619 发表于 2017-10-29 06:58
每个元素只是跟前一个状态合起来仍set里,为啥会需要遍历呢
  1. int leastLen(string str) {
  2.         int strLen = str.length();
  3.         int maxLen = log(strLen) / log(4);
  4.         vector<unordered_set<string>> comb(maxLen);
  5.         for (int i = 0; i < strLen; i++)
  6.                 for (int j = 0; j <maxLen && i-j>=0; j++)
  7.                         comb[j].insert(str.substr(i - j, j+1));
  8.         int res = maxLen + 1;
  9.         for (int i = 0; i < maxLen; i++)
  10.                 if (comb[i].size() < pow(4, i + 1))
  11.                         res = i + 1;
  12.         return res;
  13. }
复制代码
时间复杂度 nlog4(n)

补充内容 (2017-10-29 07:13):
最后那个if应该是
                if (comb[i].size() < pow(4, i + 1)) {
                        res = i + 1;
                        break;
                }
回复

使用道具 举报

🔗
 楼主| EddieStallworth 2017-10-29 07:13:43 | 只看该作者
全局:
k1938slll 发表于 2017-10-29 05:03
好难?! Google的题吗

百度的 字数字数
回复

使用道具 举报

🔗
 楼主| EddieStallworth 2017-10-29 07:15:09 | 只看该作者
全局:
fangdanzai 发表于 2017-10-29 05:10
先把所有可能的组合存在hash里 然后用长度从1到length遍历?

不能暴力解啊 那还有啥意思了..
回复

使用道具 举报

🔗
 楼主| EddieStallworth 2017-10-29 07:16:21 | 只看该作者
全局:
yanshuo619 发表于 2017-10-29 06:40
要求只是返回长度 所以并不需要知道具体是哪个没出现。有了input长度直接可以算出来每个长度应该有多少组合 ...

面试完了以后我又想了一下 应该这样做是可行的
回复

使用道具 举报

🔗
无量塔 2017-10-29 07:40:08 | 只看该作者
全局:
empy 发表于 2017-10-29 07:10
时间复杂度 nlog4(n)

补充内容 (2017-10-29 07:13):

substr也是需要时间的
回复

使用道具 举报

🔗
mmymichael 2017-10-29 07:43:10 | 只看该作者
全局:
twitter OA questions. i have seen this question last year
回复

使用道具 举报

🔗
empy 2017-10-29 07:58:40 | 只看该作者
全局:
无量塔 发表于 2017-10-29 07:40
substr也是需要时间的

即使substr的时间复杂度是O(n),总的复杂度也不过是多乘一个log4(n)
回复

使用道具 举报

🔗
magicsets 2017-10-29 16:40:40 | 只看该作者
全局:
用suffix tree可以时间O(n),空间O(n)。具体就是先O(n)建树,然后从树根逐层BFS做一些判断。不过建树算法非常复杂。

其实看到ACGT,第一反应是压缩索引技术,例如FM-index (burrow wheeler transform),不过对于这一题好像不适用。


估计面试想要的做法是把每个字符压缩为2bit编码,然后用一个32位整数编码子串(可以处理最多4*10^9长度的输入,更长的话要用64位整数)。
在编码后,就不需要用hash set了,因为压缩后的整数分布是稠密的,只需要用一个bitmap。

参考代码如下:

  1. #include <cstddef>
  2. #include <cstdint>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <iostream>
  6. #include <string>
  7. #include <vector>

  8. // BitSet的简单实现
  9. class BitSet {
  10. public:
  11.   explicit BitSet(const std::size_t num_bits)
  12.       : data_array_size_((num_bits >> kHigherOrderShift) +
  13.                          (num_bits & kLowerOrderMask ? 1 : 0)),
  14.         data_array_(static_cast<std::size_t*>(std::malloc(data_array_size_ * kDataSize))) {
  15.     std::memset(data_array_, 0, data_array_size_ * kDataSize);
  16.   }

  17.   ~BitSet() {
  18.     std::free(data_array_);
  19.   }

  20.   inline void setBit(const std::size_t bit_num) const {
  21.     data_array_[bit_num >> kHigherOrderShift] |= kTopBit >> (bit_num & kLowerOrderMask);
  22.   }

  23.   inline std::size_t onesCount() const {
  24.     std::size_t count = 0;
  25.     for (std::size_t array_idx = 0; array_idx < data_array_size_; ++array_idx) {
  26.       count += __builtin_popcountl(data_array_[array_idx]);
  27.     }
  28.     return count;
  29.   }

  30. private:
  31.   static constexpr std::size_t kDataSize = sizeof(std::size_t);
  32.   static constexpr std::size_t kLowerOrderMask = (kDataSize << 3) - 1;
  33.   static constexpr std::size_t kHigherOrderShift = kDataSize == 4 ? 5 : 6;
  34.   static constexpr std::size_t kOne = 1ull;
  35.   static constexpr std::size_t kTopBit = kOne << kLowerOrderMask;

  36.   const std::size_t data_array_size_;
  37.   std::size_t *data_array_;
  38. };

  39. int Solve(const std::string &dna) {
  40.   // 编码索引
  41.   std::uint32_t dna2code[128];
  42.   memset(dna2code, 0, sizeof(dna2code));
  43.   dna2code[(int)'a'] = dna2code[(int)'A'] = 0;
  44.   dna2code[(int)'c'] = dna2code[(int)'C'] = 1;
  45.   dna2code[(int)'g'] = dna2code[(int)'G'] = 2;
  46.   dna2code[(int)'t'] = dna2code[(int)'T'] = 3;

  47.   // 编码
  48.   constexpr std::size_t kNumBitsInWord = 32;
  49.   constexpr std::size_t kNumCodesInWord = kNumBitsInWord / 2;

  50.   std::vector<std::uint32_t> words;
  51.   std::size_t shift = 0;
  52.   std::uint32_t word = 0;
  53.   for (const unsigned char c : dna) {
  54.     word |= dna2code[c] << shift;
  55.     if (shift == kNumBitsInWord - 2) {
  56.       words.emplace_back(word);
  57.       shift = 0;
  58.       word = 0;
  59.     } else {
  60.       shift += 2;
  61.     }
  62.   }
  63.   if (shift != 0) {
  64.     words.emplace_back(word);
  65.   }

  66. //  for (const std::uint32_t w : words) {
  67. //    std::cout << std::bitset<32>(w) << "\n";
  68. //  }

  69.   // 枚举长度
  70.   const std::size_t dnaL = dna.length();
  71.   std::size_t subL = 1;
  72.   while (true) {
  73.     const std::size_t max_combinations = 1ull << (subL * 2);
  74.     if (max_combinations > dnaL) {
  75.       break;
  76.     }

  77.     // 遍历子串
  78.     BitSet existence(max_combinations);
  79.     const std::uint64_t sub_mask = max_combinations - 1;

  80.     std::uint64_t buffer = words.front();
  81.     for (std::size_t i = 0; i < words.size() - 2; ++i) {
  82.       buffer |= static_cast<std::uint64_t>(words[i+1]) << kNumBitsInWord;
  83.       for (std::size_t k = 0; k < kNumCodesInWord; ++k) {
  84.         existence.setBit(buffer & sub_mask);
  85.         buffer >>= 2;
  86.       }
  87.     }
  88.     buffer |= static_cast<std::uint64_t>(words.back()) << kNumBitsInWord;
  89.     const std::size_t last = dnaL % kNumCodesInWord;
  90.     const std::size_t num_residual =
  91.         (kNumCodesInWord + (last == 0 ? kNumCodesInWord : last) - subL + 1);
  92.     for (std::size_t k = 0; k < num_residual; ++k) {
  93.       existence.setBit(buffer & sub_mask);
  94.       buffer >>= 2;
  95.     }

  96.     if (existence.onesCount() != max_combinations) {
  97.       break;
  98.     }
  99.     ++subL;
  100.   }
  101.   return subL;
  102. }
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表