两个数字是否包含相同的数字

时间:2017-11-11 14:30:51

标签: java algorithm permutation

好的,所以我想知道如何检查两个数字是否具有相同的数字,例如2112也可以,12332313,但1231233不是,这意味着数字是另一个的排列数字的数字。

我知道如何使用数组或字符串或映射,但问题是,我不想用其中任何一个来做,如果存在另一个解决方案

阵列/地图的解决方案:

Map<int, int> counter = new HashMap<int, int>();
for (int i = 0; i < 10; i++)
    counter.put(i, 0);
int x = 2421, y = 4223; // testcase
while (x > 0 || y > 0) {
    if (x == 0 || y == 0) // if they are not the same length, one will be 0 and thus they are not permutations
        return false;
    counter.put(x%10, counter.get(x%10) + 1);
    counter.put(y%10, counter.get(y%10) - 1);
    x /= 10;
    y /= 10;
}
// For each digit we added 1 to the counter if it was found in `x`
// and subtract 1 if it was found in `y`.
return counter.values() == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

现在,数组方法完全相同,因为使用数字0-9的映射与使用map的键作为数组中的索引相同。没有任何数据结构的解决方案对我来说远非理想:

private static boolean haveSameDigits(int x, int y) {
    // Because we are not allowed to use maps, declare 10 vars...
    int c0 = 0;
    int c1 = 0;
    int c2 = 0;
    int c3 = 0;
    int c4 = 0;
    int c5 = 0;
    int c6 = 0;
    int c7 = 0;
    int c8 = 0;
    int c9 = 0;

    while (x > 0 || y > 0) {
      if (x == 0 || y == 0)
          return false;
      if ((x % 10) == 0)
          c0++;
      else if ((x % 10) == 1)
          c1++;
      else if ((x % 10) == 2)
          c2++;
      else if ((x % 10) == 3)
          c3++;
      else if ((x % 10) == 4)
          c4++;
      else if ((x % 10) == 5)
          c5++;
      else if ((x % 10) == 6)
          c6++;
      else if ((x % 10) == 7)
          c7++;
      else if ((x % 10) == 8)
          c8++;
      else if ((x % 10) == 9)
          c9++;
      if ((y % 10) == 0)
          c0--;
      else if ((y % 10) == 1)
          c1--;
      else if ((y % 10) == 2)
          c2--;
      else if ((y % 10) == 3)
          c3--;
      else if ((y % 10) == 4)
          c4--;
      else if ((y % 10) == 5)
          c5--;
      else if ((y % 10) == 6)
          c6--;
      else if ((y % 10) == 7)
          c7--;
      else if ((y % 10) == 8)
          c8--;
      else if ((y % 10) == 9)
          c9--;

      x /= 10;
      y /= 10;
    }

    return c0 == 0 && c1 == 0 && c2 == 0 && c3 == 0 && c4 == 0 && c5 == 0 && c6 == 0 && c7 == 0 && c8 == 0 && c9 == 0
}

我已经开始搜索它,但无论我输入什么,我最终得到了使用字符串或数组的解决方案。

我不是在寻找解决方案,我实际上并不想要它,我只需要提示这个方法。

添加更多信息:没有什么禁止我使用我想要的任何数据结构,这是我的程序,没有人会检查我做了什么。我就是那种喜欢学习新东西的人,所以我想知道是否有快速解决方案。

如评论中所述,可以迭代这两个数字并检查范围(0,9)中的每个数字,包括它们出现在字符串中的次数,但这显然会产生O(n*n)的时间复杂度,这是Traceback (most recent call last): File "<pyshell#5>", line 1, in <module> node._testadd() TypeError: _testadd() missing 1 required positional argument: 'self'不是最佳的。

2 个答案:

答案 0 :(得分:2)

您不希望转换为字符串,也不想使用任何帮助程序数据结构。那怎么样:从数字中创建一个哈希,格式为xor(2^d for every digit d in n)

例如,hash(3112)将是(二进制)1100

由于你不想要一个解决方案,这里有一些伪代码(又名Python):

def hash(n):
    r = 0
    while n > 0:
        d = n % 10    # last digit
        n = n // 10   # remaining digits
        r = r ^ 2**d  # xor with 2^d
    return r

def perm(n, m):
    return hash(n) == hash(m)

更新:结果证明上述情况不正常,因为XOR只能跟踪数字是偶数还是奇数次。相反,您可以使用多个素数创建哈希。这样,hash(3112)变为7 * 3 * 3 * 5。虽然这使用列表来保留前十个素数,但在检查单个数字对时不会创建任何新列表,数组或映射。另外,请记住,生成的哈希值可能非常大 - 大于Java的intlong类型。 (你可以采用另一个大素数的模数,但我不确定那个部分。)

primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
def hash(n):
    r = 1
    while n > 0:
        d = n % 10   # last digit
        n = n // 10  # remaining digits
        r = r * primes[d]
    return r

答案 1 :(得分:0)

您可以将int解析为字符串并使用.contains

进行检查
final List<Integer> intsForCheck = new ArrayList<>();

for (int i = 1; i < 180; i++)
    intsForCheck.add(i);

final int num = 17;
intsForCheck.forEach(integer -> check(integer,num));


public static void check(int integer,int num)
{
    final String _int = String.valueOf(integer);
    final String _num = String.valueOf(num);

    System.out.println(_int + (_int.contains(_num) ? " contains" : " not contains") + _num);
}