Getting TLE in CodeChef and need for improvement of code - java

I am trying to solve a practice question of CodeChef . In this problem we are given N numbers Ai...An and we first have to sort(ascending order) the numbers and then add the alternate numbers starting from the last and show the output for each test cases , the test cases has 2 parts :
1>Constraints :
1 ≤ Ai ≤ 109
1 ≤ N ≤ 1000
2>Constraints:
1 ≤ Ai ≤ 109
1 ≤ N ≤ 105
You can see the full problem here.
The first part of my problem was successfully submitted but second part showed NZEC because I was using long to add those numbers(which was beyond that range). So I decided to use Strings to add up my numbers here is the method :
public static String myStringWayToAdd(String first , String second){
String temp = "";
if(first.length() < second.length()){
temp = first;
first = second;
second = temp;
}
temp = "";
int carry = 0;
for(int i=1;i<=first.length();++i){
if(i <= second.length()){
carry += Integer.parseInt(first.charAt(first.length()-i)+"") + Integer.parseInt(second.charAt(second.length()-i)+"");
}
else{
carry += Integer.parseInt(first.charAt(first.length()-i)+"");
}
temp += carry%10;
carry = carry/10;
}
if(carry != 0)
temp += carry;
StringBuilder myResult = new StringBuilder(temp);
return(myResult.reverse().toString());
}
But now it shows TLE(Time Limit Expire) , So then I thought to use BigInteger(which I am not pretty much Aware of but I saw some tutorials) :
BigInteger big = new BigInteger("0");
big = big.add(BigInteger.valueOf(mySort.get(j))); //for addition and mySort is my ArrayList
But this gave me NZEC I don't know whywell now I want to use double variable but there is a problem with that too, because with double large numbers will be in form of exponential value like :
1.243536E15 which will not be accepted by the machine, so is there any good way to solve this problem and not getting any Time Limit Expiry?.
Any help will really be appreciated. Thank you in Advance.
Edit 1 :
I changed baxck the variable to long and run and this time strangely I got TLE here is my code :
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
import java.math.BigInteger;
import java.lang.Number;
class CFEA{
public static void main(String[] s){
Scanner scan = new Scanner(System.in);
int testCases = scan.nextInt();
for(int i = 0 ; i<testCases;++i){
long sum = 0;
//BigInteger big = new BigInteger("0");
ArrayList<Integer> mySort = new ArrayList<Integer>();
int n = scan.nextInt();
for(int j = 1 ; j <= n ; ++j){
mySort.add(scan.nextInt());
}
Collections.sort(mySort);
for(int j = mySort.size()-1 ; j >= 0 ; j=j-2){
sum += mySort.get(j);
}
System.out.println(sum);
}
}
}
And here is Link to my submission.Is there Anything I can optimize in my code?

The sum of all number is at most 10^9 * 10^5 = 10^14. It is small enough to fit into long. There is no need to use BigInteger.
java.util.Scanner has performance issues. You can implement a custom scanner(using BufferedReader) to speed up your code.
Here is my implementation of a scanner:
import java.io.*;
import java.util.StringTokenizer;
public class FastScanner {
private BufferedReader reader;
private StringTokenizer tokenizer;
public FastScanner(InputStream inputStream) {
reader = new BufferedReader(new InputStreamReader(inputStream));
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
String line = reader.readLine();
if (line == null)
throw new IOException();
tokenizer = new StringTokenizer(line);
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public void close() {
try {
reader.close();
} catch (IOException e) {
//ignore
}
}
}

I did some changes in my Program and it was All Accepted a much relief after submitting for about 20 times , here is my new code :
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
class CFEA{
public static void main(String[] s){
Scanner scan = new Scanner(System.in);
byte testCases = Byte.parseByte(scan.nextLine()); //used byte for test cases instead of int
for(int i = 0 ; i<testCases;++i){
long sum = 0;
//BigInteger big = new BigInteger("0");
ArrayList<Integer> mySort = new ArrayList<Integer>();
int n = Integer.parseInt(scan.nextLine());
String input = scan.nextLine();
String[] my = input.split(" ");
for(String myString : my){
mySort.add(Integer.parseInt(myString));
}
Collections.sort(mySort);
for(int j = mySort.size()-1 ; j >= 0 ; j=j-2){
sum += mySort.get(j);
}
System.out.println(sum);
}
}
}
I think the main villain was that I was scanning for Integers N number of times as in this :
for(int j = 1 ; j <= n ; ++j){
mySort.add(scan.nextInt());
}
When N was something Like 100000 then this really slows it down.So i used 1 String for complete line and then Split it into Integers using split method as in :
String input = scan.nextLine(); //only 1 Scanner
String[] my = input.split(" ");
for(String myString : my){
mySort.add(Integer.parseInt(myString));
}
Although My code got submitted I still think there is Further scope for optimization , so please do answer if you have something better

Related

Non-empty subsets from HackerEarth exercises

Actually, I am doing an exercise from HackerEarth.
The exercise is pretty simple: I have to use a min-max algorithm but I have some struggles when I use the readLine method from the variable BufferReader.
I cannot figure out why but my min variable for an iteration keep the Integer.MAX_VALUE.
Code
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
class TestClass {
public static void main(String args[] ) throws Exception {
//BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
int N = Integer.parseInt(br.readLine());
while (T-- >= 0) {
String[] line = br.readLine().trim().split("\\s");
int min = Integer.MAX_VALUE;
for (int i = 0; i < line.length - 1; i++) {
min = Math.min(min, Integer.parseInt(line[i]));
}
System.out.println(min);
}
}
}
Output
1
2147483647
2
I've made many corrections to your code.
You are not reading every N of every test case, you only read it once. You have to put it inside the while loop.
Method trim is unnecessary because inputs from the problems are always in the right manner.
Use > not >= when comparing using array lengths or the number of test cases, because it will iterate once more even if the index is already beyond the array's capacity or 0.
public static void main(String args[] ) throws Exception {
//BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
while (T-- > 0) {
br.readLine(); // to read N
String[] line = br.readLine().split(" ");
int min = Integer.MAX_VALUE;
for (int i = 0; i < line.length; i++) {
min = Math.min(min, Integer.parseInt(line[i]));
}
System.out.println(min);
}
}

How to optimize the longest subsequence generation code in java?

import java.util.Scanner;
public class POD9 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String tito_has = sc.nextLine();
String tito_wants = sc.nextLine();
String remaining = "";
int strips = 0;
while(true){
String longest_common = getLongestCommonSubstring(tito_has,tito_wants);
strips++;
tito_has = tito_has.replaceAll(longest_common,"*");
remaining = remaining + longest_common;
if(remaining.length() == tito_wants.length()){
break;
}
}
System.out.println(strips-1);
}
public static String getLongestCommonSubstring(String str1, String str2){
int m = str1.length();
int n = str2.length();
int max = 0;
int[][] dp = new int[m][n];
int endIndex=-1;
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(str1.charAt(i) == str2.charAt(j) && str1.charAt(i) != Character.valueOf('*'))
{
if(i==0 || j==0){
dp[i][j]=1;
}else{
dp[i][j] = dp[i-1][j-1]+1;
}
if(max < dp[i][j])
{
max = dp[i][j];
endIndex=i;
}
}
}
}
return str1.substring(endIndex-max+1,endIndex+1);
}
}
This is my code used to retrieve the minimum number of paper cuts that are needed to form string 2 from string 1. This is the solution to the problem: Paper Cut Problem
I approached the problem by finding the longest substring between what Tito wants and what he has.
Thereafter, I replace the found sequences with '' as the input will only have letters. Also, in the cases, say, it has: "abbap" and tito wants:"bbaap", then this gives 3 cuts a|bb|a|p and not
2 (found bb->remove it (cut 1)->got (aap) -> found aa(cut2)-> remove it-> found b). So using "" helps in not making wrong substrings match.
I am pretty sure that my approach will solve most of the test cases. But I am getting the TIMELIMIT error here.
Please help me find an optimum way to achieve this?

How to identify the same number in two different outputs

I was assigned to do a program where the user will input two integers and the program will be able to display the same numbers in the two integers in descending form
for example
1st input: 1122334455
2nd input: 1234567
The output will be: 5 4 3 2 1
here is the code that I tried but didn't work since I can't seem to store values in the array or maybe my logic is wrong, any kind of help will be appreciated thanks!
import java.util.*;
public class Main {
public static void main (String[]args) {
Scanner input = new Scanner(System.in);
int a = input.nextInt();
String aa= a + "";
int b = input.nextInt();
String bb = b + "";
int[] cars = new int[aa.length()];
if ( aa.length() < bb.length() )
{
for ( int x = 0; x < aa.length(); x++ )
{
for (int y = 0 ; y < bb.length() ; y++ )
{
if ( aa.charAt(x) == bb.charAt(y) )
cars[x] = aa.charAt(x);
}
}
for ( int i = 0 ; i < cars.length; i++ )
{
if ( cars[i] != 0 )
System.out.println(cars[i]);
else {
}
}
}
}
}
Well you have too many for cicles and this is pretty simple, first convert any input to char array and then iterate over it checking if every value is contained in the other input, if it is then add it to a new list which will be your results and finally sort that list.
String aa="1122334455";
String bb="1234567";
List<Integer> result = new ArrayList();
char[] aa_arr = aa.toCharArray();
for(char aa_ : aa_arr){
if(bb.contains(aa_+"") && !result.contains(Integer.parseInt(aa_+""))){
result.add(Integer.parseInt(aa_+""));
}
}
Collections.sort(result, Collections.reverseOrder());
System.out.println(result);
Result:
[5, 4, 3, 2, 1]
I don't see anything obviously wrong. You have not included what error you are getting, or the unexpected output you are getting. Maybe if you optimize a little bit.
import java.util.*;
public class Main {
public static void main (String[]args){
Scanner input = new Scanner(System.in);
int a = input.nextInt();
String aa= a + "";
int b = input.nextInt();
String bb = b + "";
StringBuilder output = new StringBuilder("[");
String delimiter = "";
for (int x = 9 ; x >= 0 ; x++) {
String compare = Integer.toString(x);
if (aa.indexOf(compare) != -1 && bb.indexOf(compare) != -1) {
output .append(delimiter);
output .append(compare);
delimiter = ", ";
}
}
output.append("]");
System.out.println(output .toString());
}
}

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();
}
}
}

Which is the most efficient way of taking input in Java?

I am solving this question.
This is my code:
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int[] t = new int[n];
int count = 0;
for (int i = 0; i < n; i++) {
t[i] = sc.nextInt();
if (t[i] % k == 0) {
count++;
}
}
System.out.println(count);
}
}
But when I submit it, it get's timed out. Please help me optimize this to as much as is possible.
Example
Input:
7 3
1
51
966369
7
9
999996
11
Output:
4
They say :
You are expected to be able to process
at least 2.5MB of input data per
second at runtime.
Modified CODE
Thank you all...I modified my code and it worked...here it is....
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] input = br.readLine().split(" ");
int n = Integer.parseInt(input[0]);
int k = Integer.parseInt(input[1]);
int count = 0;
for (int i = 0; i < n; i++) {
if (Integer.parseInt(br.readLine()) % k == 0) {
count++;
}
}
System.out.println(count);
}
regards
shahensha
This could be slightly faster, based on limc's solution, BufferedReader should be faster still though.
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int count = 0;
while (true) {
try {
if (sc.nextInt() % k == 0) {
count++;
}
} catch (NoSuchElementException e) {
break;
}
}
System.out.println(count);
}
}
How about this?
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int count = 0;
for (int i = 0; i < n; i++) {
if (sc.nextInt() % k == 0) {
count++;
}
}
System.out.println(count);
You may consider reading big chunks of input and then get the numbers from there.
Other change is, you may use Integer.parseInt() instead of Scanner.nextInt() although I don't know the details of each one, somethings tells me Scanner version performs a bit more computation to know if the input is correct. Another alternative is to convert the number yourself ( although Integer.parseInt should be fast enough )
Create a sample input, and measure your code, change a bit here and there and see what the difference is.
Measure, measure!
BufferedReader is supposed to be faster than Scanner. You will need to parse everything yourself though and depending on your implementation it could be worse.

Categories

Resources