测试4个数字以查看其是否具有3个唯一数字

时间:2018-08-14 15:42:11

标签: java unit-testing

我很难理解这个逻辑,以为我已经解决了问题,但是现在很沮丧。

目标是创建一个4位数的密码,并具有3个唯一的数字,其中1个可以重复。它们也可以是任何顺序。这是我到目前为止所拥有的:

boolean UniqueNums(String nums)
{
    for (int i=0; i < 3; i++)
        for (int j=i+1; j < 3; j++)
            if (nums.charAt(i) == nums.charAt(j))
                return false;

    // If no duplicate characters encountered,
    // return true
    return true;
}

因此,如果我通过数字1137,它将失败,而其他类似1371的则通过。

我觉得这和链接的重复答案链接是不同的,因为我没有试图在一行中做到这一点,而且我不只是在计算数字出现的次数。验证传递的值的行更长。

任何帮助或建议将不胜感激。

7 个答案:

答案 0 :(得分:3)

那又怎么样:

boolean UniqueNums(String data) {
    Set<Character> found = new HashSet<>();
    int count = 0;
    for (char c : data.toCharArray()) {
        boolean noClash = found.add(c);

        count += (noClash ? 0 : 1);
        if (count == 2) {
            return false;
        }
    }

    return true;
}
  • 1234返回true(无重复)
  • 1231返回true(一个重复项)
  • 1221返回false(一对重复项)
  • 1112返回false(一个数字使用了两次以上)

如果您的PIN码大于4个字符,它也可以工作,它只需要一个循环使其变为O(n),并且很快就会失败

答案 1 :(得分:2)

您可以使用散列来计数每个数字的出现次数,然后检查有效的引脚号,而不是嵌套的for循环(复杂度为O(n^2))。这是算法:

static boolean UniqueNums(String digit){
    int array[] = new int[10];
    for (int i=0;i<digit.length();i++){
        array[digit.charAt(i)-48]++;  //48 because ascii of 0 is 48
    }
    //Now check for frequency
    int count = 0;
    for (int i=0;i<10;i++){
       if(array[i] > 2) return false;
       if(array[i] == 2){
          ++count;
       }
     }
     if(count <= 1) return true;
     return false;
}

这将是O(k),其中k是您的电话号码中的位数。

答案 2 :(得分:2)

由于所涉及的数字限制,您的谓词可以减少为:

  

一个4位数的密码,有3个唯一的数字,其中1个可以重复。它们也可以是任何顺序。

  

具有3个唯一的字符

(您的代码不会测试数字和长度,因此我认为其他代码也可以做到这一点。)

boolean hasAtLeastThreeUniqueCharacters = "1123".codePoints().distinct().count() >= 3;

答案 3 :(得分:1)

我认为在地图中保留计数器更为简单:

public boolean UniqueNums(String pin){

    if(pin.length() > 4) {
        //pin too long
        return false;
    }

    Map<Character, Integer> counters = new HashMap<>();
    for(int i = 0; i < pin.length(); i++){

        Character c = pin.charAt(i);
        if(!Character.isDigit(c)){
            //not a number.
            return false;
        }

        counters.put(c, counters.getOrDefault(c,0) + 1);
        if(counters.get(i) > 2){
            // digit appear 3 times.
            return false;
        }
    }

    if(counters.keySet().size() < pin.length() - 1){
        // not 3 unique numbers e.g 1122
        return false;
    }

    return true;
}

答案 4 :(得分:1)

您仅需要一个附加的int即可维护每个数字的位掩码。 short可以,但是在任一方式的int调用中,它都会扩大到Integer.bitCount()

boolean uniqueNums(String nums) {
  int pin = Integer.parseInt(nums);
  int mask = 0;
  for (int i = 0; i < nums.length(); i++) {
    mask |= 1 << pin % 10;
    pin /= 10;
  }
  return Integer.bitCount(mask) >= 3;
}

导致

uniqueNums("1234") // true
uniqueNums("9393") // false

答案 5 :(得分:1)

您还可以按出现次数对数字进行分组,过滤最多2个出现次数的数字,以使它们的计数可以与num length或length-1(重复一遍)一样长:

boolean atMostOneOneDuplicate(String num) {
     long occurences = num.chars()
        .mapToObj(i -> (char) i)
        .collect(Collectors.groupingBy(c -> c, Collectors.counting()))
        .entrySet()
        .stream()
        .map(Map.Entry::getValue)
        .filter(v -> v < 3)
        .count();

    return occurences == num.length() || occurences == num.length() - 1;

}

答案 6 :(得分:0)

使用地图跟踪发生情况

import java.util.HashMap;
import java.util.Map;

class Main{
    public static void main(String[] args) {
        System.out.println(isValid("1137"));
        System.out.println(isValid("1371"));
        System.out.println(isValid("1234"));
        System.out.println(isValid("1222"));
    }
    public static boolean isValid(String num){
         Map<Character,Integer> digitsWithNumberOfOccurances = new HashMap<>();
         int numOfDigitsThatOccuredTwice = 0;
         for(int i = 0; i < num.length(); i++){
             char currentChar = num.charAt(i);
             int currentNumberOfOccurences = digitsWithNumberOfOccurances.getOrDefault(currentChar,0);
             currentNumberOfOccurences ++;
             digitsWithNumberOfOccurances.put(currentChar,currentNumberOfOccurences);
             if(currentNumberOfOccurences == 2){
                 numOfDigitsThatOccuredTwice++;
                 // only one digit can occur twice
                 if(numOfDigitsThatOccuredTwice > 1) {
                     return false;
                 }
             }else if(currentNumberOfOccurences > 2){ // no digit can occur more than twice
                 return false;
             }
         }
        return true;
    }
}