timings problems in hackerrank in "The Love-Letter Mystery" question - java

I am solving the "The Love-Letter Mystery" problem may be my logic is correct but it is showing the timings problems The Question is
Question here.My solution for same is given below. It contains two functions one is theLoveLetterMystery(String s) which is returning sum_minimum_Steps and other is conversionCount(String s,int i,int j) which is returning int characterCount variable.It sums all the minimum steps to return the value
import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.*;
public class Solution {
// Complete the theLoveLetterMystery function below.
static int theLoveLetterMystery(String s) {
int startCounter=0,endCounter=(s.length()-1),sum_minimum_Steps=0;
// s.charAt(startCounter)!=s.charAt(endCounter)
while(startCounter!=endCounter)
{
if(s.charAt(startCounter)!=s.charAt(endCounter))
{
//minimun steps function executes
sum_minimum_Steps+=conversionCount(s,startCounter,endCounter);
}else{
startCounter++;
endCounter--;
}
}
return sum_minimum_Steps;
}
static int conversionCount(String s,int i,int j) {
int charStartAscii=(int)s.charAt(i);
int charEndAscii=(int)s.charAt(j);
int characterCount=0;
while(charStartAscii!=charEndAscii)
{
charEndAscii--;
characterCount++;
}
return characterCount;
}
private static final Scanner scanner = new Scanner(System.in);
public static void main(String[] args) throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));
int q = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
for (int qItr = 0; qItr < q; qItr++) {
String s = scanner.nextLine();
int result = theLoveLetterMystery(s);
bufferedWriter.write(String.valueOf(result));
bufferedWriter.newLine();
}
bufferedWriter.close();
scanner.close();
}
}

Starting from the assumption we are working on an alphabet of 26 letters(range a - z) "The Love-Letter Mystery" question is about find the minimum number of operations consisting of decrement of value 1 of a letter (for example d -> c and excluding letter a) to convert a string to a palindrome string. This can be obtained adding the absolute int differences between chars standing in positions i and n - i - 1 where n is the length of the string and iterating over half of the string. Below the code:
public static int conversionCount(String s) {
char[] arr = s.toCharArray();
int length = s.length();
int count = 0;
for (int i = 0; i < length / 2; ++i) {
count += Math.abs((int) (arr[i] - arr[length - i - 1]));
}
return count;
}
Note: I tested it in hackerrank passing all tests.

function theLoveLetterMystery($s) {
$s = strtoupper($s);
$alpha = array('A','B','C','D','E','F','G','H','I','J','K', 'L','M','N','O','P','Q','R','S','T','U','V','W','X ','Y','Z');
$alpha_flip = array_flip($alpha);
// Write your code here
$i = 0;
$j = strlen($s)-1;
$sol = 0;
while($i<$j){
$sol += abs($alpha_flip[$s[$i]]-$alpha_flip[$s[$j]]);
++$i;
--$j;
}
return $sol;
}
echo theLoveLetterMystery('abbc')// return 2

Related

repeated string problem in hackerrank getting time limits problem

I am solving the repeated string hackerrank problem. but all the test cases are not running may be my logic is not correct.The problem is like that
my code is given below which consists of repeatedString and countingA functions having no of variables
i,a,and infinity String ...
import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.*;
public class Solution {
// Complete the repeatedString function below.
static long repeatedString(String s, long n) {
long i=1;
String infinityString="";
while(s.length()*i<=n)
{
infinityString+=s;
i++;
}
if(s.length()%infinityString.length()==0){
return countingA(infinityString);
}else{
infinityString+=s.substring(0,(s.length()%infinityString.length())-1);
return countingA(infinityString);
}
}
public static long countingA(String infinity)
{
long a=0;
for(int i=0;i<infinity.length();i++)
{
if(infinity.charAt(i)=='a')
{
a++;
}
}
return a;
}
private static final Scanner scanner = new Scanner(System.in);
public static void main(String[] args) throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));
String s = scanner.nextLine();
long n = scanner.nextLong();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
long result = repeatedString(s, n);
bufferedWriter.write(String.valueOf(result));
bufferedWriter.newLine();
bufferedWriter.close();
scanner.close();
}
}
Maybe try this,
static long countA(String s, long n) {
long totalCount = 0;
long aCount = 0;
long times = n / s.length();
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == 'a')
aCount++;
}
totalCount = times * aCount;
aCount = 0;
if(n%s.length() != 0) {
for(int i=0;i<n - (times * s.length());i++)
aCount++;
}
return totalCount + aCount;
}
The following is even in normal code too slow because of the string concatenation allocating a larger string.
String infinityString = "";
while (s.length()*i <= n) {
infinityString += s;
i++;
}
StringBuilder infinityStringB = new StringBuilder();
while (s.length()*i <= n) {
infinityStringB.append(s);
i++;
}
String infinityString = StringBuilder.toString();
Also one would like:
StringBuilder infinityStringB = new StringBuilder((int) n);
And there one sees: String cannot hold long n chars.
However you do not need the repeated string:
if (s.isEmpty()) {
return 0;
}
long repititions = n / s.length();
int remaining = (int)(n % s.length());
String remainder = s.substring(0, remaining);
return countAs(s) * repetitions + countAs(remainder);
Perhaps the case you are missing is condition when n%s!=0 then you need to count the extra a's. I have also solved this problem in c++ and used the following logic
static int numberOfAs(String s,long len){
int val=0;
for(int i=0;i<len;i++){
if(s.charAt(i)=='a'){
val++;
}
}
return val;
}
static long repeatedString(String s, long n) {
int size = s.length();
int noA = numberOfAs(s,s.length());// 1
double val = Math.floor(n/size);
if(s.length()%n==0){ // 2
return noA*(long)val;
}else{
long countedA = (long)val * noA; //3
long valsLeft = n-(long) (val*size); //4
long letfA = numberOfAs(s,valsLeft); //5
long ans = countedA + letfA; //6
return ans;
}
}
count number of a's in the provided string i.e s
Condition when string s is a multiple of total count n so you just need to multiply the number of a's in s with the result of n/s.
Is the total number of a's present in the n/s.
extra string after divisibility, we need to calculate the a's separately for this.
Calculated a's separately for extra string.
return their sum.
Hope this helps

Given a string , find the longest substring with atmost two distinct characters . if there are multiple matching strings return the first string

Java : find the substring from given string with two distinct characters and if there are multiple matching strings return the first string.
Whenever i am trying the below code getting output as ddddeddeee but i need output as aaaadddd. Please help
Used below Java code
import java.util.HashSet;
import java.util.Set;
import java.util.HashSet;
import java.util.Set;
class testlongdistinct {
public static final int CHAR_RANGE = 128;
public static String longestSubstr(String str, int k) {
int end = 0, begin = 0;
Set<Character> window = new HashSet<>();
int[] freq = new int[CHAR_RANGE];
for (int low = 0, high = 0; high < str.length(); high++) {
window.add(str.charAt(high));
freq[str.charAt(high)]++;
while (window.size() > k) {
if (--freq[str.charAt(low)] == 0) {
window.remove(str.charAt(low));
}
low++; // reduce window size
}
if (end - begin < high - low) {
end = high;
begin = low;
}
}
return str.substring(begin, end + 1);
}
// main function
public static void main(String[] args) {
String str = "aaabbbccaaaaddddeddeee";
int k = 2;
System.out.print(longestSubstr(str, k));
}
}

love letter passes for base test cases

Loveletter code question: James found a love letter his friend Harry has written for his girlfriend. James is a prankster, so he decides to meddle with the letter. He changes all the words in the letter into palindromes.
To do this, he follows 2 rules:
(a) He can reduce the value of a letter, e.g. he can change 'd' to 'c', but he cannot change 'c' to 'd'.
(b) In order to form a palindrome, if he has to repeatedly reduce the value of a letter, he can do it until the letter becomes 'a'. Once a letter has been changed to 'a', it can no longer be changed.
Each reduction in the value of any letter is counted as a single operation. Find the minimum number of operations required to convert a given string into a palindrome.
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
static int getAscii(char letter)
{
return (int)letter;
}
static boolean checkPalindrome(String str, int strLen)
{
String revStr ="";
for(int i=strLen;i >= 0;i--)
{
revStr = revStr + str.charAt(i);
}
if(str.equals(revStr))
{
return true;
}
return false;
}
static void reduceAscii(String str)
{
StringBuilder sb = new StringBuilder(str);
str = str.toString();
int strLen = str.length()-1;
int numOfOperations=0;
char letter;
for(int j=strLen; j >= 0; j--)
{
letter = str.charAt(j);
while(getAscii(letter) > 97 && getAscii(letter) <= 122)
{
if(checkPalindrome(str, strLen))
{
break;
}
else
{
int asciiValofLetter = (char)getAscii(letter);
char charToreplace = (char)(asciiValofLetter-1);
sb.setCharAt(j, charToreplace);
str = sb.toString();
letter = charToreplace;
numOfOperations++;
}
}
}
System.out.println(numOfOperations);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int numOfTestCases;
String str;
numOfTestCases = sc.nextInt();
for(int i=0; i < numOfTestCases; i++)
{
str = sc.next();
Solution.reduceAscii(str);
}
}
}
My code passes for abc, abcd, abcba but fails for lot of test cases. Here are some:
pue
heubsbn
feazhaxpux
hmhcy
tmp
Your solution looks overly complicated. You're asked to find the number of operations required, not the actual result.
Java's not my thing, so here's some pseudocode:
Number of letters to change = int(length of string/2) (for a seven letter string we change three letters)
Total operations = 0
for n=0 to number of letters to change
take nth letter and (string length-n)th letter
(number of operations on each letter is difference of ASCII values so...)
subtract ASCII value of first letter from ASCII value of second
add absolute value of this to your total
next letter
print total.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.InputMismatchException;
public class ConvertToPal {
public ConvertToPal() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Please enter a string to be palindromized! ");
String str = br.readLine();
char[] strArr = str.toCharArray();
int size = strArr.length;
int numOfOperations = 0;
for (int i = 0; i < (size/2) ; i++){
int dif = (getAscii(strArr[i])-getAscii(strArr[size-1-i]));
if (dif > 0){
strArr[i] = strArr[size-1-i];
numOfOperations += Math.abs(dif);
}
if(dif < 0){
strArr[size-1-i] = strArr[i];
numOfOperations += Math.abs(dif);
}
}
System.out.println(new String(strArr));
System.out.println("num of ops: "+ numOfOperations);
}
static int getAscii(char letter){
return (int)letter;
}
}
Here is a method in Java to achieve this
public int palindromeCount(String s) {
int count = 0;
int i = 0, j = s.length() - 1;
while (i < j) {
int front = (int) s.charAt(i);
int back = (int) s.charAt(j);
count += (Math.abs(front - back));
i++;
j--;
}
return count;
}

Java cutting string pairs

So here I have a string from 3200 characters I have to find the pair with most space between them I already have the code to find the pair, but then I have to remove the first char of the pair and move the second at the end of the string and do this things till it's not possible to so. Here is what I've done so far
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class StringPairs {
public static void main(String[] args) {
String inputString = readInputString();
printIdenticalSymbols(inputString);
}
private static String readInputString() {
Scanner in = new Scanner(System.in);
String inputString = in.nextLine();
in.close();
return inputString;
}
private static void printIdenticalSymbols(String inputString) {
Map<Character, Integer> symbolsMap = new HashMap<Character, Integer>();
char longestChar = ' ';
int longestDiff = -1;
int firstIndex = -1;
int lastIndex = -1;
int firstOccurenceOfLastIdentical = -1;
for (int i = 0; i < inputString.length(); i++) {
char currentCharacter = inputString.charAt(i);
if (!symbolsMap.containsKey(currentCharacter)) {
symbolsMap.put(currentCharacter, i);
continue;
}
int firstOccurenceIndex = symbolsMap.get(currentCharacter);
if (firstOccurenceIndex < firstOccurenceOfLastIdentical) {
symbolsMap.put(currentCharacter, i);
continue;
}
int currentIdenticalLength = i - firstOccurenceIndex;
if (currentIdenticalLength > longestDiff) {
longestChar = currentCharacter;
longestDiff = currentIdenticalLength;
firstIndex = firstOccurenceIndex;
lastIndex = i;
}
firstOccurenceOfLastIdentical = firstOccurenceIndex;
symbolsMap.put(currentCharacter, i);
}
System.out.println(longestChar + " - " + firstIndex + ":" + lastIndex);
}
}
example input:
brtba
output: b:space between them(it already does this) and rtab if the string is bigger do this thing till it's not possible to do so.
It suspiciously looks like homework to me.
Anyway, you should look into String manipulation functions, especially String.substring(begin,end). To make a loop, look into the while loop. Note that you don't handle yet the case where there is no pair.
This being said, I don't understand the function of the test:
(firstOccurenceIndex < firstOccurenceOfLastIdentical).

interviewstreet.com - String similarity

I'm trying to solve the string similarity question on interviewstreet.com. My code is working for 7/10 cases (and it is exceeding the time limit for the other 3).
Here's my code -
public class Solution {
public static void main(String[] args) {
Scanner user_input = new Scanner(System.in);
String v1 = user_input.next();
int number_cases = Integer.parseInt(v1);
String[] cases = new String[number_cases];
for(int i=0;i<number_cases;i++)
cases[i] = user_input.next();
for(int k=0;k<number_cases;k++){
int similarity = solve(cases[k]);
System.out.println(similarity);
}
}
static int solve(String sample){
int len=sample.length();
int sim=0;
for(int i=0;i<len;i++){
for(int j=i;j<len;j++){
if(sample.charAt(j-i)==sample.charAt(j))
sim++;
else
break;
}
}
return sim;
}
}
Here's the question -
For two strings A and B, we define the similarity of the strings to be the length of the longest prefix common to both strings. For example, the similarity of strings "abc" and "abd" is 2, while the similarity of strings "aaa" and "aaab" is 3.
Calculate the sum of similarities of a string S with each of it's suffixes.
Input:
The first line contains the number of test cases T. Each of the next T lines contains a string each.
Output:
Output T lines containing the answer for the corresponding test case.
Constraints:
1 <= T <= 10
The length of each string is at most 100000 and contains only lower case characters.
Sample Input:
2
ababaa
aa
Sample Output:
11
3
Explanation:
For the first case, the suffixes of the string are "ababaa", "babaa", "abaa", "baa", "aa" and "a". The similarities of each of these strings with the string "ababaa" are 6,0,3,0,1,1 respectively. Thus the answer is 6 + 0 + 3 + 0 + 1 + 1 = 11.
For the second case, the answer is 2 + 1 = 3.
How can I improve the running speed of the code. It becomes harder since the website does not provide a list of test cases it uses.
I used char[] instead of strings. It reduced the running time from 5.3 seconds to 4.7 seconds and for the test cases and it worked. Here's the code -
static int solve(String sample){
int len=sample.length();
char[] letters = sample.toCharArray();
int sim=0;
for(int i=0;i<len;i++){
for(int j=i;j<len;j++){
if(letters[j-i]==letters[j])
sim++;
else
break;
}
}
return sim;
}
used a different algorithm. run a loop for n times where n is equals to length the main string. for each loop generate all the suffix of the string starting for ith string and match it with the second string. when you find unmatched character break the loop add j's value to counter integer c.
import java.io.BufferedReader;
import java.io.InputStreamReader;
class Solution {
public static void main(String args[]) throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(in.readLine());
for (int i = 0; i < T; i++) {
String line = in.readLine();
System.out.println(count(line));
}
}
private static int count(String input) {
int c = 0, j;
char[] array = input.toCharArray();
int n = array.length;
for (int i = 0; i < n; i++) {
for (j = 0; j < n - i && i + j < n; j++)
if (array[i + j] != array[j])
break;
c+=j;
}
return c;
}
}
I spent some time to resolve this question, and here is an example of my code (it works for me, and pass thru all the test-cases):
static long stringSimilarity(String a) {
int len=a.length();
char[] letters = a.toCharArray();
char localChar = letters[0];
long sim=0;
int sameCharsRow = 0;
boolean isFirstTime = true;
for(int i=0;i<len;i++){
if (localChar == letters[i]) {
for(int j = i + sameCharsRow;j<len;j++){
if (isFirstTime && letters[j] == localChar) {
sameCharsRow++;
} else {
isFirstTime = false;
}
if(letters[j-i]==letters[j])
sim++;
else
break;
}
if (sameCharsRow > 0) {
sameCharsRow--;
sim += sameCharsRow;
}
isFirstTime = true;
}
}
return sim;
}
The point is that we need to speed up strings with the same content, and then we will have better performance with test cases 10 and 11.
Initialize sim with the length of the sample string and start the outer loop with 1 because we now in advance that the comparison of the sample string with itself will add its own length value to the result.
import java.util.Scanner;
public class StringSimilarity
{
public static void main(String args[])
{
Scanner user_input = new Scanner(System.in);
int count = Integer.parseInt(user_input.next());
char[] nextLine = user_input.next().toCharArray();
try
{
while(nextLine!= null )
{
int length = nextLine.length;
int suffixCount =length;
for(int i=1;i<length;i++)
{
int j =0;
int k=i;
for(;k<length && nextLine[k++] == nextLine[j++]; suffixCount++);
}
System.out.println(suffixCount);
if(--count < 0)
{
System.exit(0);
}
nextLine = user_input.next().toCharArray();
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Categories

Resources