Problem with even indexes in Java program - java

The method takes 2 parameters (String,char) and returns the string with the char replaced by '+' if index is even and '#' if index is odd.
The String I use is "Mary Bella Abracadabra" and the expected output is "M+ry Bell+ +br#c#d#br+". Instead I get "M#ry Bell# #br#c#d#br#".
I can't find the error in my code. It seems that all indexes where char ch is found are odd.
public String emphasize (String phrase, char ch){
String phraseEmph = "";
char c1 = '#';
char c2 = '+';
for (int i=0; i < phrase.length(); i++){
char c = phrase.charAt(i);
char cc = Character.toLowerCase(c);
if ((cc == ch) && ((i % 2) == 0)){
phraseEmph = phrase.replace(c,c2);
phrase = phraseEmph;
}
else if ((cc == ch) && ((i % 2)!= 0)){
phraseEmph = phrase.replace(c,c1);
phrase = phraseEmph;
}
phrase = phrase;
}
return phrase;
}
public void testEmphasize(){
String phrase = "Mary Bella Abracadabra";
char ch = 'a';
String Emphasized = emphasize(phrase,ch);
System.out.println("Emphasized : " + Emphasized);
}

When you call replace it doesn't just replace the current 'a', it replaces all of them. You'll need to find a different way to replace characters so that you only change one at a time.
(I've purposefully avoided suggesting a fix. It'll be more educational if you come up with it yourself.)

Note Array start with 0 in java. String is immutable and don't provide many mutable methods. It's best to make use of StringBuilder as shown below both for easiness and memory efficiency.
public static String emphasize(String phrase, char ch) {
StringBuilder phraseEmph = new StringBuilder(phrase);
char c1 = '#';
char c2 = '+';
for (int i = 0; i < phrase.length(); i++) {
char c = phrase.charAt(i);
char cc = Character.toLowerCase(c);
if ((cc == ch) && ((i % 2) == 0)) {
phraseEmph.setCharAt(i, c2);
} else if ((cc == ch) && ((i % 2) != 0)) {
phraseEmph.setCharAt(i, c1);
}
}
return phraseEmph.toString();
}

Use StringBuilder instead of String for concatenation to a string inside a loop because it is much faster and consumes less memory.
Convert both the characters in the same case (e.g. lowercase) before comparing. This way, you can pass the character to the function in any case.
You should not use String#replace for this case as it replaces all occurrences of replacement character/string in the string being replaced.
Demo:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(emphasize("Mary Bella Abracadabra", 'a'));
System.out.println(emphasize("Mary Bella Abracadabra", 'A'));
}
public static String emphasize(String phrase, char ch) {
char c1 = '#';
char c2 = '+';
StringBuilder sb = new StringBuilder();
// Convert the char parameter to lower case
char chLower = Character.toLowerCase(ch);
for (int i = 0; i < phrase.length(); i++) {
char c = phrase.charAt(i);
if (Character.toLowerCase(c) == chLower) {
if (i % 2 == 0) {
sb.append(c1);
} else {
sb.append(c2);
}
} else {
sb.append(c);
}
}
return sb.toString();
}
}
Output:
M+ry Bell+ +br#c#d#br+
M+ry Bell+ +br#c#d#br+

Here are some suggestions.
use a StringBuilder to make the character replacements. Intialize to the original string. You can then use setCharAt to make the change.
Use indexOf in conjunction with toLowerCase. Then you don't need to verify if you found the character, just use the index returned and return the final string if -1.
then just check for even or or indices like you are doing but assign to a holding char variable.
Then use that to replace the character. Like this pseudocode
char repl;
if (even) {
repl = '#';
} else {
repl = '+';
}
make replacement
don't do a check for both even or odd. Just check for one condition, Otherwise it must be the other condition (not need to check again).
Aside from my recommendations, here is another way of doing it.
The main difference is that it uses the even/odd result to index into the array to replace the character.
public static String emphasize(String phrase, char ch) {
StringBuilder sb = new StringBuilder(phrase);
char[] chars = { '#', '+' };
int idx = -1;
while ((idx = phrase.toLowerCase().indexOf(ch, idx + 1)) >= 0) {
sb.setCharAt(idx, chars[idx % 2]);
phrase = sb.toString();
}
return phrase;
}

Full tested simplified code :
public class Main {
public static void main(String[] args) {
String phrase = "Maryaa Bella Abracadabra";
char ch = 'a';
System.out.println("Original : " + phrase);
String Emphasized = emphasize(phrase,ch);
System.out.println("Emphasized : " + Emphasized);
}
public static String emphasize (String phrase, char ch){
StringBuilder temp = new StringBuilder(phrase);
char c1 = '#';
char c2 = '+';
for (int i = 0; i < phrase.length(); i++){
char c = phrase.charAt(i);
char cc = Character.toLowerCase(c);
if(cc == ch) {
if(i%2 == 0){
temp.setCharAt(i, c1);
} else {
temp.setCharAt(i, c2);
}
}
}
return temp.toString();
}
}
Output :
Original : Maryaa Bella Abracadabra
Emphasized : M+ry#+ Bell+ +br#c#d#br+

Your code is very inefficient, my suggestion :
class emphasize {
private String phrase;
private char ch;
public emphasize(String phrase, char ch) {
this.phrase = phrase;
this.ch = ch;
}
public String execute() {
char chars[] = phrase.toCharArray();
for (int i = 0 ; i < chars.length ; i++) {
/* As char is primitive type I can use == */
if (chars[i]==Character.toLowerCase(ch) || chars[i]==Character.toUpperCase(ch)) chars[i] = i%2==0 ? '+' : '#';
}
return String.valueOf(chars);
}
}
public class Main {
public static void main(String[] args) {
String phrase = "Mary Bella Abracadabra";
char ch = 'a';
emphasize obj = new emphasize(phrase, ch);
System.out.println(obj.execute());
}
}
Output :

Related

reduce string length when it has pair in java

here it is giving error----required variable ,found value
my code
for eg aabacc when we got any pair like aa remove it from string and the final answer is (ba).
public class Solution {
// Complete the superReducedString function below.
static String superReducedString(String s) {
String sn;
int j=0;
for(int i=0;i<s.length()-1;i++)
{
if(s.charAt(i)!=s.charAt(i+1))
{
sn.charAt(j)=s.charAt(i);
j++;
}
}
return sn;
}
Since String is immutable in Java - String manipulation always generates a new String leaving the previous Strings in String Pool. StringBuffer and StringBuilder are mutable objects and provide methods for String manipulation
Sample working method using StringBuilder is provided below:
static String superReducedString(String s) {
StringBuilder myName = new StringBuilder(s);
int j=0;
for(int i=0;i<s.length()-1;i++) {
if(s.charAt(i)!=s.charAt(i+1)) {
myName.setCharAt(j, s.charAt(i));
j++;
}
}
return myName.toString();
}
You can not do such assignment like sn.charAt(j)=s.charAt(i); since charAt() is function that returns the result, but not a variable. You could use StringBuilder here:
static String superReducedString(String s) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (s.length() == i+1 || s.charAt(i) != s.charAt(i + 1)) {
sb.append(s.charAt(i));
} else {
i++;
}
}
return sb.toString();
}
s.length() == i+1 checks if it's the last char. In case aabaccr the result will be as expected bar
Just another solution, in case the other answers don't work for you:
static String superReducedString(String s) {
char[] chars = s.toCharArray();
String lastChar = "";
ArrayList<String> newString = new ArrayList<>();
for (char aChar : chars) {
String currentChar = String.valueOf(aChar);
if (lastChar.equals(currentChar))
newString.remove(newString.size() - 1);
else {
newString.add(currentChar);
lastChar = currentChar;
}
}
AtomicReference<String> returnString = new AtomicReference<>("");
newString.forEach(character-> returnString.set(returnString + character));
return returnString.get();
}
The answer is quite simple.
you cannot delete anything from a String but you can move them to another String as you want.
public class Solution {
public static void main(String[] args) {
String s = "abbccd", s1 = "";
if(s.charAt(1) != s.charAt(0))
s1 += s.charAt(0);
if(s.charAt(s.length()-1) != s.charAt(s.length()-2))
s1 += s.charAt(s.length()-1);
for (int i = 1; i < s.length() - 1; i++) {
if (s.charAt(i) != s.charAt(i - 1) && s.charAt(i) != s.charAt(i + 1))
s1 += s.charAt(i);
}
System.out.println(s1);
}
}
You create another String.
Then in a for loop iterating from 1 (NOT 0) to s.length()-1 (NOT s.length()), you check if the s.charAt(i) (current character) is equal to the preceding or following one. If it's not equal to any of them, you add it to the second String and then you print it. We are checking both sides so that's why the loop is from 1 to s.length()-1, to avoid out of bounds exceptions.
EDIT: to check the first and last character.

How to Convert String to another String format

How can I convert a string in the form eyesOfTheTiger to one that reads eyes-of-the-tiger?
Just travel through the string and take different action if the character is uppercase.
public class Test {
private static String upperCaseToDash(String input) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (Character.isUpperCase(c))
sb.append('-').append(Character.toLowerCase(c));
else
sb.append(c);
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println(upperCaseToDash("eyesOfTheTiger"));
}
}
Before you start implementing this function yourself via substrings, regex, etc, consider using Google Guava. Class com.google.common.base.CaseFormat solves exactly what you intend to do.
In your case you need the LOWER_CAMEL and LOWER_HYPHEN class constants and the to(CaseFormat format, String s) method.
IMO, it's always better to use a mature and well-tested library than to implement everything yourself.
You can split() the String using a regex , like "(?<!(^|[A-Z0-9]))(?=[A-Z0-9])|(?<!^)(?=[A-Z][a-z])" and then append - at the end of each split .
public String camelCaseToDashSeparated(String initialString) {
if(initialString==null || initialString.length()<1)
return initialString;
StringBuilder str = new StringBuilder();
for (String w : "eyesOfTheTiger".split("(?<!(^|[A-Z0-9]))(?=[A-Z0-9])|(?<!^)(?=[A-Z][a-z])")) {
str.append(w.toLowerCase()+"-");
}
return str.substring(0, str.length()-1);
}
Another way would be :
Travel through the String , char by char , keep adding the characters to the StringBuilder. Once you find a char in uppercase , append - to the StringBuilder with the lowercase of the char.
public static String camelCaseToDashSeparated2 (String initialString) {
StringBuffer buff = new StringBuffer();
for(int x = 0; x < initialString.length(); x++) {
char c = initialString.charAt(x);
if(Character.isUpperCase(c)) {
buff.append("-").append(Character.toLowerCase(c));
}
else {
buff.append(c);
}
}
return buff.toString();
}
Quick and dirty solution could be something like this:
(you should decide what to do with spaces, dashes, full stops,
languages other than English etc.)
public static String toDashed(String value) {
if (null == value)
return null;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < value.length(); ++i) {
char ch = value.charAt(i);
if ((ch >= 'A') && (ch <= 'Z') && (i > 0)) {
sb.append('-');
sb.append(Character.toLowerCase(ch));
}
else
sb.append(ch);
}
return sb.toString();
}

Java - Convert lower to upper case without using toUppercase()

I'm trying to create a short program that would convert all letters that are uppercase to lowercase (from the command line input).
The following compiles but does not give me the result I am expecting. What would be the reason for this??
Eg) java toLowerCase BANaNa -> to give an output of banana
public class toLowerCase{
public static void main(String[] args){
toLowerCase(args[0]);
}
public static void toLowerCase(String a){
for (int i = 0; i< a.length(); i++){
char aChar = a.charAt(i);
if (65 <= aChar && aChar<=90){
aChar = (char)( (aChar + 32) );
}
System.out.print(a);
}
}
}
You are printing the String a, without modifying it. You can print char directly in the loop as follows:
public class toLowerCase
{
public static void main(String[] args)
{
toLowerCase(args[0]);
}
public static void toLowerCase(String a)
{
for (int i = 0; i< a.length(); i++)
{
char aChar = a.charAt(i);
if (65 <= aChar && aChar<=90)
{
aChar = (char)( (aChar + 32) );
}
System.out.print(aChar);
}
}
}
Looks like homework to me, Just a hint. You are printing string a whereas you are modifying the char type aChar, its not modifying the original string a. (Remember strings are immutable).
A cleaner way of writing this code is
public static void printLowerCase(String a){
for(char ch: a.toCharArray()) {
if(ch >= 'A' && ch <= 'Z')
ch += 'a' - 'A';
System.out.print(ch);
}
}
Note: this will not work for upper case characters in any other range. (There are 1,000s of them)
Looks like you're close. :)
For starters...
char aChar = a.charAt(i);
"a" is an array of Strings, so I believe you would want to iterate over each element
char aChar = a[i].charAt(0);
and it also seems like you want to return the value of the modified variable, not of "a" which was the originally passed in variable.
System.out.print(aChar);
not
System.out.print(a);
Hope that helps you.
public static void toLowerCase(String a){
String newStr = "";
for (int i = 0; i< a.length(); i++){
char aChar = a.charAt(i);
if (65 <= aChar && aChar<=90){
aChar = (char)( (aChar + 32) );
}
newStr = newStr + aChar;
}
System.out.println(newStr);
}
You should print newStr outside for loop. You were trying to print it inside the loop
/**
* Method will convert the Lowercase to uppercase
* if input is null, null will be returned
* #param input
* #return
*/
public static String toUpperCase(String input){
if(input == null){
return input;
}
StringBuilder builder = new StringBuilder();
for(int i=0;i<input.length();i++){
char stringChar = input.charAt(i);
if(92 <= stringChar && stringChar <=122){
stringChar = (char)( (stringChar - 32) );
builder.append(stringChar);
}
else if (65 <= stringChar && stringChar<=90)
{
builder.append(stringChar);
}
}
if(builder.length() ==0){
builder.append(input);
}
return builder.toString();
}
public class Changecase
{
static int i;
static void changecase(String s)
{
for(i=0;i<s.length();i++)
{
int ch=s.charAt(i);
if(ch>64&&ch<91)
{
ch=ch+32;
System.out.print( (char) ch);
}
else if(ch>96&&ch<123)
{
ch=ch-32;
System.out.print( (char) ch);
}
if(ch==32)
System.out.print(" ");
}
}
public static void main (String args[])
{
System.out.println("Original String is : ");
System.out.println("Alive is awesome ");
Changecase.changecase("Alive is awesome ");
}
}
public class MyClass
{
private String txt;
private char lower;
public MyClass(String txt)
{
this.txt = txt;
}
public void print()
{
for(int i=0;i<txt.length();i++)
{
if('A' <= txt.charAt(i) && txt.charAt(i) <= 'Z')
{
lower = (char)(txt.charAt(i) + 32);
System.out.print(lower);
}
else
{
lower = txt.charAt(i);
System.out.print(lower);
}
}
}
public static void main(String[] args)
{
MyClass mc = new MyClass("BaNaNa");
mc.print();
}
}
Sorry pretty late to the scene but this should solve it. An else condition because when it is not zero it totally discards the alphabet.
If somebody needs clear code without MagicNumbers and as less as possible conversions here is my solution:
final char[] charArray = new char[string.length()];
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
charArray[i] = Character.isLowerCase(c) ? Character.toUpperCase(c) : Character.toLowerCase(c);
}
String.valueOf(charArray);
import java.util.Scanner;
public class LowerToUpperC {
public static void main(String[] args) {
char ch;
int temp;
Scanner scan = new Scanner(System.in);
System.out.print("Enter a Character in Lowercase : ");
ch = scan.next().charAt(0);
temp = (int) ch;
temp = temp - 32;
ch = (char) temp;
System.out.print("Equivalent Character in Uppercase = " +ch);
}
}

Write a method to replace all spaces in a string with '%20'

I have a question about a programming problem from the book Cracking The Code Interview by Gayl Laakmann McDowell, 5th Edition.
The problem states: Write a method to replace all spaces in a string with '%20'. Assume string has sufficient space at end of string to hold additional characters, and that you're given a true length of a string. I used the books code, implementing the solution in Java using a character array (given the fact that Java Strings are immutable):
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);
}
}
The output I am getting from the replaceSpaces() call is: the%20do which is cutting of the last character of the original array. I have been scratching my head over this, can anyone explain to me why the algorithm is doing this?
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();
}
You are passing the length as 6, which is causing this. Pass length as 7 including space.
Other wise
for(i = length - 1; i >= 0; i--) {
will not consider last char.
With these two changes I got the output: the%20dog
1) Change space count to 2 [since length already includes 1 of the 3 characters you need for %20]
newLength = length + (spaceCount * 2);
2) Loop should start on length
for(i = length; i >= 0; i--) {
Here is my solution. I check for the ascii code 32 then put a %20 instead of it.Time complexity of this solution is 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();
}
This is my code for this question. Seems like working for me. If you're interested, please have a look. It's written in 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));
}
}
You can also use substring method and the ascii for space (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;
}
To test:
System.out.println(cc.replaceSpaceInString("mon day "));
Output:
mon%20day%20
You could just do this.
No need to calculate the length or whatever.
Strings are immutable anyways.
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];
}
}
}
This code works :)
We can use a regular expression to solve this problem. For example:
public String replaceStringWithSpace(String str){
return str.replaceAll("[\\s]", "%20");
}
This works correctly. However, using a StringBuffer object increases space complexity.
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;
}
Another way of doing this.
I am assuming the trailing spaces don't need to be converted to %20 and that the trailing spaces provide enough room for %20s to be stuffed in between
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();
}}
A simple approach:
Reverse the given string and check where the first character appears.
Using string builder to append "02%" for spaces - since the string is reversed.
Finally reverse the string once again.
Note: We reverse the string so as to prevent an addition of "%20" to the trailing spaces.
Hope that helps!
The question in the book mentions that the replacement should be in place so it is not possible to assign extra arrays, it should use constant space. You should also take into account many edge cases, this is my 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] = ' ';
}
}
}
Any reason not to use 'replace' method?
public String replaceSpaces(String s){
return s.replace(" ", "%20");}
Hm... I am wondering about this problem as well. Considering what I have seen in here. The book solution does not fit Java because it uses in-place
char []
modification and solutions in here that use char [] or return void don't fit as well because Java does not use pointers.
So I was thinking, the obvious solution would be
private static String encodeSpace(String string) {
return string.replcaceAll(" ", "%20");
}
but this is probably not what your interviewer would like to see :)
// 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;
}
this looks fine I thought, and you only need one pass through the string, so the complexity should be O(n), right? Wrong! The problem is in
result += c;
which is the same as
result = result + c;
which actually copies a string and creates a copy of it. In java strings are represented as
private final char value[];
which makes them immutable (for more info I would check java.lang.String and how it works). This fact will bump up the complexity of this algorithm to O(N^2) and a sneaky recruiter can use this fact to fail you :P Thus, I came in with a new low-level solution which you will never use in practice, but which is good in theory :)
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);
}
But I wonder what is wrong with following code:
private static String urlify(String originalString) {
String newString = "";
if (originalString.contains(" ")) {
newString = originalString.replace(" ", "%20");
}
return newString;
}
Question : Urlify the spaces with %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
My solution using StringBuilder with time complexity 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 case :
#Test
public void testUrl() {
assertEquals("Mr%20John%20Smith", URLify.url("Mr John Smith ", 13));
}
Can you use 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();
}
I am also looking at that question in the book. I believe we can just use String.trim() and String.replaceAll(" ", "%20) here
I updated the solution here. http://rextester.com/CWAPCV11970
If we are creating new array and not in-place trasition, then why do we need to walk backwards?
I modified the real solution slightly to walk forward to create target Url-encoded-string.
Time complexity:
O(n) - Walking original string
O(1) - Creating target string incrementally
where 'n' is number of chars in original string
Space complexity:
O(n + m) - Duplicate space to store escaped spaces and string.
where 'n' is number of chars in original string and 'm' is length of escaped spaces
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();
}
}
public class 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:: Hello%20%20%20World%20
Remember that you only to want replace ' ' with '%20' when the latter is not a leading or trailing space. Several answers above do not account for this. For what it's worth, I get "index out of bounds error" when I run Laakmann's solution example.
Here's my own solution, which runs O(n) and is implemented in C#:
public static string URLreplace(string str, int n)
{
var len = str.Length;
if (len == n)
return str;
var sb = new StringBuilder();
var i = 0;
while (i < len)
{
char c = str[i];
if (c == ' ')
{
while (i < len && str[i] == ' ')
{
i++; //skip ahead
}
}
else
{
if (sb.Length > 0 && str[i - 1] == ' ')
sb.Append("%20" + c);
else
sb.Append(c);
i++;
}
}
return sb.ToString();
}
Test:
//Arrange
private string _str = " Mr John Smith ";
private string _result = "Mr%20John%20Smith";
private int _int = 13;
[TestMethod]
public void URLified()
{
//Act
var cleaned = URLify.URLreplace(_str, _int);
//Assert
Assert.IsTrue(cleaned == _result);
}
One line code
System.out.println(s.trim().replace(" ","%20"));
// while passing the input make sure you use the .toCharArray method becuase strings are immutable
public static 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 = "Mr John Smith ".toCharArray();
int length = 13;
replaceSpaces(ch, length);
}
`// 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;
}`

Increase string value

Java question here:
If i have a string "a", how can I "add" value to the string, so I get a "b" and so on?
like "a++"
String str = "abcde";
System.out.println(getIncrementedString(str));
Output
bcdef
//this code will give next char in unicode sequence
public static String getIncrementedString(String str){
StringBuilder sb = new StringBuilder();
for(char c:str.toCharArray()){
sb.append(++c);
}
return sb.toString();
}
If you use the char primitive data type you can accomplish this:
char letter = 'a';
letter++;
System.out.println(letter);
prints out b
i made some changes to te paulo eberman code, to handle digits and characters, if valuable for someone i share this mod....
public final static char MIN_DIGIT = '0';
public final static char MAX_DIGIT = '9';
public final static char MIN_LETTER = 'A';
public final static char MAX_LETTER = 'Z';
public String incrementedAlpha(String original) {
StringBuilder buf = new StringBuilder(original);
//int index = buf.length() -1;
int i = buf.length() - 1;
//while(index >= 0) {
while (i >= 0) {
char c = buf.charAt(i);
c++;
// revisar si es numero
if ((c - 1) >= MIN_LETTER && (c - 1) <= MAX_LETTER) {
if (c > MAX_LETTER) { // overflow, carry one
buf.setCharAt(i, MIN_LETTER);
i--;
continue;
}
} else {
if (c > MAX_DIGIT) { // overflow, carry one
buf.setCharAt(i, MIN_DIGIT);
i--;
continue;
}
}
// revisar si es numero
buf.setCharAt(i, c);
return buf.toString();
}
// overflow at the first "digit", need to add one more digit
buf.insert(0, MIN_DIGIT);
return buf.toString();
}
i hope be usefull for someone.
use this code to increment char value by an integer
int a='a';
System.out.println("int: "+a);
a=a+3;
char c=(char)a;
System.out.println("char :"+c);
Convert the string to a char.
Increment the char.
Convert the char
back to a string.
Example:
//convert a single letter string to char
String a = "a";
char tmp = a.charAt(0);
//increment char
tmp++;
//convert char to string
String b = String.valueOf(tmp);
System.out.println(b);
Assuming you want something like aaab => aaac and not => bbbc, this would work:
public String incremented(String original) {
StringBuilder buf = new StringBuilder(original);
int index = buf.length() -1;
while(index >= 0) {
char c = buf.charAt(i);
c++;
buf.setCharAt(i, c);
if(c == 0) { // overflow, carry one
i--;
continue;
}
return buf.toString();
}
// overflow at the first "digit", need to add one more digit
buf.insert(0, '\1');
return buf.toString();
}
This treats all characters (in fact char values) the same, and fails (does strange stuff) for some unicode code-points outside the first plane (which occupy two char values in a String).
If you only want to use english lowercase letters as digits, you can try this variant:
public final static char MIN_DIGIT = 'a';
public final static char MAX_DIGIT = 'z';
public String incrementedAlpha(String original) {
StringBuilder buf = new StringBuilder(original);
int index = buf.length() -1;
while(index >= 0) {
char c = buf.charAt(i);
c++;
if(c > MAX_DIGIT) { // overflow, carry one
buf.setCharAt(i, MIN_DIGIT);
i--;
continue;
}
buf.setCharAt(i, c);
return buf.toString();
}
// overflow at the first "digit", need to add one more digit
buf.insert(0, MIN_DIGIT);
return buf.toString();
}
This does a => b => c, y => z => aa => ab.
if you want to do more calculation with the string, consider staying with StringBuilder (or StringBuffer for multithreaded access) instead of repeatedly copying between String and StringBuilder.
Or use a class made to do this, like BigInteger.

Categories