CodingBat: Java. Array-2, Part II

no14:

public boolean no14(int[] nums) {
	int ones = 0;
	int fours = 0;
	for (int i = 0; i < nums.length; i++) {
		if (nums[i] == 1) ones++;
		if (nums[i] == 4) fours++;
	}
	return ones == 0 || fours == 0;
}

isEverywhere:

public boolean isEverywhere(int[] nums, int val) {
	boolean flag1 = true;
	boolean flag2 = true;

	for (int i = 0; i < nums.length; i += 2)
		if (nums[i] != val) flag1 = false;

	for (int i = 0; i < nums.length - 1; i += 2)
		if (nums[i + 1] != val) flag2 = false;

	return flag1 || flag2;
}

either24:

public boolean either24(int[] nums) {
	Boolean twos = false;
	Boolean fours = false;

	for (int i = 0; i < nums.length - 1; i++) {
		if (nums[i] == 2 && nums[i + 1] == 2) twos = true;
		if (nums[i] == 4 && nums[i + 1] == 4) fours = true;
	}
	return twos ^ fours;
}

The caret (^) in the return statement represents the logical XOR operator.

matchUp:

public int matchUp(int[] nums1, int[] nums2) {
	int count = 0;
	for (int i = 0; i < nums1.length; i++)
		if (nums1[i] != nums2[i]
			&& Math.abs(nums1[i] - nums2[i]) <= 2)
				count++;
	return count;
}

has77:

public boolean has77(int[] nums) {
	for (int i = 0; i < nums.length - 1; i++)
		if (nums[i] == 7 && nums[i + 1] == 7) return true;

	for (int i = 0; i < nums.length - 2; i++)
		if (nums[i] == 7 && nums[i + 2] == 7) return true;

	return false;
}

has12:

public boolean has12(int[] nums) {
	int one = 0;
	int two = 0;
	for (int i = 0; i < nums.length; i++) {
		if (nums[i] == 1) one = i;
		if (nums[i] == 2) two = i;
	}
	return two > one;
}

The two variables keep track of the position of the number 1 and 2, respectively. After the for loop has finished, they will contain the position of the last 1 and last 2 in the array.

modThree:

public boolean modThree(int[] nums) {
	for (int i = 0; i <= nums.length - 3; i++) {
		boolean cond1 = nums[i] % 2 == 0 && nums[i + 1] % 2 == 0
				&& nums[i + 2] % 2 == 0;
		boolean cond2 = nums[i] % 2 == 1 && nums[i + 1] % 2 == 1
				&& nums[i + 2] % 2 == 1;
		if (cond1 || cond2) return true;
	}
	return false;
}

haveThree:

public boolean haveThree(int[] nums) {
	int count = 0;
	int pos = -2; // in case nums[0] == 3

	for (int i = 0; i < nums.length; i++) {
		if (nums[i] == 3) {
			count++;
			if (i - pos == 1) return false;
			pos = i;
		}
	}

	return count == 3;
}

twoTwo:

public boolean twoTwo(int[] nums) {
	for (int i = 0; i < nums.length; i++)
		if (nums[i] == 2) {
			int count = 0;
			for (int j = i; j < nums.length; j++)
				if (nums[j] == 2) count++;
				else break;
			i += count;
			if (count < 2) return false;
		}
	return true;
}

sameEnds:

public boolean sameEnds(int[] nums, int len) {
	for (int i = 0, j = nums.length - len; i < len; i++, j++)
		if (nums[i] != nums[j]) return false;
	return true;
}

The for loop traverses the array from back to front and front to back simultaneously.

47 thoughts on “CodingBat: Java. Array-2, Part II

  1. Louis N.

    Firstly, I’d like to thank you for taking the time to create meaningful solutions to the CodingBat exercises. My comment here is actually in response to your solution for the exercise “haveThree” in the section Array-2: http://codingbat.com/prob/p109783

    While your solution is marked correct by CodingBats, I believe there is one problem with it that CodingBats didn’t check. This is your solution found at: http://gregorulm.com/codingbat-java-array-2-part-ii/
    public boolean haveThree(int[] nums) {
    boolean foundFirst = false;
    int first3 = 0;
    int last3 = 0;
    int count = 0;

    for (int i = 0; i = 4);
    }

    The point in question is the return statement. You check to see if the first “3” is far enough away from the last “3” for it to be possible to have a number in between each 3. It does not actually check if there is a 3 next to any other three, however. So if the array were to be initialized to {3, 3, 1, 1, 3} your program would return true when it should return false. CodingBats never initializes the array as such, which gives the illusion that your solution is correct.

    Thanks again for your time, and I apologize if I am incorrect.

    Reply
    1. Gregor Ulm Post author

      Hi Louis,

      thank you very much for pointing this out! You are right indeed. Coding Bat does not cover the case you mentioned, and my solution didn’t account for it either. I have therefore rewritten the code, and updated the original post with a shorter and, in my opinion, cleaner solution. So, thanks again for letting me know.

      On a related note, my first attempt to rewrite the solution consisted of a single traversal of the array, minus the very last element, and checking whether a “3” is immediately followed by another “3”. I had a counter variable to keep track of the number of occurrences of “3”, and of course I had to add one last check for the very last element of the array. This solution passed all tests on Coding Bat except the “other tests” part, so I had to find a workaround for this issue of the auto grader, which inspired the solution I posted. Unexpectedly, this problem therefore turned into a neat diversion.

      Reply
  2. Frank

    Hi Gregor,
    Thanks for your work!

    I’ve got a remark about the has12 function. It is stated “Given an array of ints, return true if there is a 1 in the array with a 2 somewhere later in the array. “. However, as you check the position of the last 1 and of the last 2, you do not take into account something like {1,3,2,1}. This set should result in a true, however your function would return false, as there is a final 1. This case is not covered by the CodingBat tests.

    My solution looks like this:

    public boolean has12(int[] nums) {
    int i = 0;
    for(; i < nums.length; i++)
    // a 1 is found
    if(nums[i] == 1)
    break;
    //We start looking for a 2 from the position of the first found1
    for (int j=i; j < nums.length; j++)
    if(nums[j] ==2) return true;

    return false;
    }

    Reply
    1. Gregor Ulm Post author

      Hi Frank,

      thanks for your comment. Since I did not specify the requirements for has12, I can only rely on my own interpretation, based on the test cases Nick Parlante provides on his site. To me it therefore seems that his description on the problem — “return true if there is a 1 in the array with a 2 somewhere later in the array” — has to be understood as returning False if there is a 1 that is not followed by a 2 later in the array. Therefore, the case you provide, {1,3,2,1}, should result in False, not True.

      I’m afraid we have to agree to disagree here, but please note that you’re writing code for a merely imagined test case. Based on Nick Parlante’s test cases, your solution is therefore needlessly complicated.

      Reply
        1. Henrik

          Hi Gregor,
          comparing my answers of the Codingbat problems to yours and I have learnt quite a bit form your examples.
          However, here I have to agree with Frank. You solution on “has12” is flawed.
          To quote: “if there is A 1 in the array with a 2 somewhere later” specifies a single possible case not a case for each ‘1’. Franks case is indeed needlessly complicated, and your needlessly checks the entire array and gives some incorrect outcomes.

          This is clearer:
          boolean has1=false;

          for (int i : nums) {
          if(i == 1)
          has1 = true;
          if(has1 && i == 2)
          return true;
          }
          return false;

          Reply
          1. Gregor Ulm Post author

            It doesn’t really matter what we think the specification means. Nick Parlante, I presume, wrote the test cases on the Coding Bat website, and he would need to be the final arbiter in this case. I think my interpretation is obvious, and the only plausible one. You think the same about yours. My code passes all test cases on the Coding Bat site; yours presumably does as well. Since the test cases permit at least two solutions who differ in a non-trivial aspect, this problem is therefore underspecified. (Please note that I do not want to encourage you, or anyone else, to email Nick Parlante about this matter.)

  3. Frank

    Hi Gregor,

    Concerning the “modThree” exercise, I would have a remark/alternative solution. The solution below is slightly less verbose than yours, as it only checks that three consecutive elements have the same parity, without checking whether they are even or odd.

    public boolean modThree(int[] nums) {
    for(int i = 0; i < nums.length-2; i++)
    if( nums[i] % 2 == nums[i+1] % 2 && nums[i+1] % 2 == nums[i+2] %2 ) return true;
    return false;
    }

    Thank again for the great work provided.

    Reply
  4. whistl3r

    the modThree solution is elegant. You should have seen the 60 line “solution” that i spent so many days on that btw did not work all the way looked like. Thanks for uploading it…

    Reply
  5. Wayne

    Hi Gregor,

    For twoTwo, I think your solution didn’t take into account the situation where three “2” are placed in the middle, for example {3,3,2,2,2,1,1,3}. Following is my solution:

    public boolean twoTwo(int[] nums) {
    for (int i=0; i<nums.length; i++) {
    if (nums[i]==2) {
    if ((i+10 && nums[i-1]==2)) {
    i++;
    }
    else return false;
    }
    }
    return true;
    }

    Thanks so much for your effort and time.

    Reply
    1. Gregor Ulm Post author

      My solution could probably be rewritten a bit more nicely. I might have a go at it later today. However, your code looks odd to me. Did you paste all of it? For one, (i+10 && nums[i-1]==2) isn’t a legal statement, and ‘i+10’ is cryptic to begin with.

      Reply
      1. Wayne

        Aha, that’s weird, because I just copied and pasted. Now it should work.

        public boolean twoTwo(int[] nums) {
        for (int i=0; i<nums.length; i++) {
        if (nums[i]==2) {
        if ((i+10 && nums[i-1]==2)) {
        i++;
        }
        else return false;
        }
        }
        return true;
        }

        Reply
        1. Wayne

          Okay, i don’t know what happened. Try one more time.

          public boolean twoTwo(int[] nums) {
          for (int i=0; i<nums.length; i++) {
          if (nums[i]==2) {
          if ((i+10 && nums[i-1]==2)) {
          i++;
          }
          else return false;
          }
          }
          return true;
          }

          Reply
          1. Michael

            /*
            *Description of Code: In this approach, it takes the #s of ‘2’ and the number of
            *’2′ next to each other and compares them to check if all ‘2’ are next to each
            other
            *I hope this ( ͡° ͜ʖ ͡°)
            */

            public Boolean twoTwo(int[] nums) {
            int count = 0;
            int twos = 0;

            for (int i = 0; i 0 && nums[i – 1] == 2){
            count += 1;
            } else if (i < nums.length – 1 && nums[i + 1] == 2){
            count += 1;
            }
            }
            }

            return (count == twos);
            }

          2. Michael

            /*
            *Description of Code: In this approach, it takes the #s of ‘2’ and the number of
            *’2′ next to each other and compares them to check if all ‘2’ are next to each other
            *I hope this ( ͡° ͜ʖ ͡°)
            */

            public Boolean twoTwo(int[] nums) {
            int count = 0;
            int twos = 0;

            for (int i = 0; i 0 && nums[i – 1] == 2){
            count += 1;
            } else if (i < nums.length – 1 && nums[i + 1] == 2){
            count += 1;
            }
            }
            }

            return (count == twos);
            }

            Oops seems like I posted the error code. My bad.

  6. Wayne

    Sorry for the spams. How can I delete my replies? The condition before i++ is:

    (i+10 && nums[i-1]==2)

    and the i++ should be removed. So the complete code is as following:

    public boolean twoTwo(int[] nums) {
    for (int i=0; i<nums.length; i++) {
    if (nums[i]==2) {
    if ((i+10 && nums[i-1]==2));
    else return false;
    }
    }
    return true;
    }

    I really hope it works this time……….

    Reply
    1. Gregor Ulm Post author

      Your code still doesn’t make any sense. It doesn’t even compile. Anyway, I’ve rewritten my solution to TwoTwo, which takes your test case into account. It has the added benefit that it is easier to understand, compared to the previous one.

      Reply
      1. Wayne

        Thanks for your time and sorry for my spams. Every time I wrote the comment, everything worked, but once I posted, it has been changed without reasons. Of course the posted version cannot compile…

        Really the last post, if it doesn’t work, then just ignore it. The condition is
        if (nums[i+1]==2 when i is not the end) or (nums[i-1]==2 when i is not the start), then do nothing, so simply put a “;”
        else return false;

        Have a nice weekend!

        Reply
  7. Ryan Memmott

    I have an interesting solution to either24.

    public boolean either24 (int[] nums) {
    String str=Arrays.toString (nums);
    return str.indexOf (“2, 2”)!=-1^str.indexOf (“4, 4”)!=-1;
    }

    probably a background intensive means of doing it. but still….

    Reply
  8. Ryan Memmott

    For modThree here’s a solution that only does 3 comparisons per loop and only 1 variable added.

    public boolean modThree(int[] nums) {
    int count=0;
    for (int x: nums) {
    count=x%2==0? (count> 0? count+1:1):(count 3) return true;
    }
    return false;
    }

    Reply
    1. Ryan Memmott

      Basically for line 4 of my code the less then sign which should follow the count in ….count 3) paired with a greater then sign in line 5.

      public boolean modThree(int[] nums) {
      int count=0;
      for (int x: nums) {
      count=x%2==0? (count> 0? count+1:1):(0>count? count-1:-1);
      if Math.abs (count==3) return true;
      }
      return false;
      }

      Reply
    1. Subhan Ibrahimli

      public int[] fizzArray3(int start, int end) {
      int[] res = new int[end-start];

      for (int i = 0; i < res.length; i++) // index 0
      {
      if (start < end) {
      res[i] = start;
      start++;
      }
      }
      return res;
      }

      Reply
  9. JR Kim

    Hey thank you for providing the answer. i really appreciate it! it’s good to take a look at different perspective!

    I just had a quick comment on sameEnds function:

    for time complexity(to avoid using double for-loops), can’t you do something like:

    public boolean sameEnds(int[] nums, int len) {
    for(int i=0; i<len; i++) {
    if(nums[i]!=nums[i+nums.length-len]) {
    return false;
    }
    }
    return true;
    }

    let me know what you think! thanks!

    Reply
  10. Ryan

    Hello. Thank you for all of these explanations and solutions.

    Your Twotwo solution has two loops in it, the requirements on the CodingBat site under the Array-2 section state to use only one loop though..

    Reply
  11. William

    Hey, found a much simpler one for isEverywhere, thought I’d share it 🙂
    //basically checks every pair of numbers and sees if one is val
    //since you’re checking in pairs and if you search to nums.length-1, no out of bounds and it covers everything

    public boolean isEverywhere(int[] nums, int val) {

    for(int i=0;i<nums.length-1;i++){
    if(!(nums[i]==val||nums[i+1]==val))return false;
    }
    return true;

    }

    Reply
    1. Richard

      This is the approach I used, which is slightly easier to follow and uses the same logic:

      public boolean isEverywhere(int[] nums, int val) {
      for(int i = 0; i < nums.length – 1; i++){
      if(nums[i] != val && nums[i+1] != val) return false;
      }
      return true;
      }

      Reply
    2. Jeff

      Gregor’s solution for the isEverywhere problem may be flawed. Just one test case that doesn’t work with Gregor’s code:

      [1, 2, 1, 2, 1, 1, 3, 1], 1

      Reply
      1. Gregor Ulm Post author

        You are right. William as well as Richard provided a cleaner solution already, though.

        Reply
  12. Barto

    My approach for “either24” was a bit different. I parsed int[] array to String and check if it contains 2s or 4s.

    public boolean either24(int[] nums)
    {
    if( Arrays.toString( nums ).contains( “2, 2” ) &&
    !Arrays.toString( nums ).contains( “4, 4” ) )
    return true;
    if( Arrays.toString( nums ).contains( “4, 4” ) &&
    !Arrays.toString( nums ).contains( “2, 2” ) )
    return true;
    return false;
    }

    Reply
  13. Wazim Karim

    Beginner’s Solution to sameEnds 🙂

    public boolean sameEnds(int[] nums, int len) {
      String startEnd = "";
      String numsAsString = "";
        for(int i:nums){
        numsAsString = numsAsString + Integer.toString(i);
      }
      startEnd = numsAsString.substring(0,len);
      return numsAsString.startsWith(startEnd) && numsAsString.endsWith(startEnd);
    }
    
    Reply
  14. Wazim Karim

    Your solution to has12 is nicely thought out! Here’s mine. This is just my initial approach after reading the problem. I program just for fun, btw. Total newbie.

    public boolean has12(int[] nums) {
      boolean hasTwo = false;
      // start from the back looking for 2;
      for(int i = nums.length-1; i >= 0; i--){
        //if a 2 is found flag it as true;
        if(nums[i]==2) hasTwo = true;
        //run the flag and next element through an AND gate;
        if(hasTwo && nums[i]==1) return true;
      }
      //return false if neither of above conditions are met.
      return false;
    }
    
    Reply
  15. Rickyg

    For has 77, I have done with one FOR statement but with short-circuit AND’s.
    public boolean has77(int[] nums) {
    for (int i=0; i<nums.length-1; i++){
    if (nums[i]==7 && nums[i+1]==7) return true;
    if (nums[i]==7 && i <nums.length-2 && nums[i+2]==7) return true;
    }
    return false;
    }

    Reply
  16. Steen

    Hi Gregor.

    It’s a very nice site you’ve made. However, your solution to “has12” isn’t you at your best performance, if I may be the judge of it. Not only do i agree with those who critizise you for your interpretation of the wording of the task – worse, if I insert your solution into codingbat.com and press “Go”, I get an error. Namely, if there’s no 1’s in the array at all – as in {3, 2}, which it tests for. Your “opponents” code don’t get that same error.

    Myself, I got an error in “other tests” for the following code. And I don’t seem to be able to find any input that’ll make err. :/

    public boolean has12(int[] nums) {
    int i = 0;
    while (true){
    if (nums[i]==1)
    for (int j = i+1; j < nums.length; j++)
    if (nums[j]==2) return true;
    i++;
    if (i==nums.length) break;
    }
    return false;
    }

    Oh – and Henrik's code I found very elegant. Thank you!

    Reply
  17. Steen

    It could be a bit clearer, I have to admit. I’m an eternal beginner. And I haven’t yet found out how to insert indented code clearly into my comment.

    Reply
  18. WOJTEK

    My solution

    public boolean has12(int[] nums) {
    for(int i=0; i<nums.length; i++){
    if(nums[i]==1){
    for(int j=i; j<nums.length; j++)
    if(nums[j]==2) return true;
    }
    }
    return false;
    }

    Reply
  19. Bob Jones

    Hello! For your has12 code, it does not work for all test cases. To make it work, all you need to do is set the initial positions of one and two to -1 initially and have return two > one && one > -1;.

    Otherwise, if the array was [3, 2], let’s say, it would return true even though there are no ones.

    Thanks! 🙂

    Reply
  20. jared

    //alternative solution to modThree that i think is easier to understand
    public boolean modThree(int[] nums) {
    int even =0;
    int odd =0;
    for(int i=0;i<nums.length;i++){
    if(nums[i]%2==0){
    even++;
    odd=0;
    }
    else{
    odd++;
    even=0;
    }
    if(even==3||odd==3)
    return true;
    }
    return false;
    }

    Reply
  21. PAN

    public int countClumps(int[] nums) {
    int count =0;
    boolean clump = false;
    for (int i=0; i < nums.length -1; i++){
    if (nums[i] == nums[i+1] && !clump){
    count++;
    clump = true;
    }else if (nums[i] != nums[i+1])
    clump = false;
    }
    return count;
    }

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Spammer prevention; the answer is an integer: * Time limit is exhausted. Please reload CAPTCHA.