我正在尝试从hackerrank运行程序。这是问题:
如果字符串的所有字符出现相同的次数,Sherlock认为该字符串有效。如果他只能在字符串的 one 索引中删除一个字符,并且其余字符出现相同的次数,则也是有效的。给定一个字符串,确定它是否有效。
例如,如果s =“ abc”,则它是有效的字符串,因为频率为{a:1,b:1,c:1}。 abcc也是如此,因为我们可以删除一个c并在剩余的字符串中每个字符包含1个字符。如果s ='abccc',则该字符串无效,因为我们只能删除1次出现的c。这样将保留{a:1,b:1,c:2}的字符频率。
失败的5个测试用例之一是: aaaabbcc应该给出错误的信息,但是它给了我真实的信息。 aabbc应该给真,但是给我错。
但是不知何故我的5个测试用例就出错了: 这是下面的程序。
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
public class SherlokValidString
{
boolean is_valid(String s)
{
int count=0;
HashMap<Character, Integer> map = new HashMap<>();
char[] str_arr= s.toCharArray();
for(char c:str_arr)
{
if(map.containsKey(c))
{
map.put(c, map.get(c)+1);
}
else
{
map.put(c,1);
}
}
if (map.size()==1)
{
return true;
}
else {
List ll=new ArrayList<>(map.values());
System.out.println(ll);
Collections.sort(ll);
int first_element=(int)ll.get(0);
for(int i=1;i<(ll.size()-1);i++)
{
//System.out.println((int)ll.get(i)+1);
if (first_element==(int)ll.get(i+1))
{
count=0;
}
else if(first_element!=(int)ll.get(i+1))
{
count++;
}
}
if(count<=1)
{
//System.out.println(count);
return true;
}
else
{
return false;
}
}
}
public static void main(String[] args)
{
SherlokValidString svs = new SherlokValidString();
System.out.println(svs.is_valid("abbccc"));
}
}
它应该返回false,它使我成真。 请帮忙。谢谢。
答案 0 :(得分:1)
使用Java 8,可以做得非常出色:
public static boolean sherlockStr(String s) {
// First, we're going to walk over the characters and count how many
// times each character occurs
Map<Character, Long> charOccurs = s.chars()
.mapToObj(t -> (char) t)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
// Then we're going to map each amount of characters found to its count,
// e.g. in the string "aabbcc" each character occurs twice → [2, 2, 2].
// That will yield a map: [2=3]
Map<Long, Long> counts = charOccurs.entrySet().stream()
.map(Map.Entry::getValue)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
switch (counts.size()) {
// If all characters occur an equal number of times, then the map
// contains just a single entry.
case 1:
return true;
// If there are two different amounts, then the difference between
// those two must be 1. Also, one of the numbers must occur exactly
// once.
case 2:
Iterator<Long> it = counts.keySet().iterator();
boolean diff = Math.abs(it.next() - it.next()) == 1;
return (diff && (counts.values().stream()
.anyMatch(i -> i == 1)));
// If the map's size is 3 or more, there are differents of amounts of
// characters.
default:
return false;
}
}
简而言之:
public static boolean sherlockStr(String s) {
Map<Long, Long> counts = s.chars()
.mapToObj(t -> (char) t)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream()
.map(Map.Entry::getValue)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
switch (counts.size()) {
case 1:
return true;
case 2:
Iterator<Long> it = counts.keySet().iterator();
return (Math.abs(it.next() - it.next()) == 1 && (counts.values().stream()
.anyMatch(i -> i == 1)));
default:
return false;
}
}
答案 1 :(得分:0)
我发现您的逻辑中有以下失败:
最后一个循环的结束边界是错误的。从i == 1开始真的没关系(因为初始化first_element
时隐式处理了第一项),但是结束边界必须为ll.size()
,而不是ll.size()-1
。
决定count
是否必须递增的条件太宽泛,并且应该更具限制性:仅使出现的频率与最低频率不同是不够的(包含在first_element
中);还必须确保至少为1+first_element
。而且,如果更高,则必须中断循环并返回false。
答案 2 :(得分:0)
尝试以下操作,查看评论:
boolean isValid(String s)
{
HashMap<Character, Integer> map = new HashMap<>();
char[] str_arr= s.toCharArray();
for(char c:str_arr)
{
if(map.containsKey(c))
{
map.put(c, map.get(c)+1);
}
else
{
map.put(c,1);
}
}
//define min max frequencies
int min = (int) Math.pow(10, 5); int max = 0;
for(int value : map.values()) {
if (value < min ) {
min = value;
}
if(value > max ) {
max = value;
}
}
if(min == max) { return true;} //all frequencies equal
if( (max - min) > 1) {return false;} //removing one character can not make the equal
//for other cases make sure that only one frequency is different
int countBiggerThanMin = 0;
for(int value : map.values()) {
if(value > min ) {
countBiggerThanMin++;
}
}
if((countBiggerThanMin == 1) || //only one bigger than min
(countBiggerThanMin == (map.size() - 1))) { //min is samller than all others
return true;
}
return false;
}
通过使用Java 8 Stream,它变得更加简洁:
boolean isValidForJava8(String s) {
Stream<String> stream = Stream.of(s.split(""));
Map<String, Long> map = stream.collect(
Collectors.groupingBy( Function.identity(), Collectors.counting() ));
Long min = map.values().stream().min(Long::compareTo).get();
Long max = map.values().stream().max(Long::compareTo).get();
if(min == max) { return true;} //all frequencies equal
if( (max - min) > 1) {return false;} //removing one character can not make the equal
//for other cases make sure that only one frequency is different
int countBiggerThanMin = map.values().stream().mapToInt(v -> (v > min) ? 1 : 0).sum();
if((countBiggerThanMin == 1) || //only one bigger than min
(countBiggerThanMin == (map.size() - 1))) { //min is samller than all others
return true;
}
return false;
}
答案 3 :(得分:0)
这是一个完美的解决方案:
{
if ((s.size() == 1) || (s.size() == 2))
return "YES";
std::map <char, int> hashValues;
for (char &c: s)
{
if (hashValues.count(c) != 0)
hashValues[c]++;
else
hashValues.insert(std::pair <char, int> (c,1));
}
int highest = 0;
int lowest = 100000;
for (map<char,int>::iterator it = hashValues.begin(); it != hashValues.end(); it++)
{
if (it->second < lowest)
lowest = it->second;
if (it->second > highest)
highest = it->second;
}
int countMin = 0;
int countMax = 0;
for (map<char,int>::iterator it = hashValues.begin(); it != hashValues.end(); it++)
{
if (it->second == highest)
countMax++;
if (it->second == lowest)
countMin++;
}
if ((highest - lowest) == 0) {return "YES";};
if (((highest - lowest) == 1) && (countMax == 1))
return "YES";
if (((highest - lowest) == 2))
return "NO";
if ((lowest == 1) && (countMin == 1))
return "YES";
return "NO";
}
答案 4 :(得分:0)
科特琳(Kotlin)带来一点优雅=)
if (s.length == 1) return "YES"
val freq = s.groupingBy { it }.eachCount()
val max:Int = freq.maxBy { it.value }!!.value
val maxCount = freq.count { it.value == max }
val min = freq.minBy { it.value }!!.value
val minCount = freq.count { it.value == min }
val freqOfFreq = freq.map { it.value }.groupingBy { it }.eachCount()
return when {
freqOfFreq.size > 2 -> return "NO"
freqOfFreq.size == 1 -> return "YES"
minCount == 1 -> return "YES"
max - maxCount == min -> return "YES"
else -> "NO"
}
答案 5 :(得分:0)
静态列表myCharList = new ArrayList <>();
static int isValidStringProcessor(String s) {
int returnStatus=-2;
List<Character> chars = s.chars().mapToObj(e -> (char)e).collect(Collectors.toList());
List<Integer> myList = new ArrayList<>();
Map<Character, Long> frequencyMap =
chars.stream().collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()));
for (Map.Entry<Character, Long> entry : frequencyMap.entrySet()) {
myList.add(entry.getValue().intValue());
myCharList.add(entry.getKey());
}
int min = Collections.min(myList);
int max = Collections.max(myList);
int minFrequency = Collections.frequency(myList, min);
int maxFrequency = Collections.frequency(myList, max);
if ((max==min)) {
returnStatus=-1;
} else if ((minFrequency==1 && maxFrequency==(myList.size()-1)) && (max-min==1)) {
returnStatus=myList.indexOf(min);
} else if ((minFrequency==(myList.size()-1) && maxFrequency==1) && (max-min==1)) {
returnStatus=myList.indexOf(max);
}
return returnStatus;
}
// Complete the isValid function below.
static String isValid(String s) {
String result ="NO";
int validIdenfitier = isValidStringProcessor(s);
if (validIdenfitier == -1) {
result="YES";
} else if (validIdenfitier >= 0) {
Character ch = myCharList.get(validIdenfitier);
String newString = s.replaceFirst(ch+"", "");
if (isValidStringProcessor(newString) == -1)
result="YES";
}
return result;
}
答案 6 :(得分:0)
尝试此方法可以通过所有测试用例,类似于您的方法。 :)
static String isValid(String s) {
char c[]=s.toCharArray();
HashMap<Character,Integer> map=new HashMap<Character,Integer>();
for(char ch: c){
if(!map.containsKey(ch)){
map.put(ch,1);
}
else
map.put(ch,map.get(ch)+1);
}
Set<Integer> st = new HashSet<>();
for(int freq : map.values())
{
st.add(freq);
}
if(st.size() > 2)//More than 2 frequencies
System.out.println("NO");
else if(st.size() == 1)
return "YES";
else{
int f1 = 0;
int f2 = 0;
int f1Count = 0;
int f2Count = 0;
int i = 0;
for(int n : st)
{
if(i == 0) f1 = n;
else f2 = n;
i++;
}
for(int freq : map.values())
{
if(freq == f1) f1Count++;
if(freq == f2) f2Count++;
}
if((f1 == 1 && f1Count == 1 ) || (f2 == 1 && f2Count == 1 ))
return "YES";
else if ((Math.abs(f1 - f2) == 1) && (f1Count == 1 || f2Count == 1))
return "YES";
else
return "NO";
}
return "NO";
}
答案 7 :(得分:0)
public String isValid(String s) {
HashMap<Character, Integer> trackFrequency = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
Character c = s.charAt(i);
if (trackFrequency.containsKey(c)) {
int count = trackFrequency.getOrDefault(c, 0);
count = count + 1;
trackFrequency.put(c, count);
} else {
trackFrequency.put(c, 1);
}
}
int sample = trackFrequency.get(s.charAt(0));
int unEqualFrequency = 0;
int unEqualValue = 0;
for (Integer value : trackFrequency.values()) {
if (sample != value) {
unEqualFrequency++;
}
if (unEqualFrequency == 1) {
unEqualValue = value;
}
}
if (unEqualFrequency > 1) {
return "NO";
} else if (Math.abs(sample - unEqualValue) <= 1 ||
unEqualFrequency <= 1) {
return "YES";
}
return "NO";
}
Here i am calculating the no of times the values are different in hashmap . There are three cases
if its == 0 > its sherlock string
if its >1 -> its not a Sherlock String
if its == 1 and the difference of the two values is ==1 -> its sherlock string