我正在研究以下问题陈述:
如果字符串的所有字符都显示相同,则该字符串有效 次数。如果我们只删除1个字符也是有效的 字符串中的1个索引,其余字符将出现 相同的次数。给定字符串s,确定它是否有效。如果 因此,返回YES,否则返回NO。
例如,如果
s=abc
,则它是有效的字符串,因为频率是{a:1,b:1,c:1}
。s=abcc
也是如此,因为我们可以删除一个c
在剩余的字符串中每个字符都有1个。如果s=abccc
但是,该字符串无效,因为我们只能删除1次出现的c
。这样将保留{a:1,b:1,c:2}
的字符频率。
我想出了下面的代码,但是它没有按预期工作,并且在此输入abcdefghhgfedecba
上失败。它正在打印“否”,但对于该输入应为“是”。
private static String isValid(String s) {
if (s == null || s.equals("")) {
return "NO";
}
Map<Character, Integer> frequencies = new HashMap<>();
for (char ch : s.toLowerCase().toCharArray())
frequencies.put(ch, frequencies.getOrDefault(ch, 0) + 1);
int count = 0;
// Iterating over values only
for (Integer value : frequencies.values()) {
if (value == 2) {
count++;
}
}
if (count >= 1) {
return "YES";
}
return "NO";
}
我在这里做什么错?最佳和有效的方法是什么?
答案 0 :(得分:1)
计算频率是正确的主意,尽管我不确定为什么要检查映射中的值是否为2
。计算完这些频率后,我将创建具有每个频率的字符数的反向映射,然后:
private static boolean isValid(String s) {
TreeMap<Long, Long> frequencyCounts =
s.chars()
.boxed()
// Frequency map
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.values()
.stream()
// Frequency of frequencies map
.collect(Collectors.groupingBy
(Function.identity(),
TreeMap::new,
Collectors.counting()));
if (frequencyCounts.size() == 1) {
return true;
}
if (frequencyCounts.size() == 2) {
Iterator<Map.Entry<Long, Long>> iter = frequencyCounts.entrySet().iterator();
Map.Entry<Long, Long> minEntry = iter.next();
long minFrequency = minEntry.getKey();
long numMinFrequency = minEntry.getValue();
if (minFrequency == 1L && numMinFrequency == 1L) {
return true;
}
Map.Entry<Long, Long> maxEntry = iter.next();
long maxFrequency = maxEntry.getKey();
long numMaxFrequency = maxEntry.getValue();
if (numMaxFrequency == 1L && maxFrequency == minFrequency + 1L) {
return true;
}
}
return false;
}
编辑:
为了回答评论中的问题,尽管可能不那么优雅,但也可以使用Java 7的语法构造频率图和“频率频率”图:
Map<Character, Long> frequencies = new HashMap<>();
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
if (frequencies.containsKey(c)) {
frequencies.put(c, frequencies.get(c) + 1L);
} else {
frequencies.put(c, 1L);
}
}
TreeMap<Long, Long> frequencyCounts = new TreeMap<>();
for (Long freq : frequencies.values()) {
if (frequencyCounts.containsKey(freq)) {
frequencyCounts.put(freq, frequencyCounts.get(freq) + 1L);
} else {
frequencyCounts.put(freq, 1L);
}
}
答案 1 :(得分:0)
下面的代码工作正常。我在这里所做的是将每个字符的频率存储在数组中,然后将其转换为列表,因为我们稍后需要该点。接下来,我将列表转换为设置并从中删除零,因为与字符相对应的列表中将存在零,而输入字符串中不存在零。如果set在删除零后仅在元素上,则表示所有元素具有相同的频率,因此返回true 。如果set具有两个以上的元素,则意味着无法通过在一个位置删除一个字符来使它成为有效字符串,因此 return false 。现在如果set有两个值,我们从set中获取最小值和最大值。如果有一个字符和一个频率为条件的第一个频率,则可以使其有效。现在第二个条件是,如果b / w max与min的差为1,并且max仅具有一个频率,那么我们可以从max中删除一个字符并使其有效。
static String isValid(String s) {
Integer arr[] = new Integer[26];
Arrays.fill(arr, 0);
//fill the frequency of every character in array arr
for (int i = 0; i < s.length(); i++) {
arr[s.charAt(i) - 97]++;
}
//convert array to list of integer
List<Integer> arrList = Arrays.asList(arr);
//convert list to set and remove zero bcos zero correspond to char that is not present
HashSet<Integer> set = new HashSet<Integer>(arrList);
set.remove(new Integer(0));
int len = set.size();
// if size==1 means all freq are same
if (len == 1)
return "YES";
else if (len == 2) {
List<Integer> list = new ArrayList<>(set);
int x = list.get(0);
int y = list.get(1);
int max = (x > y) ? x : y;
int min = (x < y) ? x : y;
// if min elemnnt has value one and freuency one
if (Collections.frequency(arrList, min) == 1 && min == 1) {
return "YES";
}
//if max-min==1 and there are only one elemnt with value=max
else if (max - min == 1) {
if ((Collections.frequency(arrList, max) == 1)) {
return "YES";
} else {
return "NO";
}
}
// if no of element is more than
else {
return "NO";
}
} else
return "NO";
}
答案 2 :(得分:0)
java 8
import java.util.*;
public class MyClass {
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
System.out.println(isValid(scan.next()));
}
private static String isValid(String s) {
if (s == null || s.equals("")) {
return "NO";
}
// frequencies ( hashmap) character : frequency
// contains frequency of each character of given string input
Map<Character, Integer> frequencies = new HashMap<>();
for (char ch : s.toLowerCase().toCharArray())
frequencies.put(ch, frequencies.getOrDefault(ch, 0) + 1);
............................................... ................................................... ................................................... .....
// freqTypesCount ( hashmap)
// frequency_type : number_of_chars_having this frequency_type
Map<Integer, Integer> freqTypesCount = new HashMap<>();
for (int ch : frequencies.values())
freqTypesCount.put(ch, freqTypesCount.getOrDefault(ch, 0) + 1);
if( freqTypesCount.size() == 1){
// it means all the chars of string occurs same number of time
return "YES";
}
else if( freqTypesCount.size() > 2){
// aaabbbbccdd
// a : 3 b: 4 c:2 d:2 --> {3:1, 4:1, 2:2}
// we can't make this string a valid string just by deleting single char
return "NO";
}
else{
int valid_freq = Collections.max(freqTypesCount.entrySet(), Map.Entry.comparingByValue()).getKey();
int deleted = 0;
for (Map.Entry<Character, Integer> entry : frequencies.entrySet())
{
int thisCharCount = entry.getValue();
if(thisCharCount != valid_freq){
if(deleted == 0){
if(thisCharCount - 1 == valid_freq || thisCharCount - 1 == 0){
deleted += 1;
}
else{
return "NO";
}
}
else{
return "NO";
}
}
}
return "YES" ;
}
}
}
............................................... ................................................... ................................................... ..................
python 3
from collections import Counter
inp_string = input()
def isValidStr( string):
char_counter_dict = Counter( string)
count_type_counter_dict = Counter(char_counter_dict.values())
if len(count_type_counter_dict) == 1:
return "YES"
elif len(count_type_counter_dict) > 2:
return "NO"
else:
valid_freq = count_type_counter_dict.most_common()[0][0]
deleted = 0
for char,count in char_counter_dict.items():
if count != valid_freq:
if deleted == 0:
if count - 1 == valid_freq or count - 1 == 0:
deleted += 1
else:
return "NO"
else:
return "NO"
return "YES"
print(isValidStr(inp_string))