Ответ 1
Вы передаете длину как 6, что вызывает это. Длина прохода 7, включая пробел. Другие разумные
for(i = length - 1; i >= 0; i--) {
не рассмотрит последний char.
У меня есть вопрос о проблеме программирования из книги Cracking The Code Interview от Gayl Laakmann McDowell, 5th Edition.
Задача: Создать метод для замены всех пробелов в строке на "%20". Предположим, что строка имеет достаточное пространство в конце строки для хранения дополнительных символов и что вам задана истинная длина строки. Я использовал код книги, реализуя решение на Java с использованием массива символов (учитывая тот факт, что строки Java неизменяемы):
public class Test {
public void replaceSpaces(char[] str, int length) {
int spaceCount = 0, newLength = 0, i = 0;
for(i = 0; i < length; i++) {
if (str[i] == ' ')
spaceCount++;
}
newLength = length + (spaceCount * 2);
str[newLength] = '\0';
for(i = length - 1; i >= 0; i--) {
if (str[i] == ' ') {
str[newLength - 1] = '0';
str[newLength - 2] = '2';
str[newLength - 3] = '%';
newLength = newLength - 3;
}
else {
str[newLength - 1] = str[i];
newLength = newLength - 1;
}
}
System.out.println(str);
}
public static void main(String[] args) {
Test tst = new Test();
char[] ch = {'t', 'h', 'e', ' ', 'd', 'o', 'g', ' ', ' ', ' ', ' ', ' ', ' '};
int length = 6;
tst.replaceSpaces(ch, length);
}
}
Выход, который я получаю от вызова replaceSpaces()
: %20do, который вырезает последний символ исходного массива. Я почесал голову над этим, может ли кто-нибудь объяснить мне, почему алгоритм это делает?
Вы передаете длину как 6, что вызывает это. Длина прохода 7, включая пробел. Другие разумные
for(i = length - 1; i >= 0; i--) {
не рассмотрит последний char.
public String replace(String str) {
String[] words = str.split(" ");
StringBuilder sentence = new StringBuilder(words[0]);
for (int i = 1; i < words.length; ++i) {
sentence.append("%20");
sentence.append(words[i]);
}
return sentence.toString();
}
С этими двумя изменениями я получил результат: %20dog
1) Смените количество пробелов на 2 [поскольку длина уже включает 1 из 3 символов, которые вам нужны для %20]
newLength = length + (spaceCount * 2);
2) Петля должна начинаться с длины
for(i = length; i >= 0; i--) {
Вот мое решение. Я проверяю код ascii 32, затем ставим вместо него %20. Временная сложность этого решения - O (N)
public String replace(String s) {
char arr[] = s.toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 32)
sb.append("%20");
else
sb.append(arr[i]);
}
return sb.toString();
}
Это мой код для этого вопроса. Кажется, это работает для меня. Если вам интересно, пожалуйста, посмотрите. Это написано в JAVA
public class ReplaceSpaceInString {
private static char[] replaceSpaceInString(char[] str, int length) {
int spaceCounter = 0;
//First lets calculate number of spaces
for (int i = 0; i < length; i++) {
if (str[i] == ' ')
spaceCounter++;
}
//calculate new size
int newLength = length + 2*spaceCounter;
char[] newArray = new char[newLength+1];
newArray[newLength] = '\0';
int newArrayPosition = 0;
for (int i = 0; i < length; i++) {
if (str[i] == ' ') {
newArray[newArrayPosition] = '%';
newArray[newArrayPosition+1] = '2';
newArray[newArrayPosition+2] = '0';
newArrayPosition = newArrayPosition + 3;
}
else {
newArray[newArrayPosition] = str[i];
newArrayPosition++;
}
}
return newArray;
}
public static void main(String[] args) {
char[] array = {'a','b','c','d',' ','e','f','g',' ','h',' ','j'};
System.out.println(replaceSpaceInString(array, array.length));
}
}
Я использую Stringbuilder для добавления символов одного за другим;
Если найден пробел, замените его на " %20", иначе продолжайте с исходными символами. После анализа всей строки у нас будет строка URLify.
Сложность времени O(n)
.
public static void URLifyString(string source)
{
string replaceSpace = "%20";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < source.Length; i++)
{
if (source[i] == ' ')
{
sb.Append(replaceSpace);
}
else
{
sb.Append(source[i]);
}
}
Console.WriteLine(sb.ToString());
}
}
Это о интервью-интервью jab?
В реальном мире программирования я бы предложил: URLEncoder.encode()
void Rep_Str(char *str)
{
int j=0,count=0;
int stlen = strlen(str);
for (j = 0; j < stlen; j++)
{
if (str[j]==' ')
{
count++;
}
}
int newlength = stlen+(count*2);
str[newlength--]='\0';
for (j = stlen-1; j >=0 ; j--)
{
if (str[j]==' ')
{
str[newlength--]='0';
str[newlength--]='2';
str[newlength--]='%';
}
else
{
str[newlength--]=str[j];
}
}
}
Этот код работает :)
Вы также можете использовать метод подстроки и ascii для пробела (32).
public String replaceSpaceInString(String s){
int i;
for (i=0;i<s.length();i++){
System.out.println("i is "+i);
if (s.charAt(i)==(int)32){
s=s.substring(0, i)+"%20"+s.substring(i+1, s.length());
i=i+2;
}
}
return s;
}
Чтобы проверить:
System.out.println(cc.replaceSpaceInString("mon day "));
Вывод:
mon%20day%20
Вы могли бы просто сделать это. Не нужно рассчитывать длину или что-то еще. Строки в любом случае неизменны.
import java.util.*;
public class ReplaceString {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
String str=in.nextLine();
String n="";
for(int i=0;i<str.length();i++)
{
if(str.charAt(i)==' ')
n=n+"%20";
else
n=n+str.charAt(i);
}
str=n;
System.out.println(str);
}
}
Мы можем использовать регулярное выражение для решения этой проблемы. Например:
public String replaceStringWithSpace(String str){
return str.replaceAll("[\\s]", "%20");
}
Можете ли вы использовать StringBuilder?
public String replaceSpace(String s)
{
StringBuilder answer = new StringBuilder();
for(int i = 0; i<s.length(); i++)
{
if(s.CharAt(i) == ' ')
{
answer.append("%20");
}
else
{
answer.append(s.CharAt(i));
}
}
return answer.toString();
}
Это работает правильно. Однако использование объекта StringBuffer увеличивает пространственную сложность.
Scanner scn = new Scanner(System.in);
String str = scn.nextLine();
StringBuffer sb = new StringBuffer(str.trim());
for(int i = 0;i<sb.length();i++){
if(32 == (int)sb.charAt(i)){
sb.replace(i,i+1, "%20");
}
}
public static String replaceAllSpaces(String s) {
char[] c = s.toCharArray();
int spaceCount = 0;
int trueLen = s.length();
int index = 0;
for (int i = 0; i < trueLen; i++) {
if (c[i] == ' ') {
spaceCount++;
}
}
index = trueLen + spaceCount * 2;
char[] n = new char[index];
for (int i = trueLen - 1; i >= 0; i--) {
if (c[i] == ' ') {
n[index - 1] = '0';
n[index - 2] = '2';
n[index - 3] = '%';
index = index - 3;
} else {
n[index - 1] = c[i];
index--;
}
}
String x = new String(n);
return x;
}
Другой способ сделать это. Я предполагаю, что конечные пробелы не нужно преобразовывать в %20 и что конечные пробелы предоставляют достаточно места для %20s, которые должны быть заполнены между
public class Main {
public static void main(String[] args) {
String str = "a sd fghj ";
System.out.println(replacement(str));//a%20sd%20fghj
}
private static String replacement(String str) {
char[] chars = str.toCharArray();
int posOfLastChar = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] != ' ') {
posOfLastChar = i;
}
}
int newCharPosition = chars.length - 1;
//Start moving the characters to th end of the array. Replace spaces by %20
for (int i = posOfLastChar; i >= 0; i--) {
if (chars[i] == ' ') {
chars[newCharPosition] = '0';
chars[--newCharPosition] = '2';
chars[--newCharPosition] = '%';
} else {
chars[newCharPosition] = chars[i];
}
newCharPosition--;
}
return String.valueOf(chars);
}
}
public class ReplaceChar{
public static void main(String []args){
String s = "ab c de ";
System.out.println(replaceChar(s));
}
public static String replaceChar(String s){
boolean found = false;
StringBuilder res = new StringBuilder(50);
String str = rev(s);
for(int i = 0; i <str.length(); i++){
if (str.charAt(i) != ' ') { found = true; }
if (str.charAt(i) == ' '&& found == true) { res.append("%02"); }
else{ res.append(str.charAt(i)); }
}
return rev(res.toString());
}
// Function to reverse a string
public static String rev(String s){
StringBuilder result = new StringBuilder(50);
for(int i = s.length()-1; i>=0; i-- ){
result.append(s.charAt(i));
}
return result.toString();
}}
Простой подход:
Примечание. Мы отменяем строку, чтобы предотвратить добавление "%20" в конечные пробелы.
Надеюсь, что это поможет!
В вопросе в книге упоминается, что замена должна быть на месте, поэтому невозможно назначить дополнительные массивы, она должна использовать постоянное пространство. Вы также должны учитывать многие случаи кросс, это мое решение:
public class ReplaceSpaces {
public static void main(String[] args) {
if ( args.length == 0 ) {
throw new IllegalArgumentException("No string");
}
String s = args[0];
char[] characters = s.toCharArray();
replaceSpaces(characters);
System.out.println(characters);
}
static void replaceSpaces(char[] s) {
int i = s.length-1;
//Skipping all spaces in the end until setting `i` to non-space character
while( i >= 0 && s[i] == ' ' ) { i--; }
/* Used later to check there is enough extra space in the end */
int extraSpaceLength = s.length - i - 1;
/*
Used when moving the words right,
instead of finding the first non-space character again
*/
int lastNonSpaceCharacter = i;
/*
Hold the number of spaces in the actual string boundaries
*/
int numSpaces = 0;
/*
Counting num spaces beside the extra spaces
*/
while( i >= 0 ) {
if ( s[i] == ' ' ) { numSpaces++; }
i--;
}
if ( numSpaces == 0 ) {
return;
}
/*
Throw exception if there is not enough space
*/
if ( extraSpaceLength < numSpaces*2 ) {
throw new IllegalArgumentException("Not enough extra space");
}
/*
Now we need to move each word right in order to have space for the
ascii representation
*/
int wordEnd = lastNonSpaceCharacter;
int wordsCounter = 0;
int j = wordEnd - 1;
while( j >= 0 ) {
if ( s[j] == ' ' ){
moveWordRight(s, j+1, wordEnd, (numSpaces-wordsCounter)*2);
wordsCounter++;
wordEnd = j;
}
j--;
}
replaceSpacesWithAscii(s, lastNonSpaceCharacter + numSpaces * 2);
}
/*
Replaces each 3 sequential spaces with %20
char[] s - original character array
int maxIndex - used to tell the method what is the last index it should
try to replace, after that is is all extra spaces not required
*/
static void replaceSpacesWithAscii(char[] s, int maxIndex) {
int i = 0;
while ( i <= maxIndex ) {
if ( s[i] == ' ' ) {
s[i] = '%';
s[i+1] = '2';
s[i+2] = '0';
i+=2;
}
i++;
}
}
/*
Move each word in the characters array by x moves
char[] s - original character array
int startIndex - word first character index
int endIndex - word last character index
int moves - number of moves to the right
*/
static void moveWordRight(char[] s, int startIndex, int endIndex, int moves) {
for(int i=endIndex; i>=startIndex; i--) {
s[i+moves] = s[i];
s[i] = ' ';
}
}
}
Любая причина не использовать метод 'replace'?
public String replaceSpaces(String s){
return s.replace(" ", "%20");}
Хм... Мне тоже интересно об этой проблеме. Учитывая то, что я видел здесь. Решение книги не подходит для Java, потому что оно использует на месте
char []
и решения здесь, которые используют char [] или return void, тоже не подходят, потому что Java не использует указатели.
Итак, я думал, очевидным решением будет
private static String encodeSpace(String string) {
return string.replcaceAll(" ", "%20");
}
но это, вероятно, не то, что ваш интервьюер хотел бы увидеть:)
// make a function that actually does something
private static String encodeSpace(String string) {
//create a new String
String result = new String();
// replacement
final String encodeSpace = "%20";
for(char c : string.toCharArray()) {
if(c == ' ') result+=encodeString;
else result+=c;
}
return result;
}
Это выглядит прекрасно, я думал, и вам нужен только один проход через строку, поэтому сложность должна быть O (n), правильно? Неправильно! Проблема в
result += c;
что совпадает с
result = result + c;
который фактически копирует строку и создает ее копию. В java-строках представлены как
private final char value[];
что делает их неизменяемыми (для получения дополнительной информации я бы проверил java.lang.String и как он работает). Этот факт увеличит сложность этого алгоритма до O (N ^ 2), и подлый рекрутер может использовать этот факт, чтобы вы не смогли: P Таким образом, я пришел с новым низкоуровневым решением, которое вы никогда не будете использовать на практике, но это хорошо в теории:)
private static String encodeSpace(String string) {
final char [] original = string != null? string.toCharArray() : new char[0];
// ASCII encoding
final char mod = 37, two = 50, zero = 48, space = 32;
int spaces = 0, index = 0;
// count spaces
for(char c : original) if(c == space) ++spaces;
// if no spaces - we are done
if(spaces == 0) return string;
// make a new char array (each space now takes +2 spots)
char [] result = new char[string.length()+(2*spaces)];
for(char c : original) {
if(c == space) {
result[index] = mod;
result[++index] = two;
result[++index] = zero;
}
else result[index] = c;
++index;
}
return new String(result);
}
Но мне интересно, что не так с кодом:
private static String urlify(String originalString) {
String newString = "";
if (originalString.contains(" ")) {
newString = originalString.replace(" ", "%20");
}
return newString;
}
Вопрос: Урлируйте пробелы с %20
Решение 1:
public class Solution9 {
public static void main(String[] args) {
String a = "Gini Gina Protijayi";
System.out.println( urlencode(a));
}//main
public static String urlencode(String str) {
str = str.trim();
System.out.println("trim =>" + str);
if (!str.contains(" ")) {
return str;
}
char[] ca = str.toCharArray();
int spaces = 0;
for (char c : ca) {
if (c == ' ') {
spaces++;
}
}
char[] newca = new char[ca.length + 2 * spaces];
// a pointer x has been added
for (int i = 0, x = 0; i < ca.length; i++) {
char c = ca[i];
if (c == ' ') {
newca[x] = '%';
newca[x + 1] = '2';
newca[x + 2] = '0';
x += 3;
} else {
newca[x] = c;
x++;
}
}
return new String(newca);
}
}//urlify
Мое решение с использованием StringBuilder с временной сложностью O (n)
public static String url(String string, int length) {
char[] arrays = string.toCharArray();
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
if (arrays[i] == ' ') {
builder.append("%20");
} else {
builder.append(arrays[i]);
}
}
return builder.toString();
}
Прецедент:
@Test
public void testUrl() {
assertEquals("Mr%20John%20Smith", URLify.url("Mr John Smith ", 13));
}
Я также смотрю на этот вопрос в книге. Я считаю, что мы можем просто использовать String.trim()
и String.replaceAll(" ", "%20)
здесь
Я обновил решение здесь. http://rextester.com/CWAPCV11970
Если мы создаем новый массив, а не трафик на месте, то зачем нам идти назад?
Я немного изменил реальное решение, чтобы перейти к созданию целевой строки с кодировкой Url.
Сложность времени:
O(n) - Walking original string
O(1) - Creating target string incrementally
where 'n' is number of chars in original string
Сложность пространства: O (n + m) - дубликат пространства для хранения экранированных пробелов и строк. где 'n' - количество символов в исходной строке, а 'm' - длина экранированных пробелов.
public static string ReplaceAll(string originalString, char findWhat, string replaceWith)
{
var newString = string.Empty;
foreach(var character in originalString)
newString += findWhat == character? replaceWith : character + string.Empty;
return newString;
}
class Program
{
static void Main(string[] args)
{
string name = "Stack Over Flow ";
StringBuilder stringBuilder = new StringBuilder();
char[] array = name.ToCharArray(); ;
for(int i = 0; i < name.Length; i++)
{
if (array[i] == ' ')
{
stringBuilder.Append("%20");
}
else
stringBuilder.Append(array[i]);
}
Console.WriteLine(stringBuilder);
Console.ReadLine();
}
}
общественный класс Sol {
public static void main(String[] args) {
String[] str = "Write a method to replace all spaces in a string with".split(" ");
StringBuffer sb = new StringBuffer();
int count = 0;
for(String s : str){
sb.append(s);
if(str.length-1 != count)
sb.append("%20");
++count;
}
System.out.println(sb.toString());
}
}
public class Test {
public static void replace(String str) {
String[] words = str.split(" ");
StringBuilder sentence = new StringBuilder(words[0]);
for (int i = 1; i < words.length; i++) {
sentence.append("%20");
sentence.append(words[i]);
}
sentence.append("%20");
System.out.println(sentence.toString());
}
public static void main(String[] args) {
replace("Hello World "); **<- Hello<3spaces>World<1space>**
}
}
O/P :: Привет %20 %20 %20World %20
'// Maximum length of string after modifications.
const int MAX = 1000;
// Replaces spaces with %20 in-place and returns
// new length of modified string. It returns -1
// if modified string cannot be stored in str[]
int replaceSpaces(char str[])
{
// count spaces and find current length
int space_count = 0, i;
for (i = 0; str[i]; i++)
if (str[i] == ' ')
space_count++;
// Remove trailing spaces
while (str[i-1] == ' ')
{
space_count--;
i--;
}
// Find new length.
int new_length = i + space_count * 2 + 1;
// New length must be smaller than length
// of string provided.
if (new_length > MAX)
return -1;
// Start filling character from end
int index = new_length - 1;
// Fill string termination.
str[index--] = '\0';
// Fill rest of the string from end
for (int j=i-1; j>=0; j--)
{
// inserts %20 in place of space
if (str[j] == ' ')
{
str[index] = '0';
str[index - 1] = '2';
str[index - 2] = '%';
index = index - 3;
}
else
{
str[index] = str[j];
index--;
}
}
return new_length;
}
// Driver code
int main()
{
char str[MAX] = "Mr John Smith ";
// Prints the replaced string
int new_length = replaceSpaces(str);
for (int i=0; i<new_length; i++)
printf("%c", str[i]);
return 0;
}'