我很难理解这个逻辑,以为我已经解决了问题,但是现在很沮丧。
目标是创建一个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
的则通过。
我觉得这和链接的重复答案链接是不同的,因为我没有试图在一行中做到这一点,而且我不只是在计算数字出现的次数。验证传递的值的行更长。
任何帮助或建议将不胜感激。
答案 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;
}
如果您的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;
}
}