Reversing the even characters of a word - java

I was wondering how one would go about making all of the even characters in a word switch with it's partner on the other side of the word.
For example: abc would look like cba or monkey would be eonkMy.
I am looking for one method that would only move the even characters of a string through the use of recursion or calling the method in the return.
public static String revEven(String str)
{
if(str.length() == 0)
return "";
return str.charAt(str.length() - 1) + revEven(str.substring(0, str.length() -1));
}
The output of the current soulution is:
yeknom
edcba
I need the output to be:
yonkmy
ebcda

convert string into Char[]
String input="monkey";
char[] inparr=input.toCharArray();
int len=input.length;
for(int i=0;i<len/2;i++) //iterate till half length that will work
{
if(i%2==0)
{
//character is even
//swap i and len-i index
int temp=inparr[i];
inparr[i]=inparr[len-i];
inparr[i]=temp;
}
else
{
}
}

I would use a StringBuilder. Only loop for the first half of the input String and increment your loop counter by 2. Something like,
StringBuilder sb = new StringBuilder("monkey");
for (int i = 0; i < sb.length() / 2; i += 2) {
int p = sb.length() - i - 1;
char ch = sb.charAt(p);
sb.setCharAt(p, sb.charAt(i));
sb.setCharAt(i, ch);
}
System.out.println(sb);
Which outputs
yoknem
if you change the declaration of int p to
int p = sb.length() - i - 2;
you get
eonkmy

Related

Improving Program Efficiency

public class cowcode {
public static void main(String[] args) {
long index = 1000000
String line = HELLO
boolean found = false;
if (index <= line.length())
found = true;
while (!found) {
line += buildString(line);
if (index <= line.length())
found = true;
}
if (found)
System.out.println("" + charAt(line, index-1));
}
public static String buildString(String str){
String temp = "" + str.charAt(str.length()-1);
for (int i = 0; i < str.length()-1; i ++){
temp += str.charAt(i);
}
return temp;
}
public static String charAt(String line, long index){
for (int i = 0; i < line.length(); i ++){
if (i == index)
return line.charAt(i) + "";
}
return "";
}
}
Hey! The code above works perfectly fine. However the only problem is runtime.
The objective of this program is to build a string from "HELLO" (which will eventually have the length of at least size index). This is done by rotating the String to the right ("HELLO" --> "HELLOOHELL", and concatenating the original String and the rotated version together. This process will not stop until the index that the program is looking for is found in the String. (so in this example, the String will become "HELLOOHELLLHELLOOHEL" after going through the loop twice).
Do you guys see anything that could be eliminated/shortened to improve runtime?
What I guess is killing you is all of the String concatenations you're doing in buildString. You can cut it down to this:
public static String buildString(String str){
return str.charAt(str.length()-1) + str.substring(0, str.length()-1);
}
You need to calculate the index without actually building the string. The right half of the composite string it rotated, the left one is not. If You have index in the left half of the string, You can just throw away the right half. Hence You simplified the situation. If You have index in the right half, You can transform it to index in the left half. You just need to undo rotation of the string in the right half. So You rotate the index left by one character. Now You can substract legth of half of the string and You have index in the left half of the string. This situation is already described above. So You shorten the string and start again at the beginning. In the end You end up with the string, that is not composed. It is the original string. Now You can address the characters directly with the index as it is now in range of the string.
index = 1000000 - 1;
line = "HELLO";
int len = line.length();
long len2 = len;
while (len2 <= index) {
len2 *= 2;
}
while (len2 > len) {
long lenhalf = len2 / 2;
if (index >= lenhalf) {
index -= lenhalf;
index -= 1;
if (index < 0) {
index += lenhalf;
}
}
len2 = lenhalf;
}
System.out.println(line.charAt((int)index));

Generating all permutations of a certain length

Suppose we have an alphabet "abcdefghiklimnop". How can I recursively generate permutations with repetition of this alphabet in groups of FIVE in an efficient way?
I have been struggling with this a few days now. Any feedback would be helpful.
Essentially this is the same as: Generating all permutations of a given string
However, I just want the permutations in lengths of FIVE of the entire string. And I have not been able to figure this out.
SO for all substrings of length 5 of "abcdefghiklimnop", find the permutations of the substring. For example, if the substring was abcdef, I would want all of the permutations of that, or if the substring was defli, I would want all of the permutations of that substring. The code below gives me all permutations of a string but I would like to use to find all permutations of all substrings of size 5 of a string.
public static void permutation(String str) {
permutation("", str);
}
private static void permutation(String prefix, String str) {
int n = str.length();
if (n == 0) System.out.println(prefix);
else {
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n));
}
}
In order to pick five characters from a string recursively, follow a simple algorithm:
Your method should get a portion filled in so far, and the first position in the five-character permutation that needs a character
If the first position that needs a character is above five, you are done; print the combination that you have so far, and return
Otherwise, put each character into the current position in the permutation, and make a recursive call
This is a lot shorter in Java:
private static void permutation(char[] perm, int pos, String str) {
if (pos == perm.length) {
System.out.println(new String(perm));
} else {
for (int i = 0 ; i < str.length() ; i++) {
perm[pos] = str.charAt(i);
permutation(perm, pos+1, str);
}
}
}
The caller controls the desired length of permutation by changing the number of elements in perm:
char[] perm = new char[5];
permutation(perm, 0, "abcdefghiklimnop");
Demo.
All permutations of five characters will be contained in the set of the first five characters of every permutation. For example, if you want all two character permutations of a four character string 'abcd' you can obtain them from all permutations:
'abcd', 'abdc', 'acbd','acdb' ... 'dcba'
So instead of printing them in your method you can store them to a list after checking to see if that permutation is already stored. The list can either be passed in to the function or a static field, depending on your specification.
class StringPermutationOfKLength
{
// The main recursive method
// to print all possible
// strings of length k
static void printAllKLengthRec(char[] set,String prefix,
int n, int k)
{
// Base case: k is 0,
// print prefix
if (k == 0)
{
System.out.println(prefix);
return;
}
// One by one add all characters
// from set and recursively
// call for k equals to k-1
for (int i = 0; i < n; i++)
{
// Next character of input added
String newPrefix = prefix + set[i];
// k is decreased, because
// we have added a new character
printAllKLengthRec(set, newPrefix,
n, k - 1);
}
}
// Driver Code
public static void main(String[] args)
{
System.out.println("First Test");
char[] set1 = {'a', 'b','c', 'd'};
int k = 2;
printAllKLengthRec(set1, "", set1.length, k);
System.out.println("\nSecond Test");
char[] set2 = {'a', 'b', 'c', 'd'};
k = 1;
printAllKLengthRec(set2, "", set2.length, k);
}
This is can be easily done using bit manipulation.
private void getPermutation(String str, int length)
{
if(str==null)
return;
Set<String> StrList = new HashSet<String>();
StringBuilder strB= new StringBuilder();
for(int i = 0;i < (1 << str.length()); ++i)
{
strB.setLength(0); //clear the StringBuilder
if(getNumberOfOnes(i)==length){
for(int j = 0;j < str.length() ;++j){
if((i & (1 << j))>0){ // to check whether jth bit is set (is 1 or not)
strB.append(str.charAt(j));
}
}
StrList.add(strB.toString());
}
}
System.out.println(Arrays.toString(StrList.toArray()));
}
private int getNumberOfOnes (int n) // to count how many numbers of 1 in binary representation of n
{
int count=0;
while( n>0 )
{
n = n&(n-1);
count++;
}
return count;
}

I am try to take a string and rebuild it with two random int values i created to swap two chars at those positions

public static String jumble(String s) {
int length = s.length() - 2;
Random r = new Random();
int n = r.nextInt(2)+1;
int a = r.nextInt(length)+1;
String s1 ="";
if (s.length() < 4) {
s1 = s1 + s;
} else if (s.length() == 4) {
s1 = s1 + s.charAt(0);
s1 = s1 + s.charAt(2);
s1 = s1 + s.charAt(1);
s1 = s1 + s.charAt(3);
}
while (n == a) {
a = r.nextInt(length)+1;
}
if (0 < n && n < a && a < s.length()) {
s1 = s1 + s.substring(0,n) + s.charAt(a) + s.substring(n + 1, a) + s.charAt(n) + s.substring(a+1,s.length());
}
System.out.println(s1);
return s1;
this is my requirement
String jumble(String): accepts a string and returns a jumbled version of the original: for this method, jumbled means that two randomly chosen characters other than the first and last characters of the string are swapped; this method must use the class, Random. The method must swap two different characters: in other words the two random indices into the string cannot be equal, cannot be 0, and cannot be equal to the string’s length minus one. So, for example, a four-letter string MUST result in the returned string having the same first and last characters and have the second and third characters swapped. Examples of what this method might do: “fist” returns “fsit”, “much” returns “mcuh”, but for longer strings there will be more possible return values: “spill” could return “splil” or “sipll”. Only ONE pair of letters should be swapped and strings shorter than four characters are returned unchanged. When the string length is greater than 3, the original string must never be returned.
I have to use Random class and can only use the string class methods of length, charAt, and substring. this is what i have so far, I really need help creating the last string when it is greater than 4 and i need to use the random numbers i made.
Edit: I have got my code working better now, thanks to Ursa. The problem i have now or at least I think it is a problem is that some times the code does not always print or return anything.
Approach #1
Wrap your input string with StringBuilder builder = new StringBuilder(s);
Get characters with builder.charAt(int) and compare them
Swap characters with builder.setCharAt(int, char)
Take result with builder.toString()
And you don't need to touch other characters.
Approach #2
At the first we should choose indexes of chars to swap:
// 0 < i1 < i2 < s.length - 1
int i1 = 1 + r.nextInt(s.length() - 3); // 1 <= i1 <= s.length - 3
int i2 = 1 + i1 + r.nextInt(s.length() - i1 - 2); // i1 < i2 <= s.length - 2
Then we should split the string on intervals:
[0, i1) - substring before the first swap char
{i1} - the first swap char
[i1 + 1, i2) - substring between swap chars
{i2} - the second swap char
[i2 + 1, s.length) - substring after the second swap char
At last we should swap {i1} & {i2} chars:
return s.substring(0, i1) + s.charAt(i2) + s.substring(i1 + 1, i2) + s.charAt(i1) + s.substring(i2 + 1, s.length);
try this :
public static String jumble(String s) {
int length = s.length();
StringBuilder sb=new StringBuilder(s);
int pos1 = getRandom(length);
int pos2 = getRandom(length);
while(pos1==pos2)
pos1=getRandom(length);
sb.setCharAt(pos1, s.charAt(pos2));
sb.setCharAt(pos2, s.charAt(pos1));
return new String(sb);
}
private static int getRandom(int length) {
Random r = new Random();
int rand=r.nextInt(length);
if(rand==0||rand==length)
return getRandom(length);
else
return rand;
}

some weird stff im running into on java

So im working on java codingbat and this is the question:
Given a string, look for a mirror image (backwards) string at both the beginning and end of the given string.
In other words, zero or more characters at the very begining of the given string, and at the very end of the string in reverse order (possibly overlapping).
For example:
the string "abXYZba" has the mirror end "ab". mirrorEnds("abXYZba") → "ab" mirrorEnds("abca") → "a" mirrorEnds("aba") → "aba" .
My code passed all the test except for the other test, which is not specified. I dont know what's wrong with it.
public String mirrorEnds(String string) {
String input = string, mirror = "";
int length = string.length();
for (int n = 0; n < (length+1) / 2; n++) {
if (input.charAt(n) != input.charAt(length - n - 1)) {
break;
}else if(length%2 == 1 && n == (length - 1)/2){
// System.out.println("length/2 = " );
return input;
}
else {
mirror += input.charAt(n);
}
}
return mirror;
}
You were correct in not needing to go though the entire word, but your logic is more complex than it needs to be, making it harder to find and fix the problem. The root cause of the test failure is in the last return statement. It must return string if the loop completes without breaking. You can fix your code by changing break; to return mirror; and changing the last return mirror; to return input;
The test that is failing is one like this:
mirrorEnds("abba") -> "abba"
A much simpler version of your code can be created like this:
public String mirrorEnds(String string) {
int len = string.length();
for (int i=0; i < len/2; ++i)
if (string.charAt(i) != string.charAt(len - 1 - i))
return string.substring(0, i);
return string;
}
mirrorEnds("abba")?
Anyways, I'm sure you could come up with a better question name than "some weird stuff"...
Since you are dividing n by 2 in your loop termination condition, it will end when halfway through the word. This is enough to tell the word is a palindrome, but not enough to build your output correctly. You have a condition handling palindrome with odd numbers of letter, but not even numbers of letters. I believe the failing test will be of the form "abba", where I believe what you have will return "ab", instead of "abba".
If you change you loop to:
for (int n = 0; n < length; n++) {
I believe it should be doing what you want. This also makes the short circuit case unnecessary, so:
for (int n = 0; n < length; n++) {
if (input.charAt(n) != input.charAt(length - n - 1)) {
break;
}
else {
mirror += input.charAt(n);
}
}
The first test I tried was with the string "abba" which fails. It returns ab, and not abba. As femtoRgon mentioned, you're not going through the entire word, which may some times be necessary. femtoRgon's solution works, as well as taking a slightly different approach to iterating through the word as follows:
public String mirrorEnds(String string) {
boolean matches = true;
StringBuilder mirrorEnd = new StringBuilder();
int index = 0;
while (matches && index < string.length()) {
if (string.charAt(index) == string.charAt(string.length() - index - 1))
mirrorEnd.append(string.charAt(index));
else
matches = false;
index++;
}
return mirrorEnd.toString();
}
public String mirrorEnds(String string) {
String comp="";
for(int i=0; i<string.length(); i++){
if(string.charAt(i)==string.charAt(string.length()-(i+1)))
comp= comp+ string.charAt(i);
else break;
}
return comp;
}

What is the most efficient algorithm for reversing a String in Java?

What is the most efficient way to reverse a string in Java? Should I use some sort of xor operator? The easy way would be to put all the chars in a stack and put them back into a string again but I doubt that's a very efficient way to do it.
And please do not tell me to use some built in function in Java. I am interested in learning how to do it not to use an efficient function but not knowing why it's efficient or how it's built up.
You say you want to know the most efficient way and you don't want to know some standard built-in way of doing this. Then I say to you: RTSL (read the source, luke):
Check out the source code for AbstractStringBuilder#reverse, which gets called by StringBuilder#reverse. I bet it does some stuff that you would not have considered for a robust reverse operation.
The following does not deal with UTF-16 surrogate pairs.
public static String reverse(String orig)
{
char[] s = orig.toCharArray();
int n = s.length;
int halfLength = n / 2;
for (int i=0; i<halfLength; i++)
{
char temp = s[i];
s[i] = s[n-1-i];
s[n-1-i] = temp;
}
return new String(s);
}
You said you don't want to do it the easy way, but for those Googling you should use StringBuilder.reverse:
String reversed = new StringBuilder(s).reverse().toString();
If you need to implement it yourself, then iterate over the characters in reverse order and append them to a StringBuilder. You have to be careful if there are (or can be) surrogate pairs, as these should not be reversed. The method shown above does this for you automatically, which is why you should use it if possible.
An old post & question, however still did not see answers pertaining to recursion. Recursive method reverse the given string s, without relaying on inbuilt jdk functions
public static String reverse(String s) {
if (s.length() <= 1) {
return s;
}
return reverse(s.substring(1)) + s.charAt(0);
}
`
The fastest way would be to use the reverse() method on the StringBuilder or StringBuffer classes :)
If you want to implement it yourself, you can get the character array, allocate a second character array and move the chars, in pseudo code this would be like:
String reverse(String str) {
char[] c = str.getCharArray
char[] r = new char[c.length];
int end = c.length - 1
for (int n = 0; n <= end; n++) {
r[n] = c[end - n];
}
return new String(r);
}
You could also run half the array length and swap the chars, the checks involved slow things down probably.
I'm not really sure by what you mean when you say you need an efficient algorithm.
The ways of reversing a string that I can think of are (they are all already mentioned in other answers):
Use a stack (your idea).
Create a new reversed String by adding characters one by one in reverse order from the original String to a blank String/StringBuilder/char[].
Exchange all characters in the first half of the String with its corresponding position in the last half (i.e. the ith character gets swapped with the (length-i-1)th character).
The thing is that all of them have the same runtime complexity: O(N). Thus it cannot really be argued that any one is any significantly better than the others for very large values of N (i.e. very large strings).
The third method does have one thing going for it, the other two require O(N) extra space (for the stack or the new String), while it can perform swaps in place. But Strings are immutable in Java so you need to perform swaps on a newly created StringBuilder/char[] anyway and thus end up needing O(N) extra space.
public class ReverseInPlace {
static char[] str=null;
public static void main(String s[]) {
if(s.length==0)
System.exit(-1);
str=s[0].toCharArray();
int begin=0;
int end=str.length-1;
System.out.print("Original string=");
for(int i=0; i<str.length; i++){
System.out.print(str[i]);
}
while(begin<end){
str[begin]= (char) (str[begin]^str[end]);
str[end]= (char) (str[begin]^str[end]);
str[begin]= (char) (str[end]^str[begin]);
begin++;
end--;
}
System.out.print("\n" + "Reversed string=");
for(int i=0; i<str.length; i++){
System.out.print(str[i]);
}
}
}
I think that if you REALLY don't have performance problem you should just go with the most readable solution which is:
StringUtils.reverse("Hello World");
private static String reverse(String str) {
int i = 0;
int j = str.length()-1;
char []c = str.toCharArray();
while(i <= j){
char t = str.charAt(i);
c[i] = str.charAt(j);
c[j]=t;
i++;
j--;
}
return new String(c);
}
If you do not want to use any built in function, you need to go back with the string to its component parts: an array of chars.
Now the question becomes what is the most efficient way to reverse an array? The answer to this question in practice also depends upon memory usage (for very large strings), but in theory efficiency in these cases is measured in array accesses.
The easiest way is to create a new array and fill it with the values you encounter while reverse iterating over the original array, and returning the new array. (Although with a temporary variable you could also do this without an additional array, as in Simon Nickersons answer).
In this way you access each element exactly once for an array with n elements. Thus giving an efficiency of O(n).
I would simply do it this way without a use of any single util function. Just the String class is sufficient.
public class MyStringUtil {
public static void main(String[] args) {
String reversedString = reverse("StringToReverse");
System.out.println("Reversed String : " + reversedString);
}
/**
* Reverses the given string and returns reversed string
*
* #param s Input String
* #returns reversed string
*/
private static String reverse(String s) {
char[] charArray = s.toCharArray(); // Returns the String's internal character array copy
int j = charArray.length - 1;
for (int i = 0; charArray.length > 0 && i < j; i++, j--) {
char ch = charArray[i];
charArray[i] = charArray[j];
charArray[j] = ch;
}
return charArray.toString();
}
}
Check it. Cheers!!
Using String:
String abc = "abcd";
int a= abc.length();
String reverse="";
for (int i=a-1;i>=0 ;i--)
{
reverse= reverse + abc.charAt(i);
}
System.out.println("Reverse of String abcd using invert array is :"+reverse);
Using StringBuilder:
String abc = "abcd";
int a= abc.length();
StringBuilder sb1 = new StringBuilder();
for (int i=a-1;i>=0 ;i--)
{
sb1= sb1.append(abc.charAt(i));
}
System.out.println("Reverse of String abcd using StringBuilder is :"+sb1);
One variant can be, swapping the elements.
int n = length - 1;
char []strArray = str.toCharArray();
for (int j = 0; j < n; j++) {
char temp = strArray[j];
char temp2 = strArray[n];
strArray[j] = temp2;
strArray[n] = temp;
n--;
}
public static void main(String[] args){
String string ="abcdefghijklmnopqrstuvwxyz";
StringBuilder sb = new StringBuilder(string);
sb.reverse();
System.out.println(sb);
}
public static String Reverse(String word){
String temp = "";
char[] arr = word.toCharArray();
for(int i = arr.length-1;i>=0;i--){
temp = temp+arr[i];
}
return temp;
}
char* rev(char* str)
{
int end= strlen(str)-1;
int start = 0;
while( start<end )
{
str[start] ^= str[end];
str[end] ^= str[start];
str[start]^= str[end];
++start;
--end;
}
return str;
}
=========================
Wondering how it works?
First operation:
x1 = x1 XOR x2
x1: 1 0 0
x2: 1 1 1
New x1: 0 1 1
Second operation
x2 = x2 XOR x1
x1: 0 1 1
x2: 1 1 1
New x2: 1 0 0
//Notice that X2 has become X1 now
Third operation:
x1 = x1 XOR x2
x1: 0 1 1
x2: 1 0 0
New x1: 1 1 1
//Notice that X1 became X2
public static string getReverse(string str)
{
char[] ch = str.ToCharArray();
string reverse = "";
for (int i = str.Length - 1; i > -1; i--)
{
reverse += ch[i];
}
return reverse;
}
//using in-built method reverse of Array
public static string getReverseUsingBulidingFunction(string str)
{
char[] s = str.ToCharArray();
Array.Reverse(s);
return new string(s);
}
public static void Main(string[] args)
{
string str = "123";
Console.WriteLine("The reverse string of '{0}' is: {1}",str,getReverse(str));
Console.WriteLine("The reverse string of '{0}' is: {1}", str, getReverseUsingBulidingFunction(str));
Console.ReadLine();
}
Using multiple threads to swap the elements:
final char[] strArray = str.toCharArray();
IntStream.range(0, str.length() / 2).parallel().forEach(e -> {
final char tmp = strArray[e];
strArray[e] = strArray[str.length() - e - 1];
strArray[str.length() - e - 1] = tmp;
});
return new String(strArray);
Of course this is the most efficient way:
String reversed = new StringBuilder(str).reverse().toString();
But if you don't like using that then I recommend this instead:
public String reverseString(String str)
{
String output = "";
int len = str.length();
for(int k = 1; k <= str.length(); k++, len--)
{
output += str.substring(len-1,len);
}
return output;
}
static String ReverseString(String input) {
var len = input.Length - 1;
int i = 0;
char[] revString = new char[len+1];
while (len >= 0) {
revString[i] = input[len];
len--;
i++;
}
return new string(revString);
}
why can't we stick with the simplest loop and revere with character read and keep adding to the char array, I have come across with a whiteboard interview, where interviewer set restrictions on not to use StringBuilder and inbuilt functions.
This is the optimal way to reverse a string with O(log n) complexity.
public char[] optimisedArrayReverse(char[] chars) {
char[] reversedChars = chars;
int length = chars.length;
int center = (length / 2) - 1;
int reversedIndex = chars.length - 1;
if (center < 0) {
return chars;
}
for (int index = 0; index <= center; index++) {
//Swap values
char temp = reversedChars[index];
reversedChars[index] = chars[reversedIndex];
reversedChars[reversedIndex] = temp;
reversedIndex --;
}
return reversedChars;
}
public static String reverseString(String str)
{
StringBuilder sb = new StringBuilder();
for (int i = str.length() - 1; i >= 0; i--)
{
sb.append(str[i]);
}
return sb.toString();
}

Categories

Resources