2013-11-22 2 views
2

, когда данный входной строки я полагаю, чтобы разбить его на две группыПеременный строка полукокса и Int

  1. голец
  2. внутр.

с этими двумя группами Я хочу создать новую переменную строку.

, например

abc1234defgh567jk89 

превратится в

a1b2c3d5e6f7j8k9 

уведомления о том, что цифра 4, г, ч было сброшено.

Я понял, что очередь может быть реализована в этом случае.

queue1> а
queue2> 123
индекс 0 до 2 представляет собой символ
индекса три является INT, поэтому для очереди 2 мы принимаем только в 3-х значениях.

Мой вопрос: существует ли более эффективная структура данных для выполнения этой операции? и во время реализации, как сравнить, чтобы определить, является ли конкретное значение int или char?

сообщите пожалуйста.

+0

вам нужно разбить его на две группы перед чередующимися символами и цифрами? Я думал, что вы можете использовать регулярное выражение, чтобы получить набор букв и цифр, затем разделить буквы и цифры, затем поочередно буквы и цифры? – Jaycal

+0

С точки зрения временной сложности лучшее, что вы получите, это O (n), потому что вам нужно искать всю строку. С точки зрения сложности пространства вы также застреваете в O (n), потому что вам нужно построить новую String. – bcorso

ответ

1

Рассмотрение строки в виде массива целых чисел char упростит сравнение, поскольку вы можете сделать простое сравнение по записи. Если array [x]> 64, то это символ другой, это число. Вы можете использовать два указателя для чередования. Один для символа, а другой для целого. Найдите персонажа, а затем продвигайте указатель целых чисел до тех пор, пока он не найдет совпадение, а затем продвигайте их до тех пор, пока они оба верны, а затем быстро переадресуйте оба из них. Например:

char array[]=(char *)string; 

int letter=array[0]; 
int number=array[0]; 


// Initialize 
while(number >= 64) 
    number++; 
while (letter<64) 
    letter++; 

//Now that the pointers are initialized, interleave them. 

while(letter>=64 && number<64) 
{ 
     output[i++]=letter; 
     output[i++]=number; 
    number++; 
    letter++; 
} 

// Now you need to advance to the next batch, so you need to see the comparison false and then true again. 

....

1

Вы правы, очередь является хорошей структурой данных для этой задачи. Если, однако, вам нужны более удобные методы, то Linked List будет другой очень похожей альтернативой.

Чтобы проверить, является ли конкретное значение буквой или числом, вы можете использовать класс символов. Например,

String sample = "hello1"; 

Character.isLetter(sample.charAt(0)); // returns true 
Character.isLetter(sample.charAt(5)); // returns false 
1

как я сравнить, чтобы увидеть, если конкретное значение является INT или символ?

Вы можете сделать что-то вроде этого:

String string = "abc1234defgh567jk89"; 
for(int i=0; i<string.length;i++){ 
    int c = (int)string.charAt(i); 
    boolean isChar = 97<=c&&c<=122 || 65<=c&&c<=90; 
    boolean isNum = 48<=c&&c<=57; 
    if(!isChar && !isNum){ 
     throw new IllegalArgumentException("I don't know what you are") 
    } 
} 

О в datastructutures, лично я буду использовать два в один список, один для символов и один для чисел и каждый символ будет храниться в другом узле , Почему?, ну, если вы сохраните символы (в общем, я имею в виду символы и ints) в группах по три, вам придется добавить больше кода, чтобы разделить эти группы и поместить символы и ints вместе, помещая их в связанный список, имеет смысл, потому что

  1. вы можете поместить столько узлов, сколько вы хотите (или память позволяет вам, но давайте предположим, бесконечна)
  2. данные будут сохранены в порядке (который выглядит как своего рода требование вы имеете для того, чтобы отобразить output, также это отбрасывает деревья и стеки (FILO))
  3. , так как вам нужно только продвигаться вперед при генерации вывода, двойной список будет зависеть от инженерного.

Для генерации выходного сигнала: Имея два datastructures давайте вы добавить еще один чек, как:

if(listChars.size() != listNums.size()){ 
    throw new IllegalArgumentException("Wrong input!!!") 
} 

Кроме того, Просмотр списка займет у вас O(n) время, память, используемая будет O(n), обзор и список возьмет вас O(n/m) где m - размер начальной группы символов. Вы можете сделать это так:

Iterator<Character> iterChar = listChar.iterator(); 
Iterator<Integer> iterNum = listChar.iterator(); 
String result = ""; 
while(iterChar.hasNext() && iterNum.hasNext()){ 
    result+=iterChar.next()+iterNum.next(); 
} 

Наконец, вы можете использовать очереди или связанный список здесь и дать вам то же самое в этом сценарии

1

Чтобы проверить, если следующий символ является буквой или номером вы можете использовать это:

public static boolean isNumber(char c) { return c >= '0' && c <= '9'; } 
public static boolean isLetter(char c) { return c >= 'a' && c <= 'z'; } 

Эти функции поиска индекса следующего номера или буквы, начиная с поз i:

public static int nextNumber(String s, int i) { 
    while(i < s.length() && !isNumber(s.charAt(i))) i++; 
    return i; 
} 

public static int nextLetter(String s, int i) { 
    while(i < s.length() && !isLetter(s.charAt(i))) i++; 
    return i; 
} 

Вы действительно не нужна структура данных, все, что вам нужно, это 3 указатели:

public static String alternate(String s){ 
    // pointers 
    int start = 0, mid = 0, end = 0; 

    StringBuilder sb = new StringBuilder(s.length()); 
    while(end < s.length()){ 
     // E.g. for 'abc1234' {start, mid, end} = {0, 3, 7} 
     start = Math.min(nextLetter(s, end), nextNumber(s, end)); 
     mid = Math.max(nextLetter(s, end), nextNumber(s, end)); 
     end = Math.max(nextLetter(s, mid), nextNumber(s, mid)); 

     for(int i = 0; i < Math.min(mid - start, end - mid); i++) 
      sb.append(s.charAt(start + i)).append(s.charAt(mid + i)); 
    } 
    return sb.toString(); 
} 

Идущие ниже пример выводит желаемый результат: a1b2c3d5e6f7j8k9

public static void main(String... args){ 
    System.out.println(alternate("abc1234defgh567jk89")); 
} 
Смежные вопросы