Reverse characters of each word in a sentence - string

Reverse characters of each word in a sentence. For eg:
My name is alex
changes to
yM eman si xela
I thought of the normal O(n) time algorithm of using two pointer to point to either end of the word and reverse it.
But in the below site
http://www.businessinsider.com/8-mind-bending-interview-questions-that-google-asks-its-engineers-2012-7?op=1
(Refer to ans of ques 2)
it is give that converting it to linked list and repetitively applying reversal of linked list for individual word is better. I found the following solution for the same program on Hackerearth:
http://learn.hackerearth.com/question/317/reverse-characters-of-each-word-in-a-sentence/
This solution takes O(n) time and O(n) space. The solution I suggested takes O(n) time O(1) space. How is the second one better?
Following is the code from Hackerearth:
public node stringReverseChars(node ll){
if(ll == null || ll.next == null)
return ll;
node tmp = ll;
node head = null, prev = null;
while(tmp != null){
while(tmp != null && tmp.data == ' '){
if(head == null)
head = tmp;
prev = tmp;
tmp = tmp.next;
}
if(tmp == null)
break;
node curr = tmp;
while(tmp.next != null && tmp.next.data != ' '){
tmp = tmp.next;
}
node np = tmp.next;
tmp.next = null;
node rev = reverseLL(curr);
if(prev != null)
prev.next = rev;
prev = curr;
curr.next = np;
if(head == null)
head = rev;
tmp = np;
}
return head;
}

I'm pretty skeptical that those other approaches are better. They have worse memory usage (Θ(n) versus O(1)) and worse locality of reference (they use linked lists rather than arrays). I don't see anything wrong with your solution; in fact, I think it's the standard way to do this.
Hope this helps!

Related

Optimal algorithm for this string decompression

I have been working on an exercise from google's dev tech guide. It is called Compression and Decompression you can check the following link to get the description of the problem Challenge Description.
Here is my code for the solution:
public static String decompressV2 (String string, int start, int times) {
String result = "";
for (int i = 0; i < times; i++) {
inner:
{
for (int j = start; j < string.length(); j++) {
if (isNumeric(string.substring(j, j + 1))) {
String num = string.substring(j, j + 1);
int times2 = Integer.parseInt(num);
String temp = decompressV2(string, j + 2, times2);
result = result + temp;
int next_j = find_next(string, j + 2);
j = next_j;
continue;
}
if (string.substring(j, j + 1).equals("]")) { // Si es un bracket cerrado
break inner;
}
result = result + string.substring(j,j+1);
}
}
}
return result;
}
public static int find_next(String string, int start) {
int count = 0;
for (int i = start; i < string.length(); i++) {
if (string.substring(i, i+1).equals("[")) {
count= count + 1;
}
if (string.substring(i, i +1).equals("]") && count> 0) {
count = count- 1;
continue;
}
if (string.substring(i, i +1).equals("]") && count== 0) {
return i;
}
}
return -111111;
}
I will explain a little bit about the inner workings of my approach. It is a basic solution involves use of simple recursion and loops.
So, let's start from the beggining with a simple decompression:
DevTech.decompressV2("2[3[a]b]", 0, 1);
As you can see, the 0 indicates that it has to iterate over the string at index 0, and the 1 indicates that the string has to be evaluated only once: 1[ 2[3[a]b] ]
The core here is that everytime you encounter a number you call the algorithm again(recursively) and continue where the string insides its brackets ends, that's the find_next function for.
When it finds a close brackets, the inner loop breaks, that's the way I choose to make the stop sign.
I think that would be the main idea behind the algorithm, if you read the code closely you'll get the full picture.
So here are some of my concerns about the way I've written the solution:
I could not find a more clean solution to tell the algorithm were to go next if it finds a number. So I kind of hardcoded it with the find_next function. Is there a way to do this more clean inside the decompress func ?
About performance, It wastes a lot of time by doing the same thing again, when you have a number bigger than 1 at the begging of a bracket.
I am relatively to programming so maybe this code also needs an improvement not in the idea, but in the ways It's written. So would be very grateful to get some suggestions.
This is the approach I figure out but I am sure there are a couple more, I could not think of anyone but It would be great if you could tell your ideas.
In the description it tells you some things that you should be awared of when developing the solutions. They are: handling non-repeated strings, handling repetitions inside, not doing the same job twice, not copying too much. Are these covered by my approach ?
And the last point It's about tets cases, I know that confidence is very important when developing solutions, and the best way to give confidence to an algorithm is test cases. I tried a few and they all worked as expected. But what techniques do you recommend for developing test cases. Are there any softwares?
So that would be all guys, I am new to the community so I am open to suggestions about the how to improve the quality of the question. Cheers!
Your solution involves a lot of string copying that really slows it down. Instead of returning strings that you concatenate, you should pass a StringBuilder into every call and append substrings onto that.
That means you can use your return value to indicate the position to continue scanning from.
You're also parsing repeated parts of the source string more than once.
My solution looks like this:
public static String decompress(String src)
{
StringBuilder dest = new StringBuilder();
_decomp2(dest, src, 0);
return dest.toString();
}
private static int _decomp2(StringBuilder dest, String src, int pos)
{
int num=0;
while(pos < src.length()) {
char c = src.charAt(pos++);
if (c == ']') {
break;
}
if (c>='0' && c<='9') {
num = num*10 + (c-'0');
} else if (c=='[') {
int startlen = dest.length();
pos = _decomp2(dest, src, pos);
if (num<1) {
// 0 repetitions -- delete it
dest.setLength(startlen);
} else {
// copy output num-1 times
int copyEnd = startlen + (num-1) * (dest.length()-startlen);
for (int i=startlen; i<copyEnd; ++i) {
dest.append(dest.charAt(i));
}
}
num=0;
} else {
// regular char
dest.append(c);
num=0;
}
}
return pos;
}
I would try to return a tuple that also contains the next index where decompression should continue from. Then we can have a recursion that concatenates the current part with the rest of the block in the current recursion depth.
Here's JavaScript code. It takes some thought to encapsulate the order of operations that reflects the rules.
function f(s, i=0){
if (i == s.length)
return ['', i];
// We might start with a multiplier
let m = '';
while (!isNaN(s[i]))
m = m + s[i++];
// If we have a multiplier, we'll
// also have a nested expression
if (s[i] == '['){
let result = '';
const [word, nextIdx] = f(s, i + 1);
for (let j=0; j<Number(m); j++)
result = result + word;
const [rest, end] = f(s, nextIdx);
return [result + rest, end]
}
// Otherwise, we may have a word,
let word = '';
while (isNaN(s[i]) && s[i] != ']' && i < s.length)
word = word + s[i++];
// followed by either the end of an expression
// or another multiplier
const [rest, end] = s[i] == ']' ? ['', i + 1] : f(s, i);
return [word + rest, end];
}
var strs = [
'2[3[a]b]',
'10[a]',
'3[abc]4[ab]c',
'2[2[a]g2[r]]'
];
for (const s of strs){
console.log(s);
console.log(JSON.stringify(f(s)));
console.log('');
}

Professor's bubble sort vs my bubble sort

SO I have 2 bubble sorts: 1 from lecture slides, another I wrote on my own:
def lecture_bubble(L):
while True:
swapped = False
for i in range(len(L) -1):
if L[i] > L[i+1]:
L[i+1] ,L[i] = L[i], L[i+1]
swapped = True
if not swapped:
# No swaps this pass ; therefore sorted
return L
def bubble_sort(array):
for i in range(len(array)-1):
swapped = False
for j in range(len(array)-1,i,-1):
if array[j] < array[j-1]:
array[j], array[j-1] = array[j-1], array[j]
swapped = True
if not swapped:
return array
return array
Comparing both of them:
Time taken for lecture_bubble is 4.485383749008179
Time taken for bubble_sort is 0.00061798095703125
[Finished in 4.6s]
Can someone explain why my bubble_sort is taking significantly lesser time to sort an array?
Also can my bubble sort be further improved?
Professors code executes till "if not swapped" is true. Your's will execute till either "the end of the for loop" or "if not swapped". Your code may not work for some cases.
Professor's algorithm stops sorting once it iterates through all elements without making any swap — which means the array is sorted. Have written the same algorithm in Javascript below
Comparing each with the neighbor and swapping if first is greater than the next
function bubbleSort(arr){
console.log("Input Array");
console.log(arr);
let i = 0
let temp;
let notSorted;
do {
notSorted = false;
for (let j = 0; j < arr.length-i; j++) {
if (arr[j] > arr[j+1]) {
notSorted = true;
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
console.log(arr[j],"swapped with",arr[j+1])
console.log(arr);
} else {
console.log("SKIP");
}
console.log(j, arr.length-i);
}
i++;
} while (notSorted)
console.log("Sorted using Bubble Sort");
return arr;
}
// console.log(bubbleSort([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])); // uncomment to run and see how efficient this algorithm is when array is sorted
console.log(bubbleSort([5,8,18,4,19,13,1,3,2,20,17,15,16,9,10,11,14,12,6,7]));

LongAdder Striped64 wasUncontended implementation detail

This is a question not about how LongAdder works, it's about an intriguing implementation detail that I can't figure out.
Here is the code from Striped64 (I've cut out some parts and left the relevant parts for the question):
final void longAccumulate(long x, LongBinaryOperator fn,
boolean wasUncontended) {
int h;
if ((h = getProbe()) == 0) {
ThreadLocalRandom.current(); // force initialization
h = getProbe();
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
for (;;) {
Cell[] as; Cell a; int n; long v;
if ((as = cells) != null && (n = as.length) > 0) {
if ((a = as[(n - 1) & h]) == null) {
//logic to insert the Cell in the array
}
// CAS already known to fail
else if (!wasUncontended) {
wasUncontended = true; // Continue after rehash
}
else if (a.cas(v = a.value, ((fn == null) ? v + x : fn.applyAsLong(v, x)))){
break;
}
A lot of things from code are clear to me, except for the :
// CAS already known to fail
else if (!wasUncontended) {
wasUncontended = true; // Continue after rehash
}
Where does this certainty that the following CAS will fail?
This is really confusing for me at least, because this check only makes sense for a single case : when some Thread enters the longAccumulate method for the n-th time (n > 1) and the busy spin is at it's first cycle.
It's like this code is saying : if you (some Thread) have been here before and you have some contention on a particular Cell slot, don't try to CAS your value to the already existing one, but instead rehash the probe.
I honestly hope I will make some sense for someone.
It's not that it will fail, it's more that it has failed. The call to this method is done by the LongAdder add method.
public void add(long x) {
Cell[] as; long b, v; int m; Cell a;
if ((as = cells) != null || !casBase(b = base, b + x)) {
boolean uncontended = true;
if (as == null || (m = as.length - 1) < 0 ||
(a = as[getProbe() & m]) == null ||
!(uncontended = a.cas(v = a.value, v + x)))
longAccumulate(x, null, uncontended);
}
}
The first set of conditionals is related to existence of the long Cells. If the necessary cell doesn't exist, then it will try to accumulate uncontended (as there was no attempt to add) by atomically adding the necessary cell and then adding.
If the cell does exist, try to add (v + x). If the add failed then there was some form of contention, in that case try to do the accumulating optimistically/atomically (spin until successful)
So why does it have
wasUncontended = true; // Continue after rehash
My best guess is that with heavy contention, it will try to give the running thread time to catch up and will force a retry of the existing cells.

DP states in SPOJ SERVICES

I am having a problem in the question SERVICES on SPOJ. I tried to solve it and came up with the following DP states [posofA][posofB][posofC][NextToMove]. But looking at the constraints, I think It will Give MLE. After trying for a day, I googled it and found blogs regarding a symmetry in the question. Despite my best efforts, I am unable to understand it. Can someone Please help and spare his time to help me. Thanks.
Observe that you can drop posOfC and always denote posOfC by the last requested position. When you are processing a request , you can easily get the previous position. Now you have all the positions of the 3 partners. Send one of them to the new requested position checking that all of them will be in different location.
int f(int pos,int a,int b)
{
if(pos == req.sz)
return 0;
// last position
int c = req[pos-1];
// current position we are sending one of them
int to = req[pos];
if( dp[pos][a][b] != -1)
return dp[pos][a][b];
int ans = inf;
// a goes to current request position
if(b != c && b != to && c != to)
ans = min(ans,f(pos+1,b,c) + cost[a][to]);
// b goes to current request position
if(a != c && a != to && c != to)
ans = min(ans,f(pos+1,a,c) + cost[b][to]);
// c goes to current request position
if(a != b && a != to && b != to)
ans = min(ans , f(pos+1,a,b) + cost[c][to]);
return dp[pos][a][b] = ans;
}
First 3 elements of req will be 1,2,3 . Get the answer by calling f(3,1,2).

Check if a string is rotation of another WITHOUT concatenating

There are 2 strings , how can we check if one is a rotated version of another ?
For Example : hello --- lohel
One simple solution is by concatenating first string with itself and checking if the other one is a substring of the concatenated version.
Is there any other solution to it ?
I was wondering if we could use circular linked list maybe ? But I am not able to arrive at the solution.
One simple solution is by concatenating them and checking if the other one is a substring of the concatenated version.
I assume you mean concatenate the first string with itself, then check if the other one is a substring of that concatenation.
That will work, and in fact can be done without any concatenation at all. Just use any string searching algorithm to search for the second string in the first, and when you reach the end, loop back to the beginning.
For instance, using Boyer-Moore the overall algorithm would be O(n).
There's no need to concatenate at all.
First, check the lengths. If they're different then return false.
Second, use an index that increments from the first character to the last of the source. Check if the destination starts with all the letters from the index to the end, and ends with all the letters before the index. If at any time this is true, return true.
Otherwise, return false.
EDIT:
An implementation in Python:
def isrot(src, dest):
# Make sure they have the same size
if len(src) != len(dest):
return False
# Rotate through the letters in src
for ix in range(len(src)):
# Compare the end of src with the beginning of dest
# and the beginning of src with the end of dest
if dest.startswith(src[ix:]) and dest.endswith(src[:ix]):
return True
return False
print isrot('hello', 'lohel')
print isrot('hello', 'lohell')
print isrot('hello', 'hello')
print isrot('hello', 'lohe')
You could compute the lexicographically minimal string rotation of each string and then test if they were equal.
Computing the minimal rotation is O(n).
This would be good if you had lots of strings to test as the minimal rotation could be applied as a preprocessing step and then you could use a standard hash table to store the rotated strings.
Trivial O(min(n,m)^2) algorithm: (n - length of S1, m - length of S2)
isRotated(S1 , S2):
if (S1.length != S2.length)
return false
for i : 0 to n-1
res = true
index = i
for j : 0 to n-1
if S1[j] != S2[index]
res = false
break
index = (index+1)%n
if res == true
return true
return false
EDIT:
Explanation -
Two strings S1 and S2 of lengths m and n respectively are cyclic identical if and only if m == n and exist index 0 <= j <= n-1 such S1 = S[j]S[j+1]...S[n-1]S[0]...S[j-1].
So in the above algorithm we check if the length is equal and if exist such an index.
A very straightforward solution is to rotate one of the words n times, where n is the length of the word. For each of those rotations, check to see if the result is the same as the other word.
You can do it in O(n) time and O(1) space:
def is_rot(u, v):
n, i, j = len(u), 0, 0
if n != len(v):
return False
while i < n and j < n:
k = 1
while k <= n and u[(i + k) % n] == v[(j + k) % n]:
k += 1
if k > n:
return True
if u[(i + k) % n] > v[(j + k) % n]:
i += k
else:
j += k
return False
See my answer here for more details.
Simple solution in Java. No need of iteration or concatenation.
private static boolean isSubString(String first, String second){
int firstIndex = second.indexOf(first.charAt(0));
if(first.length() == second.length() && firstIndex > -1){
if(first.equalsIgnoreCase(second))
return true;
int finalPos = second.length() - firstIndex ;
return second.charAt(0) == first.charAt(finalPos)
&& first.substring(finalPos).equals(second.subSequence(0, firstIndex));
}
return false;
}
Test case:
String first = "bottle";
String second = "tlebot";
Logic:
Take the first string's first character, find the index in the second string. Subtract the length of the second with the index found, check if first character of the second at 0 is same as character at the difference of length of the second and index found and substrings between those 2 characters are the same.
Another python implementation (without concatenation) although not efficient but it's O(n), looking forward for comments if any.
Assume that there are two strings s1 and s2.
Obviously, if s1 and s2 are rotations, there exists two sub strings of s2 in s1, the sum of them will total to the length of the string.
The question is to find that partition for which I increment an index in s2 whenever a char of s2 matches with that of s1.
def is_rotation(s1, s2):
if len(s1) != len(s2):
return False
n = len(s1)
if n == 0: return True
j = 0
for i in range(n):
if s2[j] == s1[i]:
j += 1
return (j > 0 and s1[:n - j] == s2[j:] and s1[n - j:] == s2[:j])
The second and condition is just to ensure that the counter incremented for s2 are a sub string match.
input1= "hello" input2="llohe" input3="lohel"(input3 is special case)
if length's of input 1 & input2 are not same return 0.Let i and j be two indexes pointing to input1 and input2 respectively and initialize count to input1.length. Have a flag called isRotated which is set to false
while(count != 0){
When the character's of input1 matches input2
increment i & j
decrement count
If the character's donot match
if isRotated = true(it means even after rotation there's mismatch) so break;
else Reset j to 0 as there's a mismatch. Eg:
Please find the code below and let me know if it fails for some other combination I may not have considered.
public boolean isRotation(String input1, String input2) {
boolean isRotated = false;
int i = 0, j = 0, count = input1.length();
if (input1.length() != input2.length())
return false;
while (count != 0) {
if (i == input1.length() && !isRotated) {
isRotated = true;
i = 0;
}
if (input1.charAt(i) == input2.charAt(j)) {
i++;
j++;
count--;
}
else {
if (isRotated) {
break;
}
if (i == input1.length() - 1 && !isRotated) {
isRotated = true;
}
if (i < input1.length()) {
j = 0;
count = input1.length();
}
/* To handle the duplicates. This is the special case.
* This occurs when input1 contains two duplicate elements placed side-by-side as "ll" in "hello" while
* they may not be side-by-side in input2 such as "lohel" but are still valid rotations.
Eg: "hello" "lohel"
*/
if (input1.charAt(i) == input2.charAt(j)) {
i--;
}
i++;
}
}
if (count == 0)
return true;
return false;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(new StringRotation().isRotation("harry potter",
"terharry pot"));
System.out.println(new StringRotation().isRotation("hello", "llohe"));
System.out.println(new StringRotation().isRotation("hello", "lohell"));
System.out.println(new StringRotation().isRotation("hello", "hello"));
System.out.println(new StringRotation().isRotation("hello", "lohe"));
}
Solving the problem in O(n)
void isSubstring(string& s1, string& s2)
{
if(s1.length() != s2.length())
cout<<"Not rotation string"<<endl;
else
{
int firstI=0, secondI=0;
int len = s1.length();
while( firstI < len )
{
if(s1[firstI%len] == s2[0] && s1[(firstI+1) %len] == s2[1])
break;
firstI = (firstI+1)%len;
}
int len2 = s2.length();
int i=0;
bool isSubString = true;
while(i < len2)
{
if(s1[firstI%len] != s2[i])
{
isSubString = false;
break;
}
i++;
}
if(isSubString)
cout<<"Is Rotation String"<<endl;
else
cout<<"Is not a rotation string"<<endl;
}
}
String source = "avaraavar";
String dest = "ravaraava";
System.out.println();
if(source.length()!=dest.length())
try {
throw (new IOException());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int i = 0;
int j = 0;
int totalcount=0;
while(true)
{
i=i%source.length();
if(source.charAt(i)==dest.charAt(j))
{
System.out.println("i="+i+" , j = "+j);
System.out.println(source.charAt(i)+"=="+dest.charAt(j));
i++;
j++;
totalcount++;
}
else
{
System.out.println("i="+i+" , j = "+j);
System.out.println(source.charAt(i)+"!="+dest.charAt(j));
i++;
totalcount++;
j=0;
}
if(j==source.length())
{
System.out.println("Yes its a rotation");
break;
}
if(totalcount >(2*source.length())-1)
{
System.out.println("No its a rotation");
break;
}
}

Resources