Just to practice and improve my programming skills I decided to solve the questions on InterviewStreet. I decided to start off using simple InsertionSort (I expected it to be simple).
https://www.interviewstreet.com/challenges/dashboard/#problem/4e90477dbd22b
I am able to get correct answers. However the runtime is a problem. The max allowed runtime for the test cases is 5s. However I am going slightly overboard.
I used a few tricks (like removing something out of code. Storing the result of str.lenght() etc). However I am still slightly overboard.
The current runtimes for the ten test cases are:
1 Passed Success 0.160537
2 Passed Success 0.182606
3 Passed Success 0.172744
4 Passed Success 0.186676
5 Failed Time limit exceeded. 5.19279
6 Failed Time limit exceeded. 5.16129
7 Passed Success 2.91226
8 Failed Time limit exceeded. 5.14609
9 Failed Time limit exceeded. 5.14648
10 Failed Time limit exceeded. 5.16734
I am not aware what the test cases are.
Kindly help me improve the runtime.
Thank you.
import java.util.Scanner;
import java.io.*;
//import java.io.BufferedWriter;
//import java.io.FileInputStream;
//import java.io.FileOutputStream;
public class Solution {
public static int[] A=new int[100001];
public static int swap=0;
public static void InsertionSort(int n){
for (int i=1; i<=n; i++){
for (int var=i; var>0; var--){
if (A[var]<A[var-1]){
int temp=A[var-1];
A[var-1]=A[var];
A[var]=temp;
swap++;
}
else {
break;
}
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
int number_of_cases =Integer.parseInt(str);
int counter;
int [] spacearray = new int[100000];
for (int j=0; j<number_of_cases; j++){
swap=0;
str = br.readLine();
int arraylength = Integer.parseInt(str);
str = br.readLine();
counter=0;
int strlen=str.length();
for (int i=0; i<strlen-1; i++){
if (str.charAt(i) == ' '){
spacearray[counter]=i;
counter++;
}
}
spacearray[counter]=strlen;
A[0]=Integer.parseInt(str.substring(0, spacearray[0]));
for (int i=1; i<=arraylength-1; i++){
A[i] = Integer.parseInt(str.substring(spacearray[i-1]+1,spacearray[i]));
}
InsertionSort(arraylength-1);
System.out.println(swap);
}
}
}
Use binary indexed trees to solve this problem
The bottleneck here is the insertion sort algorithm. It's time complexity is O(n^2) and with n up to 10^5, one can easily exceed 5 seconds on the interviewstreet judge machine. Also when a TLE signal is thrown, your program stops executing. So the slight overhead to 5 isn't really an indicator of the actual time it takes to run. It is introduced by the delay between detecting TLE and stopping the execution.
For the sake of history, this question appeared originally as a part of codesprint-1. Using insertion sort isn't the way to proceed here, otherwise the question would have been a complete give away.
Hint
Use the fact that all values will be within [1,10^6]. What you are really doing here is finding the number of inversions in the array A, i.e. find all pairs of i < j s.t. A[i] > A[j]. Think of a data structure that allows you to find the number of swaps needed for each insert operation in logarithmic time complexity (like Binary Indexed Trees). Of course, there are other approaches.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
LeetCode 485
Given a binary array nums, return the maximum number of consecutive 1's in the array.
Example 1:
Input: nums = [1,1,0,1,1,1]
Output: 3
Explanation: The first two digits or the last three digits are consecutive 1s. The maximum number of consecutive 1s is 3.
---------Solution:-------
public int findMaxConsecutiveOnes(int[] nums) {
int maxConsSize = Integer.MIN_VALUE;
int i = -1, j=-1, k=0;
while(k<nums.length){
while(k<nums.length && nums[k] == 1){
k++;
i++;
}
if(nums[k] == 0){
maxConsSize = Math.max(maxConsSize,i-j);
j = i;
}
}
maxConsSize = Math.max(maxConsSize,i-j);
return maxConsSize;
}
Warning: This is not direct answer (for this "do my homework" question)
You should use (or learn to use) debugger in your IDE (trust me, IDE, e.g. Eclipse will help you a lot in your beginnings).
The easiest (I'm not saying smartest) way, how to know what the program is doing (when you need to know, like in this case) is to add some print statements, e.g. add System.out.println("k=" + k) into your program (in a while loop).
You might want to watch this youtube video.
You have an infinity loop. Try run this:
public class Test {
public static void main(String[] args) {
int maxConsSize = Integer.MIN_VALUE;
int[] nums = {1,1,0,1,1,1};
int i = -1, j=-1, k=0;
System.out.println(nums.length);
while(k<nums.length){
while(k<nums.length && nums[k] == 1){
k++;
i++;
System.out.println("k = " + k);
}
if(nums[k] == 0){
maxConsSize = Math.max(maxConsSize,i-j);
j = i;
}
}
maxConsSize = Math.max(maxConsSize,i-j);
System.out.println(maxConsSize);
}
}
Output:
6
k = 1
k = 2
After reading the first 0 you are in infinite loop. You have made this task very complicated :)
It's probably not the best solution, but it should be faster
public int findMaxConsecutiveOnes(int[] nums) {
int maxCons = 0;
int currentCons = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 0) {
if (currentCons > maxCons) {
maxCons = currentCons;
}
currentCons = 0;
} else {
currentCons++;
}
}
if (currentCons > maxCons) {
maxCons = currentCons;
}
return maxCons;
}
}
There are two basic forms of loops:
for-each, for-i or sometimes called ranged for
Use that for a countable number of iterations.
For example having an array or collection to loop through.
while and do-while (like until-loops in other programming languages)
Use that for something that has a dynamic exit-condition. Bears the risk for infinite-loops!
Your issue: infinite loop
You used the second form of a while for a typical use-case of the first. When iterating over an array, you would be better to use any kind of for loop.
The second bears always the risk of infinite-loops, without having a proper exit-condition, or when the exit-condition is not fulfilled (logical bug). The first is risk-free in that regard.
Recommendation to solve
Would recommend to start with a for-i here:
// called for-i because the first iterator-variable is usually i
for(int i=0; i < nums.length, i++) {
// do something with num[i]
System.out.println(num[i]):
}
because:
it is safer, no risk of infinite-loop
the iterations can be recognized from the first line (better readability)
no counting, etc. inside the loop-body
Even simpler and idiomatic pattern is actually to use a for each:
for(int n : nums) {
// do something with n
System.out.println(n):
}
because:
it is safer, no risk of infinite-loop
the iterations can be recognized from the first line (better readability)
no index required, suitable for arrays or lists
no counting at all
See also:
Java For Loop, For-Each Loop, While, Do-While Loop (ULTIMATE GUIDE), an in-depth tutorial covering all about loops in Java, including concepts, terminology, examples, risks
On the Codechef August long challenge, AUG21C > CHFINVNT, this is the code that I wrote, but the submit doesn't work. It's showing RE(NZEC) error.
The output still works.... but it won't submit. Please help.
/* package codechef; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Codechef
{
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
Scanner scr = new Scanner(System.in);
try {
int T = scr.nextInt();
while(T-- > 0)
{
int N = scr.nextInt();
int p = scr.nextInt();
int K = scr.nextInt();
int[] A = new int[N];
for(int i=0; i<N; i++)
{
A[i%K]++;
}
int sum=0;
for(int i=0; i<p%K; i++)
{
sum+=A[i];
}
int add = (p - (p%K)) / K;
add++;
sum = sum + add;
System.out.println(sum);
}
}catch(Exception e){}
}
}
Obviously, you have a flaw in your code. NZEC means non-zero exit code. Your code probably triggered an uncaught exception. Although you have a broad catch statement, there are exceptions outside of your catch clause.
In the question statement, N can be as large as 10^9.
If that happens, int[] A = new int[N]; tries to allocate that memory. That is over the memory constraints. Probably that is causing the problem. Even if you could allocate that memory, you would hit the time limits: even counting to 10^9 shall fail on CodeChef.
Not directly related to the question, but I want to comment on your code from the perspective of software engineering and competitive coding best practices.
Having a broad catch block will hide any exceptions you may have. Even if you get an index-out-of-bounds exception, you shall not be able to see that in your trials. You may avoid catching broad exceptions.
Your code does not have a proper indentation. That makes reading & debugging cumbersome. Especially in competitive programming, speed is important. So, a proper indentation is critical in that regard. You may just use an IDE to format the code.
Your Java code does not follow the general conventions of Java. One of the rules is "local variables start with a lowercase". The local variables A and N violate that rule.
The code you submitted contains many empty lines. While submitting your code to StackOverflow, removing unnecessary lines shall ease the reading and increase the probability of getting a good answer.
I'm fairly new to coding and am struggling with an assignment for my class. The program takes a user input for the size of an Array and prompts the user to enter each value 1 at a time. The array size starts at 3 and if the array needs to be bigger when the array has filled a new array that's 2x size is created and all info is copied into it. I was able to figure out this part but I just can't see what I'm doing wrong in the downsizing part. After the info is copied I have to remove the trailing zeroes. I think I have the downsize method right but I don't know if I'm calling it right
import java.util.Scanner;
public class Lab6 {
public static void main(String args[]) {
int[] myarray = new int[3];
int count = 0;
int limit, limitcount = 1;
Scanner kbd = new Scanner(System.in);
System.out.print("How many values would you like to enter? ");
limit = kbd.nextInt();
while (limitcount <= limit) {
System.out.println("Enter an integer value ");
int input = kbd.nextInt();
limitcount++;
if (count < myarray.length) {
myarray[count] = input;
}
else {
myarray = upsize(myarray);
myarray[count] = input;
}
count++;
}
myarray = downsize(myarray, count)
printArray(myarray);
System.out.println("The amount of values in the arrays that we care about is: " + count);
}
static int[] upsize(int[] array) {
int[] bigger = new int[array.length * 2];
for (int i =0;i<array.length; i++) {
bigger[i] = array[i];
}
return bigger;
}
static void printArray( int[] array ) {
for ( int number : array ) {
System.out.print( number + " ");
}
System.out.println();
}
static int[] downsize(int[] array,int count) {
int[] smaller = new int[count];
for (int i =0; i<count; i++) {
smaller[i] = array[i];
}
return array;
}
}
Giving you a full response rather than a comment since you're new here and I don't want to discourage you with brevity which could be misunderstood.
Not sure what happened to your code when you pasted it in here, you've provided everything but the format is weird (the 'code' bit is missing out a few lines at the top and bottom). Might be one to double-check before posting. After posting, I see that someone else has already edited your code to fix this one.
You're missing a semi-colon. I'm not a fan of handing out answers, so I'll leave you to find it :) If you're running your code in an IDE, it should already be flagging that one up for you. If you're not, why on earth not??? IntelliJ is free, easy to get going with, and incredibly helpful. There are others out there as well which different folk prefer :) An IDE will help you spot all sorts of useful things quickly.
I have now run your code, and you do have a problem! It's in your final method, downsize(). Look very, very carefully at the return statement ;) Your questions suggests you aren't actually sure whether or not this method is right, which makes me wonder: have you actually run this code with different inputs to see what results you get? Please do that.
Style-wise: blank lines between methods would make the code easier to look at, by providing a visual gap between components. Please be consistent with putting your opening { on the same line as the method signature, and with having spaces between items, e.g. for (int i = 0; i < count; i++) rather than for (int i =0; i<count; i++). The compiler couldn't care less, but it is easier for humans to look at and just makes it look like you did care. Always a good thing!
I think it is awesome that you are separating some of the work into smaller methods. Seriously. For extra brownie points, think about how you could move that while() block into its own method, e.g. private int[] getUserData(int numberOfItems, Scanner scanner). Your code is great without this, but the more you learn to write tiny units, the more favours you will be doing your future self.
Has your class looked at unit testing yet? Trust me, if not, when you get to this you will realise just how important point 5 can be. Unit tests will also help a lot with issues such as the one in point 3 above.
Overall, it looks pretty good to me. Keep going!!!
Simple mistake in your downsize method. If you have an IDE like Eclipse, Intellij, etc. you would have seen it flagged right away.
return array; // should return smaller
I have a few suggestions since you mentioned being new to coding.
The "limitcount" variable can be removed and substituted with "count" at every instance. I'll leave it to you to figure that out.
Try using more descriptive and understandable variable names. Other people will read your code (like now) and appreciate it.
Try to use consistent spacing/indentation throughout your code.
Your upsize method can be simplified using a System.arraycopy() call which generally performs better and avoids the need for writing out a for loop. You can rewrite downsize in a similar manner.
static int[] upsize(int[] array) {
int[] bigger = new int[array.length * 2];
System.arraycopy(array, 0, bigger, 0, array.length);
return bigger;
}
Edit: All good points by sunrise above - especially that you've done well given your experience. You should set up an IDE when you have the time, they're simple to use and invaluable. When you do so you should learn to step through a debugger to explore the state of your program over time. In this case you would have noticed that the myarray variable was never reassigned after the downsize() call, quickly leading you to a solution (if you had missed the warning about an unused "smaller" array).
A few days ago, I participated in the USA coding olympiad for the first time, and got the same error on all my codes. I can't figure out why because it told me that I did incredibly well on the first test case, so I don't understand how the other 9 all timed out. Could someone please explain what is wrong with my code.
Problem
Error Message
import java.io.*;
public class milkmeasure {
private static int [] cows ={7,7,7};
public static void main(String[] args) throws IOException {
// initialize file I/O
BufferedReader br = new BufferedReader(new FileReader("measurement.in"));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("measurement.out")));
int N = Integer.parseInt(br.readLine());
String [] entries = new String [N];
for (int i=0;i<N;i++){
entries [i]= br.readLine();
}
int topCow = 1;
int finalN = 0;
for (int i=0; i<N; i++){
String lowEntry = entries[lownum(N,entries)];
String name = lowEntry.substring(2,lowEntry.substring(2).indexOf(" ")+2);
int effect = Integer.parseInt(lowEntry.substring(lowEntry.substring(2).indexOf(" ")+3));
if (name.equals("Bessie")){cows[1]+=effect;}
else if (name.equals("Elsie")){cows[2]+=effect;}
else if (name.equals("Mildred")){cows[0]+=effect;}
int newTop = findTop();
if (newTop!=topCow){finalN++;}
topCow = newTop;
entries[lownum(N,entries)]="101 ";
}
pw.println(finalN);
pw.close();
}
private static int lownum (int N, String [] entries){
int lowNum = 101;
int returnInt=0;
for (int i =0; i<N; i++){
int a = Integer.parseInt(entries[i].substring(0,entries[i].indexOf(" ")));
if (a<lowNum){
lowNum = a;
returnInt =i;
}
}
return returnInt;
}
private static int findTop (){
int maxval = 0;
int returnval =0;
for (int i =0; i<3; i++){
if (cows[i]>= maxval){
returnval += cows[i]*cows[i];
maxval=cows[i];
}
}
return returnval;
}
}
Algorithmic complexity issue
For each entry, your main() method invokes lownum() (twice). lownum() scans all the entries to identify and return the one with the lowest day number. Overall, then, the complexity of your program scales at least as o(N2) in the number of entries.
That lower bound could be reduced to o(N log N) by sorting the entries once and then simply processing them in order.
With a reasonable bound on the maximum day number of the entries, and the given assurance that there is at most one entry per day, it could be reduced further to o(N) by assigning entries to an array or List at positions corresponding to their day numbers, so that no actual sorting is required.
It turns out that this is the main driver of your asymptotic complexity, so improving this lower bound allows you to improve the upper bound, too, all the way to O(N).
General efficiency issues
Since the problem specifies that there will be at most one entry per day for 100 days, however, you are probably in a regime that is still strongly influenced by (in-)efficiencies that affect the cost coefficient. And you in fact have quite a few inefficiencies. Among them:
You parse each entry many times, scanning to split them into fields and converting some of those into integers. That's terribly wasteful. It would be far more efficient to parse each entry just once, and then store the parsed results. In fact, you can get the parsing at input for almost free by using a Scanner.
You invoke the lownum() method twice for each entry. The current implementation of this method is expensive, as discussed above, and nothing changes between the first and second invocation that would affect the result.
(minor) you perform full string comparisons on the cow names, even though it would be sufficient to look only at their first letters
(minor) you invoke separate methods to find the next entry and to compute the new top cow. Method invocation is comparatively expensive, so it is a bit inefficient to make large numbers of invocations of methods that do very little work. That's probably not a significant effect for your particular code, however.
Write a program to print out all possible values of int data type from the smallest to the largest, using Java.
Some notable solutions as of 8th of May 2009, 10:44 GMT:
1) Daniel Lew was the first to post correctly working code.
2) Kris has provided the simplest solution for the given problem.
3) Tom Hawtin - tackline, came up arguably with the most elegant solution.
4) mmyers pointed out that printing is likely to become a bottleneck and can be improved through buffering.
5) Jay's brute force approach is notable since, besides defying the core point of programming, the resulting source code takes about 128 GB and will blow compiler limits.
As a side note I believe that the answers do demonstrate that it could be a good interview question, as long as the emphasis is not on the ability to remember trivia about the data type overflow and its implications (that can be easily spotted during unit testing), or the way of obtaining MAX and MIN limits (can easily be looked up in the documentation) but rather on the analysis of various ways of dealing with the problem.
class Test {
public static void main(String[] args) {
for (int a = Integer.MIN_VALUE; a < Integer.MAX_VALUE; a++) {
System.out.println(a);
}
System.out.println(Integer.MAX_VALUE);
}
}
Am I hired?
Simplest form (minimum code):
for (long i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++) {
System.out.println(i);
}
No integer overflow, no extra checks (just a little more memory usage, but who doesn't have 32 spare bits lying around).
While I suppose
for (long i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++)
System.out.println(i);
has fewer characters, I can't really say that it is simpler. Shorter isn't necessarily simpler, it does have less code though.
I just have to add an answer...
public class PrintInts {
public static void main(String[] args) {
int i = Integer.MIN_VALUE;
do {
System.out.println(i);
++i;
} while (i != Integer.MIN_VALUE);
}
}
We don't want the body repeated (think of the maintenance!)
It doesn't loop forever.
It uses an appropriate type for the counter.
It doesn't require some wild third-party weirdo library.
Ah, and here I had just started writing
System.out.println(-2147483648);
System.out.println(-2147483647);
System.out.println(-2147483646);
Okay, just give me a few weeks to finish typing this up ...
The instructions didn't say I have to use a loop, and at least this method doesn't have any overflow problems.
Is there something tricky that I'm not catching? There probably is... (edit: yes, there is!)
class AllInts {
public static void main(String[] args) {
// wrong -- i <= Integer.MAX_VALUE will never be false, since
// incrementing Integer.MAX_VALUE overflows to Integer.MIN_VALUE.
for (int i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++) {
System.out.println(i);
}
}
}
Since the printing is the bottleneck, a buffer would improve the speed quite a lot (I know because I just tried it):
class AllInts {
public static void main(String[] args) {
// a rather large cache; I did no calculations to optimize the cache
// size, but adding the first group of numbers will make the buffer
// as large as it will ever need to be.
StringBuilder buffer = new StringBuilder(10000000);
int counter = 0;
// note that termination check is now <
// this means Integer.MAX_VALUE won't be printed in the loop
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
buffer.append(i).append('\n');
if (++counter > 5000000) {
System.out.print(buffer);
buffer.delete(0, buffer.length()-1);
counter = 0;
}
}
// take care of the last value (also means we don't have to check
// if the buffer is empty before printing it)
buffer.append(Integer.MAX_VALUE);
System.out.println(buffer);
}
}
Also, this version will actually terminate (thanks to Daniel Lew for pointing out that there was, in fact, something tricky that I wasn't catching).
The total run time for this version (run with -Xmx512m) was 1:53. That's over 600000 numbers/second; not bad at all! But I suspect that it would have been slower if I hadn't run it minimized.
When I first looked at this, my first question was 'how do you define smallest and largest'. For what I thought was the most obvious definition ('smallest' == 'closest to 0') the answer would be
for (int i = 0; i >= 0; i++) {
System.out.println(i);
System.out.println(-i-1);
}
But everyone else seems to read 'smallest' as 'minimum' and 'largest' as 'maximum'
Come on folks, it said using java. It didn't say use an int in the for loop. :-)
public class Silly {
public static void main(String[] args) {
for (long x = Integer.MIN_VALUE; x <= Integer.MAX_VALUE; x++) {
System.out.println(x);
}
}
}
Another way to loop through every value using an int type.
public static void main(String[] args) {
int i = Integer.MIN_VALUE;
do {
System.out.println(i);
} while (i++ < Integer.MAX_VALUE);
}
Given the overview of the best answers, I realized that we're seriously lacking in the brute-force department. Jay's answer is nice, but it won't actually work. In the name of Science, I present - Bozo Range:
import java.util.Random;
import java.util.HashSet;
class Test {
public static void main(String[] args) {
Random rand = new Random();
HashSet<Integer> found = new HashSet<Integer>();
long range = Math.abs(Integer.MAX_VALUE - (long) Integer.MIN_VALUE);
while (found.size() < range) {
int n = rand.nextInt();
if (!found.contains(n)) {
found.add(n);
System.out.println(n);
}
}
}
}
Note that you'll need to set aside at least 4 GB of RAM in order to run this program. (Possibly 8 GB, if you're on a 64-bit machine, which you'll probably require to actually run this program...). This analysis doesn't count the bloat that the Integer class adds to any given int, either, nor the size of the HashSet itself.
The maximum value for int is Integer.MAX_VALUE and the minimum is Integer.MIN_VALUE. Use a loop to print all of them.
Package fj is from here.
import static fj.pre.Show.intShow;
import static fj.pre.Show.unlineShow;
import static fj.data.Stream.range;
import static java.lang.Integer.MIN_VALUE;
import static java.lang.Integer.MAX_VALUE;
public class ShowInts
{public static void main(final String[] args)
{unlineShow(intShow).println(range(MIN_VALUE, MAX_VALUE + 1L));}}
At 1000 lines/sec you'll be done in about 7 weeks. Should we get coffee now?
Just improving the StringBuilder's approach a little:
2 threads + 2 buffers (i.e. StringBuilder): The main idea is that one thread fills one buffer while the other thread dumps the content of the other buffer.
Obviously, the "dumper" thread will always run slower than the "filler" thread.
If the interviewer was looking for all the Integer values possible in Java, You might try giving him a solution using Long:
class AllIntegers{
public static void main(String[] args) {
for (int i = Integer.MIN_VALUE; i < Long.MAX_VALUE; i++) {
System.out.println(i);
}
System.out.println(Long.MAX_VALUE);
}
}
This should print a range from -9223372036854775808 to 9223372036854775807 which is way more than you would achieve using Integer.