How to check if an array of numbers has gaps? - java

I have a Long array with these numbers:
long[] = {1,2,3,5,6,7};
Notice that 4 is missing.
What's the best way to test this array if any such gaps exist or not?

If you're guaranteed that arrays is ordered without any duplicate then you could check that in O(1)
I think this code should work in this specific case :)
//assume that given array is ordered and has no duplicated value
long[] myarray = {5,6,7}; //no gap
long[] myarray1 = {1,2,4}; //has gap
long[] myarray2 = {10,11,12,13,14,15}; //no gap
//return true if has gap
//return false if no gap
//throw null-pointer if empty
public static boolean checkIfHasGap(long[] array) {
if (array.length == 0) {
throw new NullPointerException("Given Array is empty");
} else {
return array[0] + array.length != array[array.length - 1] + 1;
}
}

public static boolean hasGaps(long[] array) {
if (array == null || array.length == 0) {
return false;
}
if (array[array.length - 1] - array[0] + 1 != array.length) {
return true;
}
for (int i = 1; i < array.length; i++) {
if (array[i] != array[i - 1] + 1) {
return true;
}
}
return false;
}
This method first check for the "easy" cases, then iterate the array to check the more complex cases.

Loop through the array and check, if the current item is exactly x more than the current index, where x is the first element in your array.
public boolean hasGaps(long[] array) {
if(array == null || array.length == 0) {
return false;
}
long start = array[0];
for(int i = 0; i < array.length; i++) {
if(array[i] != i + start) {
return true;
}
}
return false;
}

A simpler and reliable way:
const getMissingNumbers = (list) => {
if (!list || list.length === 0) return [];
const missing = [];
// sort the list
list.sort((a, b) => a - b);
// pin start and end points in the list
const step = list[0];
const last = list[list.length - 1];
for (let i = step; i < last; i++) {
if (list.indexOf(i) === -1) missing.push(i);
}
return missing;
}

Related

How to check if all elements in array are even in Java

How i can check if all elements in the arrays are even or odd?
For the evens I try with this:
public boolean isEvens(int[] array) {
for (int i = 0; i<array.length;i++) {
if ( i % 2 == 0) {
return true;
}
else {
return false;
}
}
}
But there is error......
Thnx in advance !
You should check the array elements, not the array indices.
You shouldn't return true before checking all the elements of the array.
You can use a counter to count the number of odds or evens, or a boolean to determine if there are any odds or evens.
For example:
public boolean allEven(int[] array) {
for (int i = 0; i<array.length; i++) {
if (array[i] % 2 != 0) {
return false;
}
}
return true;
}
To check whether all are even or all are odd:
public boolean allEvenOrAllOdd(int[] array) {
boolean hasOdd = false;
boolean hasEven = false;
for (int i = 0; i<array.length; i++) {
if (array[i] % 2 == 0) {
hasEven = true;
if (hasOdd) { // has both odds and evens
return false;
}
} else {
hasOdd = true;
if (hasEven) { // has both odds and evens
return false;
}
}
}
return true; // either all elements are odd or all elements are even
}
Since java 8 it's a good practice to reduce code by using lambdas:
For even:
return Arrays.stream(array).allMatch( i -> i % 2 == 0);
for odd:
return Arrays.stream(array).allMatch( i -> i % 2 == 1);
Just check for an odd element, if not present then all are even.
public boolean isEvens (int[] array){
for (int i = 0; i < array.length; i++) {
if (array[i] % 2 != 0) {
return false;
}
}
return true;
}
You want to be comparing array elements at index i, and not i itself.
The check should be if (array[i] % 2 == 0)
Use Below code to for reference use a[i]
public static void isEvens() {
int [] array = {1,2,3,4,5};
for (int i = 0; i<array.length;i++) {
if (array[i] % 2 == 0) {
System.out.println("Even");
}
else {
System.out.println("Odd");
}
}
I would recommend using recursion for it, because with recursion the run time will be less than with loops, also it's some lines of code.
I made a code for doing this but with c#, I will post it below, it might help you, because the syntax in java is so similar to the syntax of c#.
public static bool isAllEvens(int[] a, int index)
{
if (index == 0 && a[index] % 2 == 0) return true;
else
{
if (a[index] % 2 == 0)
return true && isAllEvens(a, index - 1);
return false;
}
}
And to call this function just call it with two parameters(array, and array.length - 1 which is the last index).
Here is an example for calling this function:
int[] a = new int[4];
a[0] = 8; a[1] = 4; a[2] = 8; a[3] = 8;
Console.WriteLine(isAllEvens(a, a.Length - 1));

Java Program testing for a strictly increasing array after removing at most one element

Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.
For sequence = [1, 3, 2, 1], the output should be
almostIncreasingSequence(sequence) = false;
There is no one element in this array that can be removed in order to get a strictly increasing sequence.
For sequence = [1, 3, 2], the output should be
almostIncreasingSequence(sequence) = true.
You can remove 3 from the array to get the strictly increasing sequence [1, 2]. Alternately, you can remove 2 to get the strictly increasing sequence [1, 3].
The code which I've written for the above is given bellow , but it's not satisfying for sequence [1,2,3,4,3,6]
Actual output = false
expected output = true
boolean almostIncreasingSequence(int[] sequence) {
int max = Integer.MIN_VALUE, count = 0;
boolean flag = true;
for (int j = 0; j < sequence.length-1 ; j++){
if ( max >= sequence [j] || sequence[j]>=sequence[j+1]){
count++;
}
else
max = sequence[j];
if ( count > 1){
flag = false;
break;
}
}
return flag;
}
[time limit] : 3000ms (java)
[input] : array.integer sequence
Guaranteed constraints:
2 ≤ sequence.length ≤ 105,
-105 ≤ sequence[i] ≤ 105.
[output] : boolean
Return true if it is possible to remove one element from the array in order to get a strictly increasing sequence, otherwise return false.
This is one of the errors that can be fixed by just removing stuff from the original program:
boolean almostIncreasingSequence(int[] sequence) {
int max = Integer.MIN_VALUE, count = 0;
boolean flag = true;
for (int j = 0; j < sequence.length; j++){
if ( max >= sequence[j]){
count++;
}
max = sequence[j];
if ( count > 1){
flag = false;
break;
}
}
return flag;
}
The main problem of the original version was, that the same out-of-order place was found two times. Just removing one of the checks, and at the same time adding one loop iteration solves this.
Based on your method, I would suggest you to do the following modification in your for loop:
for (......):
if s[i] >= s[i+1] count++
else if max >= s[i] count++
else max = s[i]
After finished for loop:
if count > 1 return false
else return true
Using a simplistic brute force approach, create a method that returns an array with one of the elements missing, then check that array to see if it is increasing. A Loop around all of this should work.
public static void main(String[] args) {
if (IncreasingSequence(new int[] {1,2,3,4,3,6}))
System.out.println("By removing one element the array is increasing");
else
System.out.println("By removing one element the array is Not increasing");
}
private static boolean IncreasingSequence(int[] sequence) {
int[] nextArray;
for (int i = 0; i < sequence.length; i++) {
nextArray = MinusOneElement(sequence, i);
if (CheckSequenceIncreasing(nextArray))
return true;
}
return false;
}
private static boolean CheckSequenceIncreasing(int[] sequence) {
for (int i = 0; i < sequence.length - 1; i++) {
if (sequence[i] >= sequence[i + 1]) {
return false;
}
}
return true;
}
private static int[] MinusOneElement(int[] sequence, int elementToRemove) {
int[] newArray = new int[sequence.length - 1];
int index = 0;
for (int i = 0; i < sequence.length; i++) {
if (i != elementToRemove) {
newArray[index] = sequence[i];
index++;
}
}
return newArray;
}
This program goes through elements of array comparing if current is bigger or equal to next. If so it compares elements around current because it may be removed. And it compares elements around next because it may be removed. If deleting current or next doesn't make increasing array return false.
public static void main(String[] args) {
boolean almostIncreasingSequence = almostIncreasingSequence(new int[] { 1, 2, 3, 4, 99, 4, 3 });
System.out.println(almostIncreasingSequence);
}
static boolean almostIncreasingSequence(int[] sequence) {
int removeCount = 0;
for (int i = 0; i < sequence.length - 1; i++) {
int current = sequence[i];
int next = sequence[i + 1];
if (current >= next) {
removeCount++;
// Try to remove current. Skip removed element(current). Check
// if previous is less than next element around current
// if i is 0 there is no previous element
// if removeCurrent is true it is possible to remove it and
// arrays stays increasing
boolean removeCurrent = i == 0 || sequence[i - 1] < next;
// if removeNext is true it is possible to remove it and arrays
// stays increasing
boolean removeNext = i + 1 == sequence.length - 1 || current < sequence[i + 2];
if (!removeCurrent && !removeNext)
// if current is removed and array isn't increasing and if
// next is removed and array is not increasing,
// increment removeCount to return false
removeCount++;
}
if (removeCount > 1) {
return false;
}
}
return true;
}
it meets all given test cases.
For kotlin Programmers
fun almostIncreasingSequence(sequence: MutableList<Int>): Boolean
{
var removeCount = 0;
var i = 0;
while ( i < sequence.size - 1) {
var current = sequence[i];
var next = sequence[i + 1];
if (current >= next) {
removeCount++;
var removeCurrent : Boolean= i == 0 || sequence[i - 1] < next;
var removeNext : Boolean = i + 1 == sequence.size - 1 || current < sequence[i + 2];
if (!removeCurrent && !removeNext)
removeCount++;
}
if (removeCount > 1) {
return false;
}
i++
}
return true;
}

Need help to solve the hackerrank challenge

I'm trying to solve an "Almost Sorted" challenge in hackerrank the problem is:
Given an array with elements, can you sort this array in ascending order using only one of the following operations?
Swap two elements.
Reverse one sub-segment.
Input Format
The first line contains a single integer, , which indicates the size of the array.
The next line contains integers separated by spaces.
Sample Input #1
2
4 2
Sample Output #1
yes
swap 1 2
Sample Input #2
3
3 1 2
Sample Output #2
no
Sample Input #3
6
1 5 4 3 2 6
Sample Output #3
yes
reverse 2 5
I tried to solve the challenge and my code is working but it seems it's to slow for big arrays.
Kindly asking you to help me to find a better solution for mentioned problem.
Below is my code:
import java.util.*;
public class Solution
{
private static int[] arr;
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int N = in.nextInt();
arr = new int[N];
for (int i = 0; i < N; i++)
{
arr[i] = in.nextInt();
}
if (IsSorted(arr))
{
System.out.println("yes");
return;
}
if(CheckSingleSwap(arr))
return;
if(CheckSingleReverse(arr))
return;
System.out.println("no");
}
private static boolean CheckSingleReverse(int[] arr)
{
int length = arr.length;
int limit = length - 2;
int current = 1;
List<Integer> indexes = new ArrayList<Integer>();
while (current < limit)
{
for (int i = 0; i < length; i++)
{
int temp = current + i;
for (int j = i; j <= temp && temp < length; j++)
{
indexes.add(j);
}
if (IsSorted(ReverseArrayPart(arr, indexes)))
{
System.out.println("yes");
System.out.println("reverse " + (indexes.get(0) + 1) + " " + (indexes.get(indexes.size() - 1) + 1));
return true;
}
indexes.clear();
}
current++;
}
return false;
}
private static int[] ReverseArrayPart(int[] arr, List<Integer> indexes)
{
int[] result = new int[arr.length];
int[] arrayPart = new int[indexes.size()];
int j = 0;
for (int i = 0; i < arr.length; i++)
{
if (indexes.contains(i))
{
arrayPart[j] = arr[i];
j++;
}
result[i] = arr[i];
}
for(int i = 0; i < arrayPart.length / 2; i++)
{
int temp = arrayPart[i];
arrayPart[i] = arrayPart[arrayPart.length - i - 1];
arrayPart[arrayPart.length - i - 1] = temp;
}
j = 0;
for (int i = 0; i < result.length; i++)
{
if (indexes.contains(i))
{
result[i] = arrayPart[j];
j++;
}
}
return result;
}
private static boolean CheckSingleSwap(int[] arr)
{
int count = 0;
int[] B = Arrays.copyOf(arr, arr.length);
Arrays.sort(B);
List<Integer> indexes = new ArrayList<Integer>();
for(int i = 0; i < arr.length; i++)
{
if(arr[i] != B[i])
{
count++;
indexes.add(i+1);
}
}
if(count > 2)
return false;
System.out.println("yes");
System.out.println("swap " + indexes.get(0) + " " + indexes.get(1));
return true;
}
private static boolean IsSorted(int[] arr)
{
int length = arr.length;
for (int i = 0; i < length - 1; i++)
{
if (arr[i] > arr[i + 1])
{
return false;
}
}
return true;
}
}
For the following code, pass in A as the original array and B as the sorted array.
CheckSingleSwap:
Instead of adding the indices to another list, store the first swap you encounter, and keep going; if you find the corresponding other swap, then store it and record the finding; if you find a different swap, exit with false. At the end if you've recorded the finding, print the corresponding indices.
private static boolean CheckSingleSwap(int[] A, int[] B)
{
int L = A.length;
int firstSwap = -1, secondSwap = -1;
for(int i = 0; i < L; i++)
{
if(A[i] != B[i])
{
if (firstSwap == -1)
firstSwap = i;
else if (secondSwap == -1 && A[i] == B[firstSwap] && A[firstSwap] == B[i])
secondSwap = i;
else
return false;
}
}
if (firstSwap != -1 && secondSwap != -1)
{
System.out.println("yes");
System.out.println("swap " + (firstSwap + 1) + " " + (secondSwap + 1));
return true;
}
System.out.println("array is already sorted!");
return false; // or whatever you decide to do; maybe even an exception or enumerated type
}
CheckSingleReverse:
You are doing WAY too much here! You seem to be brute forcing every single possible case (at first glance).
What you can do instead is to find the region where all the numbers are different. If there are more than two of these, or two which are separated by more than one element, then return false immediately.
The reason for the "more than one" thing above is because of odd-number length regions - the middle element would be the same. If you find such two regions, treat them as one. Then you can proceed to find out if the region is reversed.
private static boolean CheckSingleReverse(int[] A, int[] B)
{
// find region
int L = A.length;
int diffStart = -1, diffEnd = -1; boolean mid = false, found = false;
for (int i = 0; i < L; i++)
{
if (A[i] != B[i])
{
if (found)
{
if (i - diffEnd == 2 && !mid)
{
mid = true;
found = false;
diffEnd = -1;
}
else
return false;
}
else if (diffStart == -1)
diffStart = i;
}
else
if (diffStart != -1 && diffEnd == -1)
{
found = true;
diffEnd = i - 1;
}
}
if (diffEnd == -1)
{
if (A[L - 1] != B[L - 1])
diffEnd = L - 1;
else if (!found)
{
System.out.println("array is already sorted!");
return false;
}
}
// find out if it's reversed
int count = (diffEnd - diffStart + 1) / 2;
for (int i = 0; i < count; i++)
{
int oneEnd = diffStart + i, otherEnd = diffEnd - i;
if (!(A[oneEnd] == B[otherEnd] && A[otherEnd] == B[oneEnd]))
return false;
}
System.out.println("yes");
System.out.println("reverse " + (diffStart + 1) + " " + (diffEnd + 1));
return true;
}
Just to give you an idea of the performance boost, on ideone.com, with an array length of 150, the original implementation of CheckSingleReverse took 1.83 seconds, whereas the new one took just 0.1 seconds. With a length of 250, the original actually exceeded the computational time limit (5 seconds), whereas the new one still took just 0.12 seconds.
From this it would seem that your implementation takes exponential time, whereas mine is linear time (ignoring the sorting).
Funnily enough, with an array size of 3 million I'm still getting around 0.26 seconds (ideone's execution time fluctuates a bit as well, probs due to demand)

Binary search an element (with duplicate items) in a 2D array column-wise sorted?

EDIT:
For the 2D array, only column were sorted but not sorted for rows. Below is the method I wrote, first binary search each column, then go through every column and also count the duplicate element.But the code does not work for me. Does anyone can help me? Many thanks!
public static int count(int[][] array, int query) {
int count = 0;
for (int j = 0; j < array[0].length; j++) {
count += biSearch(array, query, j);
}
return count;
}
private static int biSearch(int[][] array, int searchItem, int row) {
// create a 1D array to hold the entries of 2D array's column
int[] column = new int[array.length];
int count = 0;
int low = 0;
int high = column.length - 1;
// put 2D array's column into 1D array
for (int i = 0; i < array.length; i++)
column[i] = array[i][row];
// binary search on column array
while (low < high) {
int mid = (low + high) / 2;
if ( column[mid]== searchItem ) {
while ((mid - 1) >= 0) {
if (column[mid - 1] == searchItem){
mid--;
count++;
}
}
while ((mid + 1) < (column.length - 1)) {
if (column[mid + 1] == searchItem){
mid++;
count++;
}
}
}
else if ( column[mid] > searchItem)
high = mid - 1;
else if (column[mid] <searchItem )
low = mid + 1;
}
return count;
}
Not sure if that's the only problem, but this code is wrong :
if ( column[mid]== searchItem ) {
while ((mid - 1) >= 0) {
if (column[mid - 1] == searchItem){
mid--;
count++;
}
}
while ((mid + 1) < (column.length - 1)) {
if (column[mid + 1] == searchItem){
mid++;
count++;
}
}
}
It basically tests all the elements of the column array from mid to 0, and than from 0 to column.length-1. Not only you pass over the entire array, which defeats the purpose of your binary search, you visit all the elements between mid and 0 twice, which means your count is wrong.
At better approach :
if ( column[mid]== searchItem ) {
count = 1;
int temp = mid;
while (temp > 0 && column[temp - 1] == searchItem) {
temp--;
count++;
}
temp = mid;
while (temp < column.length - 1 && column[temp + 1] == searchItem) {
temp++;
count++;
}
}
The two things to note :
I don't modify mid, since we need the original value of mid for the second while loop.
I quit each while loop when I encounter an element that is not equal to searchItem. Since the array is supposed to be sorted (otherwise binary serarch won't work), there's no need to iterate over the entire array.
P.S. the argument called row in your biSearch is actualy an index of a column of your 2D array, so its name is confusing.

Finding three elements in an array that are not adjacent

This the question I must answer-
Given an array of ints, return true if the value 3 appears in the array exactly 3 times, and no 3's are next to each other.
haveThree({3, 1, 3, 1, 3}) → true
haveThree({3, 1, 3, 3}) → false
haveThree({3, 4, 3, 3, 4}) → false
This is my solution:
public boolean haveThree(int[] nums) {
int count = 0;
for (int i=0;i<nums.length-1;i++) {
if (nums[i] == 3 && nums[i+1] ==3) {
return false;
}
else
if ((nums[i]==3 && nums[i+1]!=3)||(nums[i]==3 && nums[i+1]!=3)) {
count ++;
}
}
return count ==3;
}
It fails for some tests. For example {3,1,3,1,3} should result in true being returned; however, false is returned and I can't figure out why.
You need to loop all the way to nums.length to count all occurences. Also, there is no need for the else statement. I would do something like:
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 3) {
if ((i < nums.length - 1) && (nums[i + 1] == 3)) {
return false;
}
count++;
}
}
It fails for that example because you don't check the last index, presumably to fix the out of bounds error for checking if two 3's are next to eachother. Also the or condition in your second if statement is redundant.
public boolean haveThree(int[] nums) {
int count = 0;
for (int i=0;i<nums.length-1;i++) {
if (nums[i] == 3 && nums[i+1] ==3) {
return false;
}
if ((nums[i]==3)) { //removed redundant condition and doesn't need to be an else
count ++;
}
}
// check the last index, you've already ensured the second to last is not also a 3
if(nums[nums.length-1] == 3) {
count++;
}
return count == 3;
}
Because you're not comparing the final value, you can't tell if the last array element is a three or not. What I would do (to guarantee going through each element as needed) is add a flag boolean that lets you know if the previous value was a three or not (resetting it back to false if the current value is not three).
My example:
public boolean haveThree(int[] nums) {
int count = 0;
boolean flag = false;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 3) { // The current value is a 3
if(flag) { // Previous value was a 3, rejecting.
return false;
}
else { // We have another 3, set the flag
count++;
flag = true;
}
}
else { // Since this wasn't a 3, we can set the flag back to false
flag = false;
}
}
return count == 3;
}
The for statement also has another form designed for iteration through Collections and arrays, and can be used to make your loops more compact and easy to read.
boolean haveThree(int[] nums) {
int count = 0, prevNum = 0;
for (int i : nums){
if (i==3) {
count++;
if (prevNum == i)
return false;
}
prevNum = i;
}
return count == 3;
}
As some people have already pointed out, you are not counting all the 3s that are present in the array. Your loop ends just before the last element in order to avoid ArrayIndexOutOfBoundsException.
It is a logical error. Your code fails for the test case that you've mentioned because first if condition returns false when i = 0. I wrote the following code snippet when I practiced. Hope it helps.
public boolean haveThree(int[] nums) {
int threeCount = 0;
boolean successive3s = false;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 3) {
threeCount++;
}
if (nums[i] == 3 && (i + 1) < nums.length && nums[i + 1] == 3)
successive3s = true;
}
return (!successive3s && threeCount == 3);
}
public boolean haveThree(int[] nums) {
int count = 0;
if(nums.length >= 1 && nums[0] == 3)
count++;
for(int i = 1; i < nums.length; i++) {
if(nums[i - 1] == 3 && nums[i] == 3)
return false;
if(nums[i] == 3)
count++;
}
return count == 3;
}
I made a trailing counter for mine.
public boolean haveThree(int[] nums)
{
//We check to see if it is possible to get 3 without being in a row.
//In this case, it is the smallest at five chars
//E.G 31313, so if we have any size less than this, we know it to be false.
if (nums.length >= 5)
{
//Create a counter to track how many 3's we have in a row,
//as well as how many we have total.
int counterInRow = 0;
int counterThrees = 0;
//Check for 3's
for (int i = 0; i < nums.length; i++)
{
//If a number is 3, we increment both;
if (nums[i] == 3)
{
counterInRow++;
counterThrees++;
}
//Otherwise, we reset the amount in a row to 0;
else
{
counterInRow = 0;
}
//If we have 2 or more in a row, we return false.
if (counterInRow >= 2)
{
return false;
}
}
//Return if the amount of the counterThrees equals 3 or not.
return (counterThrees == 3);
}
//If we have less than 5 characters, it isn't possible. We then,
//Return false;
else
{
return false;
}
}

Categories