2015-01-29 2 views
0

Просто чиститься на некоторые простые вещи из java. Я пытаюсь проверить, является ли строка уникальной, и я решил, что лучший способ - сделать это через рекурсию. Вот то, что я до сих пор, но я получаю ошибку выхода за границы, очевидно, я что-то довольно просто: с видомНайти, если строка имеет все уникальные символы, используя рекурсию.

public class uniqueCharString { 

    public static void main(String [] args){ 
     String a = "abcdefghijk"; 
     System.out.println(unique(a)); 
    } 

    public static boolean unique(String s){ 
     if(s.substring(1).contains(String.valueOf(s.charAt(0)))){ 
      return false; 
     } 
     else return unique(s.substring(1)); 
    } 

} 

хорошо, так что я закончил свой образ мышления. Я получил некоторые полезные советы от вас, ребята, но я хотел закончить свой мыслительный процесс. Как это решение сравнивается с некоторыми из тех, которые вы сказали, используя набор?

public static boolean unique(String s){ 
     for(int x = 0; x < s.length(); x++){ 
      if(s.substring(x+1).contains(String.valueOf(s.charAt(x)))){ 
       return false; 
      } 

     } 
     return true; 
    } 
+2

'Я полагал, что лучше всего было бы не сделать это через recursion' нет нет – Kon

+0

Пожалуйста, не уточнить, что вы подразумеваете под«уникальный»? Разве что один и тот же символ не должен появляться дважды? Также я согласен с @Kon, рекурсия редко является эффективным подходом к обработке строк. – Gergely

+0

Да нет ни одного персонажа. Хорошо, спасибо за подсказку – erp

ответ

4

Самый эффективный способ сделать это с помощью набора. Итерации над каждым символом и добавление их в набор. Если операция добавления возвращает ложь, то этот символ уже в вашем наборе и строка не имеет-все-уникальные символы, в противном случае все являются уникальным

String s = "some string blah blah blah"; 

Set<Character> set = new HashSet<>(); 
for (char c : s.toCharArray()) 
{ 
    boolean elementFirstAdded = set.add(c); 
    if (!elementFirstAdded) 
     //Duplicate 
} 
//Not duplicate 
+0

будет ли это наиболее эффективным? спасибо за ваш ответ, тем не менее – erp

+0

С точки зрения обработки, да. Хотя это будет использовать больше пространства, потому что он удвоит вашу строку в Set – Kon

+0

Set.add() возвращает «true, если этот набор сделал ** не ** уже содержит указанный элемент», поэтому я думаю, что вам нужно 'boolean duplicate =! Set.add (с) '? – Barney

3

Как @Kon сказал, набор является (возможно) более эффективным ,

Однако, чтобы использовать рекурсию, вам нужно добавить условие завершения: ваша функция никогда не возвращает true!

Строка ноль или один длина должна быть уникальной (хорошо, уникальная нулевая длина немного неоднозначная ...): добавить это в верхней части:

if (s.length() <= 1) { 
    return true; 
    } 
+0

gotcha. спасибо за совет – erp

0

Другим способом сделать это, в случае вы без ума от проблем в выполнении домашних заданий настройки производительности :)

public static boolean unique(String s) { 
    BitSet chars = new BitSet(Character.SIZE); 
    for (int i = 0; i < s.length(); i++) { 
     char c = s.charAt(i); 
     if (chars.get(c)) { 
      return false; 
     } 
     chars.set(c); 
    } 
    return true; 
} 
+0

Проблема с настройкой производительности, как это, это то, что вы действительно не знаете, если она более эффективна, если вы на самом деле ее не измеряете. Составители в наши дни довольно умны и могут сделать для вас большую оптимизацию. Кроме того, вы должны определить «производительность»: «быстрее» и «меньше использования памяти» - это два общих (и часто конкурирующих) критерия. Не сказать, что это плохо в любом случае, просто указывая на то, что оптимизация требует как четкого определения того, что вы пытаетесь оптимизировать, так и набора тестов для его измерения. – Barney

+1

@ Барни, ты совершенно прав.И на самом деле первое решение выглядит быстрее по любой безумной причине! Тайна, которую я разрешу позже. – Gergely

+0

Ничего, я сделал глупую ошибку раньше - окончательный вывод заключается в том, что реализация BitSet примерно в 4 раза быстрее. – Gergely

0

Если вам не нужно знать, что было продублировано я бы просто бросить все в Set(), так как Set() не может содержать дубликаты. Они никогда не будут добавлены в Set(). И если вы просто хотите знать, есть ли у вас дубликаты, вы можете проверить длину строки до и затем размер HashSet() после. Как это:

String a = "abcdefghijk"; 
String[] ary = a.split(""); 
Set<T> mySet = new HashSet<T>(Arrays.asList(words)) 

if (mySet.size() != ary.length){ 
    //do something 
} 
+0

Будет работать, но не так эффективно, как ответ @ Kon: для этого требуется вставить всю строку в набор, тогда как подход Kon останавливается, как только будет найден дубликат. – Barney

+0

С целью определения, есть ли дубликаты в строке, вы верны. Однако, если вы используете набор или хэшсет, вам никогда не понадобится выполнять эту проверку. И добавленный бонус, если вы работаете с большими строками, они будут намного эффективнее для поиска. – Technivexy