Java 测试4个数字,查看其是否有3个唯一的数字

Java 测试4个数字,查看其是否有3个唯一的数字,java,unit-testing,Java,Unit Testing,我有点难以理解这个逻辑,以为我已经解决了,但现在我被难倒了 我们的目标是创建一个4位数的pin,有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))

我有点难以理解这个逻辑,以为我已经解决了,但现在我被难倒了

我们的目标是创建一个4位数的pin,有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;
}
布尔唯一性(字符串nums)
{
对于(int i=0;i<3;i++)
对于(int j=i+1;j<3;j++)
if(nums.charAt(i)=nums.charAt(j))
返回false;
//如果没有遇到重复字符,
//返回真值
返回true;
}
因此,如果我通过数字
1137
,它会失败,但其他类似的
1371
通过

我觉得这是不同的,然后链接重复答案链接,因为我不试图在一行这样做,我不只是计数的次数出现。验证传递的值的代码行更长


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

对于循环(复杂度为
O(n^2)
),您可以使用哈希计算每个数字的出现次数,然后检查有效的pin码。以下是算法:

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;
}
static boolean UniqueNums(字符串数字){
int数组[]=新的int[10];

对于(int i=0;i我认为在映射中保留计数器更简单:

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;
}
public boolean UniqueNums(字符串pin){
如果(引脚长度()>4){
//别针太长
返回false;
}
映射计数器=新的HashMap();
对于(int i=0;i2){
//数字出现3次。
返回false;
}
}
if(counters.keySet().size()
关于:

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;
}
布尔唯一性(字符串数据){
Set found=new HashSet();
整数计数=0;
for(char c:data.toCharArray()){
布尔noClash=found.add(c);
计数+=(NoFlash?0:1);
如果(计数=2){
返回false;
}
}
返回true;
}
  • 1234返回true(无重复)
  • 1231返回true(单个副本)
  • 1221返回false(一对副本)
  • 1112返回false(使用两次以上的数字)

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

您只需要另外一个
int
来维护每个数字的位掩码。短的
可以,但在
Integer.bitCount()
调用中它会被加宽到
int

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;
}

由于涉及的数字限制,谓词可以从以下内容中缩减:

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

有3个独特的字符

(您的代码不测试数字和长度,所以我假设其他代码也会这样做。)


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

boolean atMostOneOneDuplicate(字符串num){
长出现次数=个字符()
.mapToObj(i->(char)i)
.collect(Collectors.groupingBy(c->c,Collectors.counting())
.entrySet()
.stream()
.map(map.Entry::getValue)
.过滤器(v->v<3)
.count();
返回发生次数==num.length()| |发生次数==num.length()-1;

}

使用地图记录事件

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;
    }
}
import java.util.HashMap;
导入java.util.Map;
班长{
公共静态void main(字符串[]args){
System.out.println(isValid(“1137”));
System.out.println(isValid(“1371”));
System.out.println(isValid(“1234”));
System.out.println(isValid(“1222”));
}
公共静态布尔值isValid(字符串num){
Map Digits WithNumberOfOfOccurances=新HashMap();
int numodigits that occurrentedwice=0;
对于(int i=0;i2){//没有任何数字可以出现两次以上
返回false;
}
}
返回true;
}
}

您必须计算数字的出现次数,因此添加一个计数,如果计数大于2,则为false?是。您可以优化第一个循环,以仅测试第一个和第二个数字。您还可以创建一个重复数组,并比较一个循环中的每个元素……可能重复是这些检查在其他位置进行一个line解决方案-提出正确问题的完美示例我尝试编写与需求类似的代码,并根据需要进行功能分解,以获得一致的抽象级别。因此,我不理解此问题的返回值?@whisk做了一个小编辑,因为我之前的编辑弄错了。现在,如果至少有3个唯一值,则返回true在
掩码
变量上作为位跟踪的数字,例如
0
被跟踪
.01
1
被跟踪
.010
2
被跟踪为掩码
.0100
。请参阅
Integer.bitCou>文档
boolean hasAtLeastThreeUniqueCharacters = "1123".codePoints().distinct().count() >= 3;
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;
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;
    }
}