【问题标题】:Find unique number among 3n+1 numbers [duplicate]在3n + 1个数字中找到唯一的数字[重复]
【发布时间】:2015-07-06 04:26:34
【问题描述】:

我在一次采访中被问到这个问题。

鉴于此,有 3n+1 个数字。这些数字中有 n 个以三胞胎出现,只有 1 个出现单次。我们如何在线性时间内找到唯一的数字,即 O(n) ?数字未排序。

请注意,如果有 2n+1 个数字,其中 n 个成对出现,我们可以对所有数字进行异或运算以找到唯一的数字。面试官告诉我,可以通过位操作来完成。

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 你面试的目的是什么?
  • 内存限制和数字范围怎么样?

标签: algorithm


【解决方案1】:
  1. 计算每个位在 3n+1 个数字的集合中出现的次数。
  2. 减少每个位计数模 3。
  3. 剩下的是单个数字的位模式。

哦,dreamzor(上图)已经打败了我。

【讨论】:

    【解决方案2】:

    您可以发明一个 3 进制 XOR(称为 XOR3)运算,该运算以 3 为底而不是 2 为底,并且只需将每个 3 进制数字取模 3(通常 XOR 取 2 进制数字取模 2)。

    然后,如果您以这种方式XOR3 所有数字(首先将它们转换为 3nary),您将得到唯一的数字(以 3 为底,因此您需要将其转换回来)。

    不过,复杂度并不完全是线性的,因为从/到基数 3 的转换需要额外的对数时间。但是,如果数字的范围是恒定的,那么转换时间也是恒定的。

    C++ 上的代码(故意冗长):

    vector<int> to_base3(int num) {
      vector<int> base3;
      for (; num > 0; num /= 3) {
        base3.push_back(num % 3);
      }
      return base3;
    }
    
    int from_base3(const vector<int> &base3) {
      int num = 0;
      for (int i = 0, three = 1; i < base3.size(); ++i, three *= 3) {
        num += base3[i] * three;
      }
      return num;
    }
    
    int find_unique(const vector<int> &a) {
      vector<int> unique_base3(20, 0); // up to 3^20
      for (int num : a) {
        vector<int> num_base3 = to_base3(num);
        for (int i = 0; i < num_base3.size(); ++i) {
          unique_base3[i] = (unique_base3[i] + num_base3[i]) % 3;
        }
      }
    
      int unique_num = from_base3(unique_base3);
      return unique_num;
    }
    
    int main() {
      vector<int> rands { 1287318, 172381, 5144, 566546, 7123 };
      vector<int> a;
      for (int r : rands) {
        for (int i = 0; i < 3; ++i) {
          a.push_back(r);
        }
      }
      a.push_back(13371337); // unique number
    
      random_shuffle(a.begin(), a.end());
    
      int unique_num = find_unique(a);
      cout << unique_num << endl;
    }
    

    【讨论】:

    • 为什么要转换成三进制数?它比 theorish 的解决方案有什么额外的优势吗?
    • @parvez_bai 不,这只是我的第一个想法,因为与二进制/三元异或的简单类比,他的解决方案确实更容易实现。
    【解决方案3】:
    byte [] oneCount = new byte [32];
    
    int [] test = {1,2,3,1,5,2,9,9,3,1,2,3,9};
    
    for (int n: test) {
        for (int bit = 0; bit < 32; bit++) {
            if (((n >> bit) & 1) == 1) {
                oneCount[bit]++;
                oneCount[bit] = (byte)(oneCount[bit] % 3);
            }
        }
    }
    
    int result = 0;
    int x = 1;
    
    for (int bit = 0; bit < 32; bit++) {
        result += oneCount[bit] * x;
        x = x << 1;
    }
    
    System.out.print(result);
    

    看起来我在编码时,其他人给出了主要想法

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-07
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      • 2020-09-18
      • 2023-04-10
      • 2017-12-19
      • 2011-01-30
      相关资源
      最近更新 更多