function to remove duplicate characters in a string - java
The following code is trying to remove any duplicate characters in a string. I'm not sure if the code is right. Can anybody help me work with the code (i.e whats actually happening when there is a match in characters)?
public static void removeDuplicates(char[] str) {
if (str == null) return;
int len = str.length;
if (len < 2) return;
int tail = 1;
for (int i = 1; i < len; ++i) {
int j;
for (j = 0; j < tail; ++j) {
if (str[i] == str[j]) break;
}
if (j == tail) {
str[tail] = str[i];
++tail;
}
}
str[tail] = 0;
}
The function looks fine to me. I've written inline comments. Hope it helps:
// function takes a char array as input.
// modifies it to remove duplicates and adds a 0 to mark the end
// of the unique chars in the array.
public static void removeDuplicates(char[] str) {
if (str == null) return; // if the array does not exist..nothing to do return.
int len = str.length; // get the array length.
if (len < 2) return; // if its less than 2..can't have duplicates..return.
int tail = 1; // number of unique char in the array.
// start at 2nd char and go till the end of the array.
for (int i = 1; i < len; ++i) {
int j;
// for every char in outer loop check if that char is already seen.
// char in [0,tail) are all unique.
for (j = 0; j < tail; ++j) {
if (str[i] == str[j]) break; // break if we find duplicate.
}
// if j reachs tail..we did not break, which implies this char at pos i
// is not a duplicate. So we need to add it our "unique char list"
// we add it to the end, that is at pos tail.
if (j == tail) {
str[tail] = str[i]; // add
++tail; // increment tail...[0,tail) is still "unique char list"
}
}
str[tail] = 0; // add a 0 at the end to mark the end of the unique char.
}
Your code is, I'm sorry to say, very C-like.
A Java String is not a char[]. You say you want to remove duplicates from a String, but you take a char[] instead.
Is this char[] \0-terminated? Doesn't look like it because you take the whole .length of the array. But then your algorithm tries to \0-terminate a portion of the array. What happens if the arrays contains no duplicates?
Well, as it is written, your code actually throws an ArrayIndexOutOfBoundsException on the last line! There is no room for the \0 because all slots are used up!
You can add a check not to add \0 in this exceptional case, but then how are you planning to use this code anyway? Are you planning to have a strlen-like function to find the first \0 in the array? And what happens if there isn't any? (due to all-unique exceptional case above?).
What happens if the original String/char[] contains a \0? (which is perfectly legal in Java, by the way, see JLS 10.9 An Array of Characters is Not a String)
The result will be a mess, and all because you want to do everything C-like, and in place without any additional buffer. Are you sure you really need to do this? Why not work with String, indexOf, lastIndexOf, replace, and all the higher-level API of String? Is it provably too slow, or do you only suspect that it is?
"Premature optimization is the root of all evils". I'm sorry but if you can't even understand what the original code does, then figuring out how it will fit in the bigger (and messier) system will be a nightmare.
My minimal suggestion is to do the following:
Make the function takes and returns a String, i.e. public static String removeDuplicates(String in)
Internally, works with char[] str = in.toCharArray();
Replace the last line by return new String(str, 0, tail);
This does use additional buffers, but at least the interface to the rest of the system is much cleaner.
Alternatively, you can use StringBuilder as such:
static String removeDuplicates(String s) {
StringBuilder noDupes = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
String si = s.substring(i, i + 1);
if (noDupes.indexOf(si) == -1) {
noDupes.append(si);
}
}
return noDupes.toString();
}
Note that this is essentially the same algorithm as what you had, but much cleaner and without as many little corner cases, etc.
Given the following question :
Write code to remove the duplicate characters in a string without
using any additional buffer. NOTE: One or two additional variables
are fine. An extra copy of the array is not.
Since one or two additional variables are fine but no buffer is allowed, you can simulate the behaviour of a hashmap by using an integer to store bits instead. This simple solution runs at O(n), which is faster than yours. Also, it isn't conceptually complicated and in-place :
public static void removeDuplicates(char[] str) {
int map = 0;
for (int i = 0; i < str.length; i++) {
if ((map & (1 << (str[i] - 'a'))) > 0) // duplicate detected
str[i] = 0;
else // add unique char as a bit '1' to the map
map |= 1 << (str[i] - 'a');
}
}
The drawback is that the duplicates (which are replaced with 0's) will not be placed at the end of the str[] array. However, this can easily be fixed by looping through the array one last time. Also, an integer has the capacity for only regular letters.
private static String removeDuplicateCharactersFromWord(String word) {
String result = new String("");
for (int i = 0; i < word.length(); i++) {
if (!result.contains("" + word.charAt(i))) {
result += "" + word.charAt(i);
}
}
return result;
}
This is my solution.
The algorithm is mainly the same as the one in the book "Cracking the code interview" where this exercise comes from, but I tried to improve it a bit and make the code more understandable:
public static void removeDuplicates(char[] str) {
// if string has less than 2 characters, it can't contain
// duplicate values, so there's nothing to do
if (str == null || str.length < 2) {
return;
}
// variable which indicates the end of the part of the string
// which is 'cleaned' (all duplicates removed)
int tail = 0;
for (int i = 0; i < str.length; i++) {
boolean found = false;
// check if character is already present in
// the part of the array before the current char
for (int j = 0; j < i; j++) {
if (str[j] == str[i]) {
found = true;
break;
}
}
// if char is already present
// skip this one and do not copy it
if (found) {
continue;
}
// copy the current char to the index
// after the last known unique char in the array
str[tail] = str[i];
tail++;
}
str[tail] = '\0';
}
One of the important requirements from the book is to do it in-place (as in my solution), which means that no additional data structure should be used as a helper while processing the string. This improves performance by not wasting memory unnecessarily.
char[] chars = s.toCharArray();
HashSet<Character> charz = new HashSet<Character>();
for(Character c : s.toCharArray() )
{
if(!charz.contains(c))
{
charz.add(c);
//System.out.print(c);
}
}
for(Character c : charz)
{
System.out.print(c);
}
public String removeDuplicateChar(String nonUniqueString) {
String uniqueString = "";
for (char currentChar : nonUniqueString.toCharArray()) {
if (!uniqueString.contains("" + currentChar)) {
uniqueString += currentChar;
}
}
return uniqueString;
}
public static void main (String [] args)
{
String s = "aabbbeeddsfre";//sample string
String temp2="";//string with no duplicates
HashMap<Integer,Character> tc = new HashMap<Integer,Character>();//create a hashmap to store the char's
char [] charArray = s.toCharArray();
for (Character c : charArray)//for each char
{
if (!tc.containsValue(c))//if the char is not already in the hashmap
{
temp2=temp2+c.toString();//add the char to the output string
tc.put(c.hashCode(),c);//and add the char to the hashmap
}
}
System.out.println(temp2);//final string
}
instead of HashMap I think we can use Set too.
I understand that this is a Java question, but since I have a nice solution which could inspire someone to convert this into Java, by all means. Also I like answers where multiple language submissions are available to common problems.
So here is a Python solution which is O(n) and also supports the whole ASCII range. Of course it does not treat 'a' and 'A' as the same:
I am using 8 x 32 bits as the hashmap:
Also input is a string array using dedup(list('some string'))
def dedup(str):
map = [0,0,0,0,0,0,0,0]
for i in range(len(str)):
ascii = ord(str[i])
slot = ascii / 32
bit = ascii % 32
bitOn = map[slot] & (1 << bit)
if bitOn:
str[i] = ''
else:
map[slot] |= 1 << bit
return ''.join(str)
also a more pythonian way to do this is by using a set:
def dedup(s):
return ''.join(list(set(s)))
Substringing method. Concatenation is done with .concat() to avoid allocation additional memory for left hand and right hand of +.
Note: This removes even duplicate spaces.
private static String withoutDuplicatesSubstringing(String s){
for(int i = 0; i < s.length(); i++){
String sub = s.substring(i+1);
int index = -1;
while((index = sub.toLowerCase().indexOf(Character.toLowerCase(s.charAt(i)))) > -1 && !sub.isEmpty()){
sub = sub.substring(0, index).concat(sub.substring(index+1, sub.length()));
}
s = s.substring(0, i+1).concat(sub);
}
return s;
}
Test case:
String testCase1 = "nanananaa! baaaaatmaan! batman!";
Output:
na! btm
Question: Remove Duplicate characters in a string
Method 1 :(Python)
import collections
a = "GiniGinaProtijayi"
aa = collections.OrderedDict().fromkeys(a)
print(''.join(aa))
Method 2 :(Python)
a = "GiniGinaProtijayi"
list = []
aa = [ list.append(ch) for ch in a if ch not in list]
print( ''.join(list))
IN Java:
class test2{
public static void main(String[] args) {
String a = "GiniGinaProtijayi";
List<Character> list = new ArrayList<>();
for(int i = 0 ; i < a.length() ;i++) {
char ch = a.charAt(i);
if( list.size() == 0 ) {list.add(ch);}
if(!list.contains(ch)) {list.add(ch) ;}
}//for
StringBuffer sbr = new StringBuffer();
for( char ch : list) {sbr.append(ch);}
System.out.println(sbr);
}//main
}//end
This would be much easier if you just looped through the array and added all new characters to a list, then retruned that list.
With this approach, you need to reshuffle the array as you step through it and eventually redimension it to the appropriate size in the end.
String s = "Javajk";
List<Character> charz = new ArrayList<Character>();
for (Character c : s.toCharArray()) {
if (!(charz.contains(Character.toUpperCase(c)) || charz
.contains(Character.toLowerCase(c)))) {
charz.add(c);
}
}
ListIterator litr = charz.listIterator();
while (litr.hasNext()) {
Object element = litr.next();
System.err.println(":" + element);
} }
this will remove the duplicate if the character present in both the case.
public class RemoveDuplicateInString {
public static void main(String[] args) {
String s = "ABCDDCA";
RemoveDuplicateInString rs = new RemoveDuplicateInString();
System.out.println(rs.removeDuplicate(s));
}
public String removeDuplicate(String s) {
String retn = null;
boolean[] b = new boolean[256];
char[] ch = s.toCharArray();
for (int i = 0; i < ch.length; i++) {
if (b[ch[i]]) {
ch[i]=' ';
}
else {
b[ch[i]] = true;
}
}
retn = new String(ch);
return retn;
}
}
/* program to remove the duplicate character in string */
/* Author senthilkumar M*/
char *dup_remove(char *str)
{
int i = 0, j = 0, l = strlen(str);
int flag = 0, result = 0;
for(i = 0; i < l; i++) {
result = str[i] - 'a';
if(flag & (1 << result)) {
*/* if duplicate found remove & shift the array*/*
for(j = i; j < l; j++) {
str[j] = str[j+1];
}
i--;
l--; /* duplicates removed so string length reduced by 1 character*/
continue;
}
flag |= (1 << result);
}
return str;
}
public class RemoveCharsFromString {
static String testcase1 = "No, I am going to Noida";
static String testcase2 = "goings";
public static void main(String args[])throws StringIndexOutOfBoundsException{
RemoveCharsFromString testInstance= new RemoveCharsFromString();
String result = testInstance.remove(testcase1,testcase2);
System.out.println(result);
}
//write your code here
public String remove(String str, String str1)throws StringIndexOutOfBoundsException
{ String result=null;
if (str == null)
return "";
try
{
for (int i = 0; i < str1.length (); i++)
{
char ch1=str1.charAt(i);
for(int j=0;j<str.length();j++)
{
char ch = str.charAt (j);
if (ch == ch1)
{
String s4=String.valueOf(ch);
String s5= str.replaceAll(s4, "");
str=s5;
}
}
}
}
catch(Exception e)
{
}
result=str;
return result;
}
}
public static void main(String[] args) {
char[] str = { 'a', 'b', 'a','b','c','e','c' };
for (int i = 1; i < str.length; i++) {
for (int j = 0; j < i; j++) {
if (str[i] == str[j]) {
str[i] = ' ';
}
}
}
System.out.println(str);
}
An improved version for using bitmask to handle 256 chars:
public static void removeDuplicates3(char[] str)
{
long map[] = new long[] {0, 0, 0 ,0};
long one = 1;
for (int i = 0; i < str.length; i++)
{
long chBit = (one << (str[i]%64));
int n = (int) str[i]/64;
if ((map[n] & chBit ) > 0) // duplicate detected
str[i] = 0;
else // add unique char as a bit '1' to the map
map[n] |= chBit ;
}
// get rid of those '\0's
int wi = 1;
for (int i=1; i<str.length; i++)
{
if (str[i]!=0) str[wi++] = str[i];
}
// setting the rest as '\0'
for (;wi<str.length; wi++) str[wi] = 0;
}
Result: "##1!!ASDJasanwAaw.,;..][,[]==--0" ==> "#1!ASDJasnw.,;][=-0" (double quotes not included)
This function removes duplicate from string inline. I have used C# as a coding language and the duplicates are removed inline
public static void removeDuplicate(char[] inpStr)
{
if (inpStr == null) return;
if (inpStr.Length < 2) return;
for (int i = 0; i < inpStr.Length; ++i)
{
int j, k;
for (j = 1; j < inpStr.Length; j++)
{
if (inpStr[i] == inpStr[j] && i != j)
{
for (k = j; k < inpStr.Length - 1; k++)
{
inpStr[k] = inpStr[k + 1];
}
inpStr[k] = ' ';
}
}
}
Console.WriteLine(inpStr);
}
(Java) Avoiding usage of Map, List data structures:
private String getUniqueStr(String someStr) {
StringBuilder uniqueStr = new StringBuilder();
if(someStr != null) {
for(int i=0; i <someStr.length(); i++) {
if(uniqueStr.indexOf(String.valueOf(someStr.charAt(i))) == -1) {
uniqueStr.append(someStr.charAt(i));
}
}
}
return uniqueStr.toString();
}
package com.java.exercise;
public class RemoveCharacter {
/**
* #param args
*/
public static void main(String[] args) {
RemoveCharacter rem = new RemoveCharacter();
char[] ch=rem.GetDuplicates("JavavNNNNNNC".toCharArray());
char[] desiredString="JavavNNNNNNC".toCharArray();
System.out.println(rem.RemoveDuplicates(desiredString, ch));
}
char[] GetDuplicates(char[] input)
{
int ctr=0;
char[] charDupl=new char[20];
for (int i = 0; i <input.length; i++)
{
char tem=input[i];
for (int j= 0; j < i; j++)
{
if (tem == input[j])
{
charDupl[ctr++] = input[j];
}
}
}
return charDupl;
}
public char[] RemoveDuplicates(char[] input1, char []input2)
{
int coutn =0;
char[] out2 = new char[10];
boolean flag = false;
for (int i = 0; i < input1.length; i++)
{
for (int j = 0; j < input2.length; j++)
{
if (input1[i] == input2[j])
{
flag = false;
break;
}
else
{
flag = true;
}
}
if (flag)
{
out2[coutn++]=input1[i];
flag = false;
}
}
return out2;
}
}
Yet another solution, seems to be the most concise so far:
private static String removeDuplicates(String s)
{
String x = new String(s);
for(int i=0;i<x.length()-1;i++)
x = x.substring(0,i+1) + (x.substring(i+1)).replace(String.valueOf(x.charAt(i)), "");
return x;
}
I have written a piece of code to solve the problem.
I have checked with certain values, got the required output.
Note: It's time consuming.
static void removeDuplicate(String s) {
char s1[] = s.toCharArray();
Arrays.sort(s1); //Sorting is performed, a to z
//Since adjacent values are compared
int myLength = s1.length; //Length of the character array is stored here
int i = 0; //i refers to the position of original char array
int j = 0; //j refers to the position of char array after skipping the duplicate values
while(i != myLength-1 ){
if(s1[i]!=s1[i+1]){ //Compares two adjacent characters, if they are not the same
s1[j] = s1[i]; //if not same, then, first adjacent character is stored in s[j]
s1[j+1] = s1[i+1]; //Second adjacent character is stored in s[j+1]
j++; //j is incremented to move to next location
}
i++; //i is incremented
}
//the length of s is i. i>j
String s4 = new String (s1); //Char Array to String
//s4[0] to s4[j+1] contains the length characters after removing the duplicate
//s4[j+2] to s4[i] contains the last set of characters of the original char array
System.out.println(s4.substring(0, j+1));
}
Feel free to run my code with your inputs. Thanks.
public class RemoveRepeatedCharacters {
/**
* This method removes duplicates in a given string in one single pass.
* Keeping two indexes, go through all the elements and as long as subsequent characters match, keep
* moving the indexes in opposite directions. When subsequent characters don't match, copy value at higher index
* to (lower + 1) index.
* Time Complexity = O(n)
* Space = O(1)
*
*/
public static void removeDuplicateChars(String text) {
char[] ch = text.toCharArray();
int i = 0; //first index
for(int j = 1; j < ch.length; j++) {
while(i >= 0 && j < ch.length && ch[i] == ch[j]) {
i--;
j++;
System.out.println("i = " + i + " j = " + j);
}
if(j < ch.length) {
ch[++i] = ch[j];
}
}
//Print the final string
for(int k = 0; k <= i; k++)
System.out.print(ch[k]);
}
public static void main(String[] args) {
String text = "abccbdeefgg";
removeDuplicateChars(text);
}
}
public class StringRedundantChars {
/**
* #param args
*/
public static void main(String[] args) {
//initializing the string to be sorted
String sent = "I love painting and badminton";
//Translating the sentence into an array of characters
char[] chars = sent.toCharArray();
System.out.println("Before Sorting");
showLetters(chars);
//Sorting the characters based on the ASCI character code.
java.util.Arrays.sort(chars);
System.out.println("Post Sorting");
showLetters(chars);
System.out.println("Removing Duplicates");
stripDuplicateLetters(chars);
System.out.println("Post Removing Duplicates");
//Sorting to collect all unique characters
java.util.Arrays.sort(chars);
showLetters(chars);
}
/**
* This function prints all valid characters in a given array, except empty values
*
* #param chars Input set of characters to be displayed
*/
private static void showLetters(char[] chars) {
int i = 0;
//The following loop is to ignore all white spaces
while ('\0' == chars[i]) {
i++;
}
for (; i < chars.length; i++) {
System.out.print(" " + chars[i]);
}
System.out.println();
}
private static char[] stripDuplicateLetters(char[] chars) {
// Basic cursor that is used to traverse through the unique-characters
int cursor = 0;
// Probe which is used to traverse the string for redundant characters
int probe = 1;
for (; cursor < chars.length - 1;) {
// Checking if the cursor and probe indices contain the same
// characters
if (chars[cursor] == chars[probe]) {
System.out.println("Removing char : " + chars[probe]);
// Please feel free to replace the redundant character with
// character. I have used '\0'
chars[probe] = '\0';
// Pushing the probe to the next character
probe++;
} else {
// Since the probe has traversed the chars from cursor it means
// that there were no unique characters till probe.
// Hence set cursor to the probe value
cursor = probe;
// Push the probe to refer to the next character
probe++;
}
}
System.out.println();
return chars;
}
}
This is my solution
public static String removeDup(String inputString){
if (inputString.length()<2) return inputString;
if (inputString==null) return null;
char[] inputBuffer=inputString.toCharArray();
for (int i=0;i<inputBuffer.length;i++){
for (int j=i+1;j<inputBuffer.length;j++){
if (inputBuffer[i]==inputBuffer[j]){
inputBuffer[j]=0;
}
}
}
String result=new String(inputBuffer);
return result;
}
Well I came up with the following solution.
Keeping in mind that S and s are not duplicates. Also I have just one hard coded value.. But the code works absolutely fine.
public static String removeDuplicate(String str)
{
StringBuffer rev = new StringBuffer();
rev.append(str.charAt(0));
for(int i=0; i< str.length(); i++)
{
int flag = 0;
for(int j=0; j < rev.length(); j++)
{
if(str.charAt(i) == rev.charAt(j))
{
flag = 0;
break;
}
else
{
flag = 1;
}
}
if(flag == 1)
{
rev.append(str.charAt(i));
}
}
return rev.toString();
}
I couldn't understand the logic behind the solution so I wrote my simple solution:
public static void removeDuplicates(char[] str) {
if (str == null) return; //If the string is null return
int length = str.length; //Getting the length of the string
if (length < 2) return; //Return if the length is 1 or smaller
for(int i=0; i<length; i++){ //Loop through letters on the array
int j;
for(j=i+1;j<length;j++){ //Loop through letters after the checked letters (i)
if (str[j]==str[i]){ //If you find duplicates set it to 0
str[j]=0;
}
}
}
}
Using guava you can just do something like Sets.newHashSet(charArray).toArray();
If you are not using any libraries, you can still use new HashSet<Char>() and add your char array there.
#include <iostream>
#include <string>
using namespace std;
int main() {
// your code goes here
string str;
cin >> str;
long map = 0;
for(int i =0; i < str.length() ; i++){
if((map & (1L << str[i])) > 0){
str[i] = 0;
}
else{
map |= 1L << str[i];
}
}
cout << str;
return 0;
}
Related
Find the length of the longest substring without repeating characters
So the problem I'm trying to solve this problem given a string, find the length of the longest substring without repeating characters. I'm aware of the HashMap based solution, but that fails in case of overlapping substrings.Here's my code. public static int lengthOfLongestSubstring(String s) { Deque<Character> primary = new ArrayDeque<>(); Deque<Character> secondary = new ArrayDeque<>(); for (int i = 0; i < s.length() ; i++) { char c = s.charAt(i); if(primary.contains(c)){ while(primary.peek() != c){ secondary.offerLast(primary.poll()); } secondary.offerFirst(c); primary = secondary; secondary.clear(); }else{ primary.offerFirst(c); } } return primary.size(); } This fails at the line where I do primary = secondary otherwise I think I'm doing it right logically. To test the correctness I'm using the string dvdf Can someone help me understand why this is not working.
I am wondering this: primary = secondary; secondary.clear(); It's assignment by reference. You set primary and secondary to point to the same data and clear it. Is that your intention? What about this: public static int lengthOfLongestSubstring(String s) { Deque<Character> primary = new ArrayDeque<>(); Deque<Character> secondary = new ArrayDeque<>(); Deque<Character> longest = new ArrayDeque<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (primary.contains(c)) { // Store longest if (primary.size() > longest.size()) { longest = new ArrayDeque<>(primary); } while (primary.peek() != c) { secondary.offerLast(primary.poll()); } secondary.offerFirst(c); primary = secondary; secondary = new ArrayDeque<>(); // Altered } else { primary.offerFirst(c); } } // Also check at end of line. if (primary.size() > longest.size()) { longest = primary; } return longest.size(); } OUTPUT dvdf => 3 dvdfvadv => 4 EDIT Your logic is right. I just altered one line. EDIT Keep track of the longest.
May not be exact answer you were looking. Try to avoid using ArrayDeque in a multi threaded env as it is not thread safe. Go through this link:: Find longest substring without repeating characters this returns a string. you can use .length() method and find the length as you require. Hope it helps.
You can try this: public class LongestSubstring { public static void main(String [] args){ System.out.println(longestSub("abcdefgghij")); //prints 7 abcdefg g is repeated character } public static int longestSub(String s) { if(s==null) return 0; boolean[] flag = new boolean[256]; int result = 0; int start = 0; char[] arr = s.toCharArray(); for (int i = 0; i < arr.length; i++) { char current = arr[i]; if (flag[current]) { result = Math.max(result, i - start); // the loop update the new start point and reset flag array for (int k = start; k < i; k++) { if (arr[k] == current) { start = k + 1; break; } flag[arr[k]] = false; } } else { flag[current] = true; } } result = Math.max(arr.length - start, result); return result; } }
/*C++ program to print the largest substring in a string without repetation of character. eg. given string :- abcabbabcd largest substring possible without repetition of character is abcd.*/ #include<bits/stdc++.h> using namespace std; int main() { string str,str1; int max =0; string finalstr; vector<string> str2; cin>>str; int len = str.length(); for(int i=0;i<len;i++) { if(str1.find(str[i]) != std::string::npos) { str2.push_back(str1); char p = str[i]; str1 = ""; i--; while(p!=str[i]) i--; } else str1.append(str,i,1); } str2.push_back(str1); for(int i=0;i<str2.size();i++) { if(max<str2[i].length()){ max = str2[i].length(); finalstr = str2[i]; } } cout<<finalstr<<endl; cout<<finalstr.length()<<endl; }
implement basic string compression
I am working on question 1.5 from the book Cracking The Coding interview. The problem is to take a string "aabcccccaaa" and turn it into a2b1c5a3. If the compressed string is not smaller than the original string, then return the original string. My code is below. I used an ArrayList because I would not know how long the compressed string would be. My output is [a, 2, b, 1, c, 5], aabc, []. When the program gets to the end of string, it doesn't have a character to compare the last character too. import java.util.*; import java.io.*; public class stringCompression { public static void main(String[] args) { String a = "aabcccccaaa"; String b = "aabc"; String v = "aaaa"; check(a); System.out.println(""); check(b); System.out.println(""); check(v); } public static void check(String g){ ArrayList<Character> c = new ArrayList<Character>(); int count = 1; int i = 0; int h = g.length(); for(int j = i + 1; j < g.length(); j++) { if(g.charAt(i) == g.charAt(j)){ count++; } else { c.add(g.charAt(i)); c.add((char)( '0' + count)); i = j; count = 1; } } if(c.size() == g.length()){ System.out.print(g); } else{ System.out.print(c); } } }
In the last loop you're not adding the result to the array. When j = g.length() still needs to add the current char and count to the array. So you could check the next value of j before increment it: for(int j = i + 1; j < g.length(); j++) { if(g.charAt(i) == g.charAt(j)){ count++; } else { c.add(g.charAt(i)); c.add((char)( '0' + count)); i = j; count = 1; } if((j + 1) = g.length()){ c.add(g.charAt(i)); c.add((char)( '0' + count)); } }
I would use a StringBuilder rather than an ArrayList to build your compressed String. When you start compressing, the first character should already be added to the result. The count of the character will be added once you've encountered a different character. When you've reached the end of the String you should just be appending the remaining count to the result for the last letter. public static void main(String[] args) throws Exception { String[] data = new String[] { "aabcccccaaa", "aabc", "aaaa" }; for (String d : data) { System.out.println(compress(d)); } } public static String compress(String str) { StringBuilder compressed = new StringBuilder(); // Add first character to compressed result char currentChar = str.charAt(0); compressed.append(currentChar); // Always have a count of 1 int count = 1; for (int i = 1; i < str.length(); i++) { char nextChar = str.charAt(i); if (currentChar == nextChar) { count++; } else { // Append the count of the current character compressed.append(count); // Set the current character and count currentChar = nextChar; count = 1; // Append the new current character compressed.append(currentChar); } } // Append the count of the last character compressed.append(count); // If the compressed string is not smaller than the original string, then return the original string return (compressed.length() < str.length() ? compressed.toString() : str); } Results: a2b1c5a3 aabc a4
You have two errors: one that Typo just mentioned, because your last character was not added; and another one, if the original string is shorter like "abc" with only three chars: "a1b1c1" has six chars (the task is "If the compressed string is not smaller than the original string, then return the original string.") You have to change your if statement, ask for >= instead of == if(c.size() >= g.length()){ System.out.print(g); } else { System.out.print(c); }
Use StringBuilder and then iterate on the input string. private static string CompressString(string inputString) { var count = 1; var compressedSb = new StringBuilder(); for (var i = 0; i < inputString.Length; i++) { // Check if we are at the end if(i == inputString.Length - 1) { compressedSb.Append(inputString[i] + count.ToString()); break; } if (inputString[i] == inputString[i + 1]) count++; else { compressedSb.Append(inputString[i] + count.ToString()); count = 1; } } var compressedString = compressedSb.ToString(); return compressedString.Length > inputString.Length ? inputString : compressedString; }
Trouble breaking from a method
I am having difficulties with my method returning true. It is a boolean method that takes two words and tries to see if one can be turned into the other by transposing two neighboring letters. I have had no troubles getting the false boolean. When the code gets to the for loop with an if statement in it it runs fine but does not return true when the if statement is satisfied. For some reason it continues through the for loop. For example, when comparing "teh" and "the" when the loop hits 1 the if statement is satisfied but does not return true, the for lo public static boolean transposable(String word1, String word2) { ArrayList<Character> word1char = new ArrayList<Character>(); ArrayList<Character> word2char = new ArrayList<Character>(); int word1length = word1.length(); int word2length = word2.length(); int count = 0; String w1 = word1.toUpperCase(); String w2 = word2.toUpperCase(); if(word1length != word2length) { return false; } for(int i = 0; i < word1length; i++) { char letter1 = w1.charAt(i); word1char.add(letter1); char letter2 = w2.charAt(i); word2char.add(letter2); } for(int i = 0; i < word1length; i++) { char w1c = word1char.get(i); char w2c = word2char.get(i); if(w1c == w2c) { count++; } } if(count < word1length - 2) { return false; } for(int i = 0; i < word1length; i++) { char w1c = word1char.get(i); char w2c = word2char.get(i+1); if(w1c == w2c) { return true; } } return false; } op just keeps running. What am I doing wrong?
As pointed out in the comments this doesn't seem to be the easiest way around this problem. Here is a solution which tries to follow your logic and includes the use of toUpperCase() and ArrayLists. Going over your code it looks like you were getting a bit lost in your logic. This is because you had one method trying to do everything. Break things down into smaller methods and you also will benefit by not having to repeat code and it keeps things much cleaner. The code below is tested with Java8 (although there is no reason why this should not work with Java 7). public static void main(String args[]) { String word1 = "Hello"; String word2 = "Hlelo"; transposable(word1, word2); } private static boolean transposable(String word1, String word2) { // Get an ArrayList of characters for both words. ArrayList<Character> word1CharacterList = listOfCharacters(word1); ArrayList<Character> word2CharacterList = listOfCharacters(word2); boolean areWordsEqual; // Check that the size of the CharacterLists is the same if (word1CharacterList.size() != word2CharacterList.size()) { return false; } // check to see if words are equal to start with areWordsEqual = checkIfTwoWordsAreTheSame(word1CharacterList, word2CharacterList); System.out.print("\n" + "Words are equal to be begin with = " + areWordsEqual); if (!areWordsEqual) { /* This loop i must start at 1 because you can't shift an ArrayList index of 0 to the left! Loops through all the possible combinations and checks if there is a match. */ for (int i = 1; i < word1CharacterList.size(); i++) { ArrayList<Character> adjustedArrayList = shiftNeighbouringCharacter(word2CharacterList, i); areWordsEqual = checkIfTwoWordsAreTheSame(word1CharacterList, adjustedArrayList); System.out.print("\n" + "Loop count " + i + " words are equal " + areWordsEqual + word1CharacterList + adjustedArrayList.toString()); if (areWordsEqual) { break; } } } return areWordsEqual; } // takes in a String as a parameter and returns an ArrayList of Characters in the order of the String parameter. private static ArrayList<Character> listOfCharacters(String word) { ArrayList<Character> wordCharacters = new ArrayList<Character>(); String tempWord = word.toUpperCase(); for (int wordLength = 0; wordLength < tempWord.length(); wordLength++) { Character currentCharacter = tempWord.charAt(wordLength); wordCharacters.add(currentCharacter); } return wordCharacters; } // takes in two character arrayLists, and compares each index character. private static boolean checkIfTwoWordsAreTheSame(ArrayList<Character> characterList1, ArrayList<Character> characterList2) { // compare list1 against list two for (int i = 0; i < characterList1.size(); i++) { Character currentCharacterList1 = characterList1.get(i); Character currentCharacterList2 = characterList2.get(i); if (!currentCharacterList1.equals(currentCharacterList2)) { return false; } } return true; } // this method takes in an ArrayList of characters and the initial index that we want to shift one place to the left. private static ArrayList<Character> shiftNeighbouringCharacter(ArrayList<Character> characterListToShift, int indexToShiftLeft) { ArrayList<Character> tempCharacterList = new ArrayList<Character>(); int indexAtLeft = indexToShiftLeft - 1; // fill the new arrayList full of nulls. We will have to remove these nulls later before we can add proper values in their place. for (int i = 0; i < characterListToShift.size(); i++) { tempCharacterList.add(null); } //get the current index of indexToShift Character characterOfIndexToShift = characterListToShift.get(indexToShiftLeft); Character currentCharacterInThePositionToShiftTo = characterListToShift.get(indexAtLeft); tempCharacterList.remove(indexAtLeft); tempCharacterList.add(indexAtLeft, characterOfIndexToShift); tempCharacterList.remove(indexToShiftLeft); tempCharacterList.add(indexToShiftLeft, currentCharacterInThePositionToShiftTo); for (int i = 0; i < characterListToShift.size(); i++) { if (tempCharacterList.get(i) == null) { Character character = characterListToShift.get(i); tempCharacterList.remove(i); tempCharacterList.add(i, character); } } return tempCharacterList; } Hope this helps. If you are still struggling then follow along in your debugger. :)
Can anybody help me to correct the following code?
Please help me to identify my mistakes in this code. I am new to Java. Excuse me if I have done any mistake. This is one of codingbat java questions. I am getting Timed Out error message for some inputs like "xxxyakyyyakzzz". For some inputs like "yakpak" and "pakyak" this code is working fine. Question: Suppose the string "yak" is unlucky. Given a string, return a version where all the "yak" are removed, but the "a" can be any char. The "yak" strings will not overlap. public String stringYak(String str) { String result = ""; int yakIndex = str.indexOf("yak"); if (yakIndex == -1) return str; //there is no yak //there is at least one yak //if there are yaks store their indexes in the arraylist ArrayList<Integer> yakArray = new ArrayList<Integer>(); int length = str.length(); yakIndex = 0; while (yakIndex < length - 3) { yakIndex = str.indexOf("yak", yakIndex); yakArray.add(yakIndex); yakIndex += 3; }//all the yak indexes are stored in the arraylist //iterate through the arraylist. skip the yaks and get non-yak substrings for(int i = 0; i < length; i++) { if (yakArray.contains(i)) i = i + 2; else result = result + str.charAt(i); } return result; }
Shouldn't you be looking for any three character sequence starting with a 'y' and ending with a 'k'? Like so? public static String stringYak(String str) { char[] chars = (str != null) ? str.toCharArray() : new char[] {}; StringBuilder sb = new StringBuilder(); for (int i = 0; i < chars.length; i++) { if (chars[i] == 'y' && chars[i + 2] == 'k') { // if we have 'y' and two away is 'k' // then it's unlucky... i += 2; continue; //skip the statement sb.append } //do not append any pattern like y1k or yak etc sb.append(chars[i]); } return sb.toString(); } public static void main(String[] args) { System.out.println(stringYak("1yik2yak3yuk4")); // Remove the "unlucky" strings // The result will be 1234. }
It looks like your programming assignment. You need to use regular expressions. Look at http://www.vogella.com/articles/JavaRegularExpressions/article.html#regex for more information. Remember, that you can not use contains. Your code maybe something like result = str.removeall("y\wk")
you can try this public static String stringYak(String str) { for (int i = 0; i < str.length(); i++) { if(str.charAt(i)=='y'){ str=str.replace("yak", ""); } } return str; }
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; }`