J'ai une question sur un problème de programmation de l'ouvrage Cracking The Code Interview réalisé par Gayl Laakmann McDowell, 5ème édition.
Le problème est le suivant: Ecrivez une méthode pour remplacer tous les espaces d'une chaîne par '% 20'. Supposons que la chaîne a suffisamment d’espace à la fin de la chaîne pour contenir des caractères supplémentaires et que la longueur réelle de la chaîne vous est attribuée. J'ai utilisé le code du livre en implémentant la solution en Java à l'aide d'un tableau de caractères (étant donné que les chaînes de caractères Java sont immuables):
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);
}
}
Le résultat de l'appel replaceSpaces()
que je reçois est: le% 20do qui coupe le dernier caractère du tableau d'origine. Je me suis gratté la tête à ce sujet. Quelqu'un peut-il m'expliquer pourquoi l'algorithme le fait?
Vous passez la longueur en tant que 6, ce qui provoque ceci. La longueur du passage est de 7, espace compris. Autrement
for(i = length - 1; i >= 0; i--) {
ne considérera pas le dernier caractère.
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();
}
Avec ces deux modifications, j'ai obtenu le résultat: the% 20dog
1) Définissez le nombre d'espaces sur 2 [car la longueur inclut déjà l'un des 3 caractères nécessaires pour% 20]
newLength = length + (spaceCount * 2);
2) La boucle devrait commencer sur la longueur
for(i = length; i >= 0; i--) {
Ceci est mon code pour cette question. On dirait travailler pour moi. Si cela vous intéresse, jetez un coup d'oeil. C'est écrit en 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));
}
}
Voici ma solution. Je vérifie le code ASCII 32, puis je mets un% 20 à la place de celui-ci. La complexité temporelle de cette solution est 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();
}
Vous pouvez également utiliser la méthode substring et l’ascii pour obtenir de l’espace (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;
}
Tester:
System.out.println(cc.replaceSpaceInString("mon day "));
Sortie:
mon%20day%20
Nous pouvons utiliser une expression régulière pour résoudre ce problème. Par exemple:
public String replaceStringWithSpace(String str){
return str.replaceAll("[\\s]", "%20");
}
S'agit-il de questions d'entretien?
Dans la programmation du monde réel, je suggérerais: URLEncoder.encode ()
Vous pouvez simplement faire ça. Pas besoin de calculer la longueur ou autre chose. Les cordes sont immuables de toute façon.
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);
}
}
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];
}
}
}
Ce code fonctionne :)
Hm ... Je m'interroge également sur ce problème. Compte tenu de ce que j'ai vu ici. La solution de livre ne convient pas à Java car elle utilise in-situ
char []
les modifications et les solutions ici qui utilisent char [] ou return void ne conviennent pas aussi bien, car Java n'utilise pas de pointeur.
Alors je pensais, la solution évidente serait
private static String encodeSpace(String string) {
return string.replcaceAll(" ", "%20");
}
mais ce n'est probablement pas ce que votre intervieweur aimerait voir :)
// 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;
}
cela a l'air bien, pensais-je, et il ne faut qu'un seul passage dans la chaîne, la complexité devrait donc être O (n), non? Faux! Le problème est dans
result += c;
qui est le même que
result = result + c;
qui copie réellement une chaîne et en crée une copie. En Java, les chaînes sont représentées par
private final char value[];
ce qui les rend immuables (pour plus d’informations, je voudrais vérifier Java.lang.String et comment cela fonctionne). Ce fait va alourdir la complexité de cet algorithme en O (N ^ 2) et un recruteur sournois peut l'utiliser pour vous faire échouer: P Ainsi, je suis arrivé avec une nouvelle solution de bas niveau que vous n'utiliserez jamais dans la pratique, mais ce qui est bon en théorie :)
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);
}
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();
}}
Une approche simple:
Remarque: nous inversons la chaîne afin d'éviter l'ajout de "% 20" aux espaces de fin.
J'espère que cela pourra aider!
Une autre façon de faire ça. Je suppose que les espaces de fin n'ont pas besoin d'être convertis en% 20 et que ceux-ci offrent suffisamment de place pour que 20% soient remplis
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);
}
}
La question dans le livre mentionne que le remplacement doit être en place de sorte qu'il ne soit pas possible d'affecter des tableaux supplémentaires, il doit utiliser un espace constant. Vous devez également prendre en compte de nombreux cas Edge, voici ma solution:
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] = ' ';
}
}
}
Cela fonctionne correctement Cependant, l'utilisation d'un objet StringBuffer augmente la complexité de l'espace.
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");
}
}
classe publique 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());
}
}
Une raison de ne pas utiliser la méthode 'replace'?
public String replaceSpaces(String s){
return s.replace(" ", "%20");}
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();
}
}
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;
}
Pouvez-vous utiliser 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();
}
Question: Urlifiez les espaces avec% 20
Solution 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
Ma solution utilisant StringBuilder avec une complexité temporelle 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();
}
Cas de test :
@Test
public void testUrl() {
assertEquals("Mr%20John%20Smith", URLify.url("Mr John Smith ", 13));
}
Je regarde aussi cette question dans le livre. Je crois que nous pouvons simplement utiliser String.trim()
et String.replaceAll(" ", "%20)
ici
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 :: Bonjour% 20% 20% 20World% 20
J'ai mis à jour la solution ici. http://rextester.com/CWAPCV11970
Si nous créons un nouveau tableau et non une transition sur place, pourquoi devons-nous marcher à reculons?
J'ai légèrement modifié la vraie solution pour avancer pour créer la chaîne cible encodée en URL.
Complexité temporelle:
O(n) - Walking original string
O(1) - Creating target string incrementally
where 'n' is number of chars in original string
Complexité des espaces: O (n + m) - Dupliquer de l’espace pour stocker des espaces et des chaînes. où 'n' est le nombre de caractères dans la chaîne d'origine et 'm' est la longueur des espaces échappés
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;
}
Mais je me demande ce qui ne va pas avec le code suivant:
private static String urlify(String originalString) {
String newString = "";
if (originalString.contains(" ")) {
newString = originalString.replace(" ", "%20");
}
return newString;
}