Java - Assistance with understanding codility code - java

For the PermCheck codility test, I coded one solution (please see below) but it only really solved the example given in the codility test because there are only a few values in the array and small values. I also added code below which scored 100%, which is code I found on the internet. That code looks very different from mine and I couldn't work out how he/she was able to get the answer. Could someone please explain the code step by step and how it results in the answer please.
Codility Test:
PermCheck
Check whether array A is a permutation.
A non-empty zero-indexed array A consisting of N integers is given.
A permutation is a sequence containing each element from 1 to N once, and only once.
For example, array A such that:
A[0] = 4
A[1] = 1
A[2] = 3
A[3] = 2
is a permutation, but array A such that:
A[0] = 4
A[1] = 1
A[2] = 3
is not a permutation, because value 2 is missing.
The goal is to check whether array A is a permutation.
Write a function:
class Solution {
public int solution(int[] A);
}
that, given a zero-indexed array A, returns 1 if array A is a permutation and 0 if it is not.
For example, given array A such that:
A[0] = 4
A[1] = 1
A[2] = 3
A[3] = 2
the function should return 1.
Given array A such that:
A[0] = 4
A[1] = 1
A[2] = 3
the function should return 0.
Assume that:
N is an integer within the range [1..100'000];
Each element of array A is an integer within the range [1..1'000'000'000].
Complexity:
Expected worst-case time complexity is O(N)
Expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
100% Score Solution (found from internet):
public static final int NOT_PERMUTATION = 0;
public static final int PERMUTATION = 1;
// (4,1,3,2) = 1
// (4,1,3) = 0
// (1) = 1
// () = 1
// (2) = 0
public int PermSolution(int[] A) {
// write your code in Java SE 8
int[] mark = new int[A.length + 1];
int counter = 0;
for (int i = 0; i < A.length; ++i) {
int value = A[i];
if(value >= mark.length) {
return NOT_PERMUTATION;
}
if(mark[value] == 0) {
mark[value]=1;
++counter;
} else {
return NOT_PERMUTATION;
}
}
return counter == A.length ? PERMUTATION : NOT_PERMUTATION;
}
My Solution:
public int PermSolution(int[] A)
{
int perm = 1;
Arrays.sort(A);
if (A[0] != 1) return 0;
for (int i = 0; i < A.length; i++)
{
if (A[i] + 1 == A[i + 1])
{
return perm;
}
if (A[i] + 1 != A[i + 1])
{
return 0;
}
}
return perm;
}

Using Arrays.sort() is kind of original, that's not how I would have done it though.
To comment your code, it's probably isn't working because of this : return perm;
Let's say you have this Array which is not a permutation:
A[0] = 4
A[1] = 1
A[2] = 2
One you execute Arrays.sort(A), you'll have this :
A[0] = 1
A[1] = 2
A[2] = 4
Now let's execute your code :
if (A[0] != 1) return 0;
A[0] is indeed equal to 1
Next, for i==0 we have :
if (A[i] + 1 == A[i + 1])
{
return perm;
}
A[i] + 1 is equal 2 and A[i+1] is also equal to 2
the condition being true, you execute a return perm; and thus, you end your execution with a return 1.
Actually, as long as your array contains 1 and 2, this function will always return 1
For it to work, you'll have to check all of the array before actually returning a value.
This should work :
public int PermSolution(int[] A)
{
int perm = 1;
Arrays.sort(A);
if (A[0] != 1) return 0;
for (int i = 0; i < A.length; i++)
{
if (A[i] + 1 != A[i + 1])
{
return 0;
}
}
return perm;
}
To optimize it even further, this should work as well :
public int PermSolution(int[] A)
{
Arrays.sort(A);
for (int i = 0; i < A.length; i++)
{
if (A[i] != i+1)
{
return 0;
}
}
return 1;
}

Why don't we avoid Arrays.sort(A) in order to gain the computation efficiency by below:
public static int PermSolution(int[] A)
{
int len=A.length;
if(len==1)
return A[0]==1 ? 1 : 0;
BitSet set=new BitSet(len+2);
for (int i = 0; i < len; i++)
{
if(A[i]>len || set.get(A[i]))
return 0;
set.set(A[i]);
}
return set.nextClearBit(1)==(len+1) ? 1 : 0;
}

Here is some solution that I have developed. Not sure about constraints, if someone can help to test it against them. Thanks people!
private static int solution(int[] arr) {
int perm=1;
boolean b=false;
Arrays.sort(arr);
int i=0;
while (i<=arr.length) {
if(i < arr.length-2)
b = arr[i+1]-1 == (arr[i]);
if(b) {
System.out.println("if " + i);
i++;
perm=1;
}else {
System.out.println("else " + i);
perm = 0;
break;
}
}
return perm;
}

Related

how to determine if a number is a smart number in java?

I have this question I am trying to solve. I have tried coding for the past 4 hours.
An integer is defined to be a Smart number if it is an element in the infinite sequence
1, 2, 4, 7, 11, 16 …
Note that 2-1=1, 4-2=2, 7-4=3, 11-7=4, 16-11=5 so for k>1, the kth element of the sequence is equal to the k-1th element + k-1. For example, for k=6, 16 is the kth element and is equal to 11 (the k-1th element) + 5 ( k-1).
Write function named isSmart that returns 1 if its argument is a Smart number, otherwise it returns 0. So isSmart(11) returns 1, isSmart(22) returns 1 and isSmart(8) returns 0
I have tried the following code to
import java.util.Arrays;
public class IsSmart {
public static void main(String[] args) {
// TODO Auto-generated method stub
int x = isSmart(11);
System.out.println(x);
}
public static int isSmart(int n) {
int[] y = new int[n];
int j = 0;
for (int i = 1; i <= n; i++) {
y[j] = i;
j++;
}
System.out.println(Arrays.toString(y));
for (int i = 0; i <= y.length; i++) {
int diff = 0;
y[j] = y[i+1] - y[i] ;
y[i] = diff;
}
System.out.println(Arrays.toString(y));
for (int i = 0; i < y.length; i++) {
if(n == y[i])
return 1;
}
return 0;
}
}
When I test it with 11 it is giving me 0 but it shouldn't. Any idea how to correct my mistakes?
It can be done in a simpler way as follows
import java.util.Arrays;
public class IsSmart {
public static void main(String[] args) {
int x = isSmart(11);
System.out.println("Ans: "+x);
}
public static int isSmart(int n) {
//------------ CHECK THIS LOGIC ------------//
int[] y = new int[n];
int diff = 1;
for (int i = 1; i < n; i++) {
y[0] =1;
y[i] = diff + y[i-1];
diff++;
}
//------------ CHECK THIS LOGIC ------------//
System.out.println(Arrays.toString(y));
for (int i = 0; i < y.length; i++) {
if(n == y[i])
return 1;
}
return 0;
}
}
One of the problems is the way that your populating your array.
The array can be populated as such
for(int i = 0; i < n; i++) {
y[i] = (i == 0) ? 1 : y[i - 1] + i;
}
The overall application of the function isSmart can be simplified to:
public static int isSmart(int n) {
int[] array = new int[n];
for(int i = 0; i < n; i++) {
array[i] = (i == 0) ? 1 : array[i - 1] + i;
}
for (int i = 0; i < array.length; i++) {
if (array[i] == n) return 1;
}
return 0;
}
Note that you don't need to build an array:
public static int isSmart(int n) {
int smart = 1;
for (int i = 1; smart < n; i++) {
smart = smart + i;
}
return smart == n ? 1 : 0;
}
Here is a naive way to think of it to get you started - you need to fill out the while() loop. The important thing to notice is that:
The next value of the sequence will be the number of items in the sequence + the last item in the sequence.
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
System.out.println(isSmart(11));
}
public static int isSmart(int n) {
ArrayList<Integer> sequence = new ArrayList<Integer>();
// Start with 1 in the ArrayList
sequence.add(1);
// You need to keep track of the index, as well as
// the next value you're going to add to your list
int index = 1; // or number of elements in the sequence
int nextVal = 1;
while (nextVal < n) {
// Three things need to happen in here:
// 1) set nextVal equal to the sum of the current index + the value at the *previous* index
// 2) add nextVal to the ArrayList
// 3) incriment index by 1
}
// Now you can check to see if your ArrayList contains n (is Smart)
if (sequence.contains(n)) { return 1; }
return 0;
}
}
First think of a mathematical solution.
Smart numbers form a sequence:
a0 = 1
an+1 = n + an
This gives a function for smart numbers:
f(x) = ax² + bx + c
f(x + 1) = f(x) + x = ...
So the problem is to find for a given y a matching x.
You can do this by a binary search.
int isSmart(int n) {
int xlow = 1;
int xhigh = n; // Exclusive. For n == 0 return 1.
while (xlow < xhigh) {
int x = (xlow + xhigh)/2;
int y = f(x);
if (y == n) {
return 1;
}
if (y < n) {
xlow = x + 1;
} else {
xhigh = x;
}
}
return 0;
}
Yet smarter would be to use the solution for x and look whether it is an integer:
ax² + bx + c' = 0 where c' = c - n
x = ...
I was playing around with this and I noticed something. The smart numbers are
1 2 4 7 11 16 22 29 ...
If you subtract one you get
0 1 3 6 10 15 21 28 ...
0 1 2 3 4 5 6 7 ...
The above sequence happens to be the sum of the first n numbers starting with 0 which is n*(n+1)/2. So add 1 to that and you get a smart number.
Since n and n+1 are next door to each other you can derive them by reversing the process.
Take 29, subtract 1 = 28, * 2 = 56. The sqrt(56) rounded up is 8. So the 8th smart number (counting from 0) is 29.
Using that information you can detect a smart number without a loop by simply reversing the process.
public static int isSmart(int v) {
int vv = (v-1)*2;
int sq = (int)Math.sqrt(vv);
int chk = (sq*(sq+1))/2 + 1;
return (chk == v) ? 1 : 0;
}
Using a version which supports longs have verified this against the iterative process from 1 to 10,000,000,000.

Array Manipulation : HackerRank Questions : JAVA

I am doing this Array Manipulation problem from hackerrank and it tells me compile error is Terminated due to timeout.
For small arrays my method work perfectly. This error only happens for bigger array values.
Here is the question link. Question Here
Starting with a 1-indexed array of zeros and a list of operations, for each operation add a value to each of the array element between two given indices, inclusive. Once all operations have been performed, return the maximum value in your array.
For example, the length of your array of zeros . Your list of queries is as follows:
a b k
1 5 3
4 8 7
6 9 1
Add the values of between the indices and inclusive:
index -> 1 2 3 4 5 6 7 8 9 10
[0,0,0, 0, 0,0,0,0,0, 0]
[3,3,3, 3, 3,0,0,0,0, 0]
[3,3,3,10,10,7,7,7,0, 0]
[3,3,3,10,10,8,8,8,1, 0]
The largest value is after all operations are performed.
Given below is my method.
static long arrayManipulation(int n, int[][] queries) {
long max = 0L;
long[] arr = new long[n];
for (int i = 0; i < n; i++) {
arr[i] = 0L;
}
for (int i = 0; i < queries.length; i++) {
int[] q = queries[i];
int start = q[0] - 1;
int end = q[1] - 1;
int val = q[2];
long tempMax = updateVal(start, end, val, arr);
if (tempMax > max) {
max = tempMax;
}
}
return max;
}
static long updateVal(int start, int end, int val, long[] arr) {
long max = 0L;
for (int i = start; i <= end; i++) {
arr[i] = arr[i] + val;
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
Given below are few test classes that doesn't work with my code.
Test1 Test2 Test3
Please help me to figure this out. I searched for lots of answers based on java.
But I couldn't understand them.
This is my last resort. Please help.
Updated after Kanahaiya's answer
static long arrayManipulation(int n, int[][] queries) {
long max = 0L;
int a, b, k;
int[] arr = new int[n + 2];
for (int i = 0; i < queries.length; i++) {
a = queries[i][0];
b = queries[i][1];
k = queries[i][2];
for (int j = 0; j < arr.length; j++) {
if (j >= a) {
arr[j] = arr[j] + k;
}
if (j > b) {
arr[j] = arr[j] - k;
}
}
}
Arrays.sort(arr);
max = arr[arr.length - 1];
return max;
}
Brute-force solution is not going to work here due to the given time constraint.
That is the reason you will get the time out error.
So you need to optimize your code which can be done with the help of prefix sum array.
instead of adding k to all the elements within a range from a to b in an array, accumulate the difference array
Whenever we add anything at any index into an array and apply prefix sum algorithm the same element will be added to every element till the end of the array.
ex- n=5, m=1, a=2 b=5 k=5
i 0.....1.....2.....3.....4.....5.....6 //take array of size N+2 to avoid index out of bound
A[i] 0 0 0 0 0 0 0
Add k=5 to at a=2
A[a]=A[a]+k // start index from where k element should be added
i 0.....1.....2.....3.....4.....5.....6
A[i] 0 0 5 0 0 0 0
now apply prefix sum algorithm
i 0.....1.....2.....3.....4.....5.....6
A[i] 0 0 5 5 5 5 5
so you can see K=5 add to all the element till the end after applying prefix sum but we don't have to add k till the end. so to negate this effect we have to add -K also after b+1 index so that only from [a,b] range only will have K element addition effect.
A[b+1]=A[b]-k // to remove the effect of previously added k element after bth index.
that's why adding -k in the initial array along with +k.
i 0.....1.....2.....3.....4.....5.....6
A[i] 0 0 5 0 0 0 -5
Now apply prefix sum Array
i 0.....1.....2.....3.....4.....5.....6
A[i] 0 0 5 5 5 5 0
You can see now K=5 got added from a=2 to b=5 which was expected.
Here we are only updating two indices for every query so complexity will be O(1).
Now apply the same algorithm in the input
# 0.....1.....2.....3.....4.....5.....6 //taken array of size N+2 to avoid index out of bound
5 3 # 0 0 0 0 0 0 0
1 2 100 # 0 100 0 -100 0 0 0
2 5 100 # 0 100 100 -100 0 0 -100
3 4 100 # 0 100 100 0 0 -100 -100
To calculate the max prefix sum, accumulate the difference array to 𝑁 while taking the maximum accumulated prefix.
After performing all the operation now apply prefix sum Array
i 0.....1.....2.....3.....4.....5.....6
A[i] 0 100 200 200 200 100 0
Now you can traverse this array to find max which is 200.
traversing the array will take O(N) time and updating the two indices for each query will take O(1)* number of queries(m)
overall complexity=O(N)+O(M)
= O(N+M)
it means = (10^7+10^5) which is less than 10^8 (per second)
Note: If searching for video tutorial , you must check it out here for detailed explanation.
First of all, in case you don't realize it, Terminated due to timeout is not a compilation error, it means that your implementation is too slow. The challenge is not to implement any correct solution to the problem. The solution must also be efficient. Since your solution is inefficient, it fails for large inputs due to being too slow.
Since the number of queries seems to be 2 orders of magnitude smaller than the length of the array (100K vs. 10M in the 3 test cases you posted), it would be more efficient to work just with the queries instead of actually updating the array.
I'm not going to give you an implementation, but I'll suggest an algorithm that should be more efficient than your current implementation.
I suggest you process the queries as follows:
Add the first query to a list of processed queries, which will contain queries with disjoint sub-array ranges. This list will be sorted by the first array index (you will keep it sorted by adding new elements in the proper position).
For each query not processed yet, find all the processed queries that overlap it (you can do it using binary search to improve performence).
Split the current query in a way that the resulting queries will each be either fully contained in an existing processed query or not contained in each existing processed query.
For each of the queries created in the split:
if their range is equal to the range of an existing processed query, add the value of the query to the processed query.
If their range is not contained in any existing processed query, add that query as a new processed query.
If their range is partially contained in an existing processed query, split the processed query.
I'm not sure if my explanation is clear enough. I'll show an example with the
1 5 3
4 8 7
6 9 1
input:
Add 1 5 3 to the list of processed queries.
Process 4 8 7: There is one processed query the overlaps it - 1 5 3.
Split 4 8 7 into two sub-queries : 4 5 7 and 6 8 7.
4 5 7 is contained in 1 5 3, so split 1 5 3 into 1 3 3 and 4 5 3+7
6 8 7 is not contained in any processed queries, so add it as is.
Now the processed queries are:
1 3 3
4 5 10
6 8 7
Process 6 9 1: There is one processed query that overlaps it: 6 8 7.
Split 6 9 1 into two sub queries : 6 8 1 and 9 9 1.
6 8 1 has the same range a 6 8 7, which will become 6 8 7+1
9 9 1 is not contained in any processed queries, so add it as is.
Now the processed queries are:
1 3 3
4 5 10
6 8 8
9 9 1
As you process the queries you keep track of the max processed query value, so after you process all the queries you know that the max value is 10.
static long arrayManipulation(int n, int[][] queries)
{
// To Avoid "Index was outside the bounds of the array." exception
long[] numbers = new long[n + 1];
for(int i = 0; i < queries.length; i++)
{
int a = queries[i][0] - 1;
int b = queries[i][1];
int k = queries[i][2];
numbers[a] += k;
numbers[b] -= k;
}
// Calculate sum(s)
int max=0;
for(int i = 1; i < numbers.length; i++)
{
numbers[i] += numbers[i - 1];
if(numbers[i]>max)
{
max=numbers[i];
}
}
return max;
}
import java.io.*;
import java.util.InputMismatchException;
import java.util.Random;
public class Solution {
public static void main(String[] args) {
InputStream inputStream = System.in;
InputReader in = new InputReader(inputStream);
int n = in.readInt();
int m = in.readInt();
long[] list = new long[n+3];
while(m-- > 0) {
int a = in.readInt();
int b = in.readInt();
long k = in.readLong();
list[a] += k;
list[b+1] -= k;
}
long max = 0;
long c = 0;
for (int i = 1; i <= n; i++) {
c += list[i];
max = Math.max(max, c);
}
System.out.println(max);
}
}
class InputReader {
private InputStream stream;
private byte[] buf = new byte[1024];
private int curChar;
private int numChars;
private SpaceCharFilter filter;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int read() {
if (numChars == -1)
throw new InputMismatchException();
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
} catch (IOException e) {
throw new InputMismatchException();
}
if (numChars <= 0)
return -1;
}
return buf[curChar++];
}
public int peek() {
if (numChars == -1)
return -1;
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
} catch (IOException e) {
return -1;
}
if (numChars <= 0)
return -1;
}
return buf[curChar];
}
public int readInt() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
int res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
public long readLong() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
long res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
public boolean isSpaceChar(int c) {
if (filter != null)
return filter.isSpaceChar(c);
return isWhitespace(c);
}
public static boolean isWhitespace(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
public boolean isExhausted() {
int value;
while (isSpaceChar(value = peek()) && value != -1)
read();
return value == -1;
}
public interface SpaceCharFilter {
public boolean isSpaceChar(int ch);
}
}
Implemented the solution in Java for this problem and its working efficiently. Please try if you needed.
public long arrayManipulation(int n, int[][] queries)
{
if(n==0 || queries==null || queries.length==0){
return -1;
}
long[] computation = new long[n];
for (int i = 0; i < queries.length; i++) {
int a = queries[i][0] - 1;
int b = queries[i][1] - 1;
int k = queries[i][2];
computation[a] += k;
if (b + 1 < n ) {
computation[b + 1] -= k;
}
}
long max = 0; long sum = 0;
for (int i = 0; i < n; i++) {
sum += computation[i];
max = Math.max(max, sum);
}
return max;
}
package arrayProblems;
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.*;
public class ArrayManipuations {
public static void main(String[] args) {
int n=10;
int[] arr = new int[n];
List<List<Integer>> nl = new ArrayList<List<Integer>>();
nl=asList(asList(1,5,3),asList(4,8,7),asList(6,9,1));
for(int i=0;i<nl.size();i++) {
for(int j=nl.get(i).get(0);j<=nl.get(i).get(1);j++) {
arr[j-1]=arr[j-1]+nl.get(i).get(2);
}
}
int max = Integer.MIN_VALUE;
for(int k=0;k<n;k++) {
if(max<arr[k]) {
max = arr[k];
arr[k]=max;
}
}
System.out.print(max);
}
}
solution in java for Array Manipulation hackerank ...
code does not pass all the cases because of timeout need suggestions to improve
static long arrayManipulation(int n, int[][] queries) {
ArrayList<Long> list = new ArrayList<Long>(n);
for(int i=0; i<n; i++){
list.add(i,0l);
}
for(int i=0; i<queries.length; i++){
int s = queries[i][0];
int e = queries[i][1];
long k = queries[i][2];
int size = 0;
for(int j = s - 1; j<e; j++){
list.set(j, list.get(j) + k);
}
}
long max =Collections.max(list);
return max;
}

How to improve the algorithm for the Max Common Array Slice?

I was asked to take a HackerRank code test, and the exercise I was asked is the Max Common Array Slice. The problem goes as follows:
You are given a sequence of n integers a0, a1, . . . , an−1 and the
task is to find the maximum slice of the array which contains no more
than two different numbers.
Input 1 :
[1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]
Result 1 : Answer is 10 because the array slice of (0, 9) is the
largest slice of the array with no more than two different numbers.
There are 10 items in this slice which are "1, 1, 1, 2, 2, 2, 1, 1, 2, 2".
2 different numbers for this slice are 1 and 2.
Input 2:
[53, 800, 0, 0, 0, 356, 8988, 1, 1]
Result 2: Answer is 4 because the slice of (1, 4) is the largest slice
of the array with no more than two different numbers. The slice (2, 5)
would also be valid and would still give a result of 4.
There are 4 items in this slice which are "800,0,0,0".
2 different numbers for this slice are 800 and 0.
Maximum common array slice of the array which contains no more than
two different numbers implementation in Java takes a comma delimited
array of numbers from STDIN and the output is written back to console.
The implementation I provide (below) works, however 3 test cases timeout in HR. Clearly, HR hides the test cases, so I could not see exactly the conditions the timeout was triggered or even the length of the timeout.
I'm not surprised of the timeout, though, given the asymptotic complexity of my solution. But my question is: how could my solution be improved?
Thanks in advance to all those that will help!
import java.io.*;
import java.lang.*;
import java.util.*;
import java.util.stream.*;
public class Solution {
public static void main(String args[] ) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
List<Integer> inputSequence = parseIntegerSequence(line);
int largestSliceSize = calculateLargestSlice(inputSequence);
System.out.println(largestSliceSize);
}
private static List<Integer> parseIntegerSequence(String input) {
if (input == null)
return new ArrayList();
return Arrays.asList(input.split("\\s*,\\s*"))
.stream()
.filter(item -> item.matches("^\\s*-?[0-9]+\\s*$"))
.map(item -> Integer.parseInt(item))
.collect(Collectors.toList());
}
private static int calculateLargestSlice(List<Integer> inputSequence) {
Map<Integer, Integer> temporaryMap = new HashMap<>();
int result = 0;
int startIndex = 0;
int uniqueItemCount = 0;
Integer[] array = inputSequence.toArray(new Integer[inputSequence.size()]);
while (startIndex < array.length) { // loop over the entire input sequence
temporaryMap.put(array[startIndex], startIndex);
uniqueItemCount++;
for (int j = startIndex + 1; j < array.length; j++) {
if (temporaryMap.get(array[j]) == null) {
if (uniqueItemCount != 2) {
temporaryMap.put(array[j], j);
uniqueItemCount++;
if (j == array.length - 1) {
result = Math.max(result, j - startIndex + 1);
startIndex = array.length;
break;
}
} else {
result = Math.max(result, j - startIndex);
int item = array[j-1];
int firstFoundIndex = 0;
for( int k=j-1; k>=0; k-- )
{
if( array[k] != item )
{
firstFoundIndex = k+1;
break;
}
}
startIndex = firstFoundIndex;
temporaryMap.clear();
uniqueItemCount = 0;
break;
}
} else if (temporaryMap.get(array[j]) != null) {
if (j == array.length - 1) {
result = Math.max(result, j - startIndex + 1);
startIndex = array.length;
break;
}
}
}
}
return result;
}
}
This is my answer in Java and it passed all the HackerRank test cases. Please feel free to comment if you find something wrong.
public static int maxCommonArraySlice(List<Integer> inputSequence) {
if(inputSequence.size() < 2) return inputSequence.size(); // I'm doubting this line should be <= 2
List<Integer> twoInts = new LinkedList<>();
twoInts.add(inputSequence.get(0));
int start = 0;
int end = inputSequence.size();
int count = 0;
int max_length = 0;
while(start < end) {
if(twoInts.contains(inputSequence.get(start))) {
count++;
start++;
}
else if(twoInts.size() == 1) {
twoInts.add(inputSequence.get(start));
}
else { // twoInts.size() is 2
count = 0;
start--;
twoInts.set(0, inputSequence.get(start));
twoInts.set(1, inputSequence.get(start + 1));
}
if(count > max_length) {
max_length = count;
}
}
return max_length;
}
public static void main(String[] args) {
List<Integer> input = new LinkedList<Integer>(Arrays.asList(53,800,0,0,0,356,8988,1,1));
System.out.println(maxCommonArraySlice(input));
}
I think this would work:
public int solution(int[] arr) {
int lastSeen = -1;
int secondLastSeen = -1;
int lbs = 0;
int tempCount = 0;
int lastSeenNumberRepeatedCount = 0;
for (int current : arr) {
if (current == lastSeen || current == secondLastSeen) {
tempCount ++;
} else {
// if the current number is not in our read list it means new series has started, tempCounter value in this case will be
// how many times lastSeen number repeated before this new number encountered + 1 for current number.
tempCount = lastSeenNumberRepeatedCount + 1;
}
if (current == lastSeen) {
lastSeenNumberRepeatedCount++;
} else {
lastSeenNumberRepeatedCount = 1;
secondLastSeen = lastSeen;
lastSeen = current;
}
lbs = Math.max(tempCount, lbs);
}
return lbs;
}
Reference
This is a python solution, as per requested by OP
def solution(arr):
if (len(arr) <= 2): print arr
lres = 0
rres = 0
l = 0
r = 1
last = arr[1]
prev = arr[0]
while(r <= len(arr)-1):
if prev != last:
if arr[r] == prev:
prev = last
last = arr[r]
elif arr[r] != last:
l = r-1
while(arr[l-1] == last):
l -= 1
last = arr[r]
prev = arr[r-1]
else:
if arr[r] != prev:
last = arr[r]
if r - l > rres-lres:
rres = r
lres = l
r += 1
print arr[lres:rres+1]
For current segment let's say that last is the last value added and prev is the second distinct value in the segment. (initially they might be equal).
Let's keep to pointers l and r to left and right ends of the current segment with at most two distinct elements. And let's say we consider element arr[r].
If current segment [l,r-1] contains only one distinct element, we can safely add arr[r], with possibly updating last and prev.
Now if arr[r] equals to last, then we don't need to do anything. If arr[r] equals to prev, we need to swap prev and last. If it equals to neither of those two, we need to update l left pointer, by tracing back from r-1 until we find an element which is not equal to last, then update last and prev.

Codility PermCheck Solution isn't working on a few data sets

Trying to solve codility lessons for practice and working on this.
Written my code in Java and tested the code on a wide range of inputs, however the code fails for extreme_min_max, single and double in the codility test results.
Assumption given:
N is an integer within the range [1..100,000].
Each element of array A is an integer within the range [1..1,000,000,000].
Explanation of my code:
1. Sort the given array.
2. Iterate over each element in the array to find the difference between every consecutive pair. If the difference is not 1, Then its not a perm hence return 0. In case there is only one element in the array, return 1.
Can anyone please help me find out the bug(s) in my code?
My code:
public int solution(int[] A)
{
if(A.length == 1)
return 1;
Arrays.sort(A);
for (int i = 0; i < A.length-1; i++)
{
long diff = Math.abs(A[i] - A[i+1]);
if(diff!=1)
return 0;
}
return 1;
}
Here is simple and better implementation which runs in O(N) time complexity and takes O(N) space complexity.
public int solution(int[] A)
{
int size = A.length;
int hashArray[] = new int[size+1];
for (int i = 0; i < size; i++)
{
if(A[i]>size)
return 0;
else
hashArray[A[i]]+=1;
}
for(int i=1;i<=size;i++)
if(hashArray[i]!=1)
return 0;
return 1;
}
Try this in C# (Score 100%) :
using System;
using System.Linq;
class Solution {
public int solution(int[] A) {
if (A.Any(x => x == 0)) { return 0; }
var orderSelect = A.OrderBy(x => x).GroupBy(x => x);
if (orderSelect.Any(x => x.Count() > 1)) { return 0; }
var res = Enumerable.Range(1, A.Length).Except(A);
return res.Any() ? 0 : 1;
}
}
Pretty simple:
Your code doesn't check this condition:
A permutation is a sequence containing each element from 1 to N once, and only once.
Ensure that the first element after sorting is 1, and everything should work.
I'm not big on Java syntax, but what you want to do here is:
Create an array temp the length of A - initialized to 0.
Go over A and do temp[A[i]]++.
Go over temp, and if any place in the array is not 1, return false.
If duplicate exists - return 0 I have implemented with 100% pass
https://codility.com/demo/results/trainingWX2E92-ASF/
public static int permCheck(int A[]){
Set<Integer> bucket = new HashSet<Integer>();
int max = 0;
int sum=0;
for(int counter=0; counter<A.length; counter++){
if(max<A[counter]) max=A[counter];
if(bucket.add(A[counter])){
sum=sum+A[counter];
}
else{
return 0;
}
}
System.out.println(max+"->"+sum);
int expectedSum = (max*(max+1))/2;
if(expectedSum==sum)return 1;
return 0;
}
Here's my first 100% code.
I can't say if it's the fastest but it seems all correct -- watch the double OR ( || ) condition.
import java.util.Arrays;
class Solution
{
public int solution(int[] A)
{
int i = 0;
int size = A.length;
if ( size > 0 && size < 100001)
{
// Sort the array ascending:
Arrays.sort(A);
// Check each element:
for(i = 0; i < size; i++)
if ( A[i] > size || A[i] != (i + 1) )
return 0;
return 1;
}
return 0;
}
}
EDIT
Actually, we need not worry about valid first element data (i.e. A[i] > 0) because, after sorting, a valid perm array must have A[0] = 1 and this is already covered by the condition A[i] = i + 1.
The upper limit for array entries (> 1,000,000,000) is restricted further by the limit on the array size itself (100,000) and we must check for conformity here as there will be a Codility test for this. So I have removed the lower limit condition on array entries.
Below code runs and gave me a 100%, the time complexity is O(n):
private static int solution(int[] A) {
int isPermutation = 1; // all permutations start at 1
int n = A.length;
Arrays.sort(A);
if (n == 0) return 0; // takes care of edge case where an empty array is passed
for (int i = 0; i < n; i++) {
if (A[i] != isPermutation) { //if current array item is not equals to permutation, return 0;
return 0;
}
isPermutation++;
}
return 1;
}
100% score with complexity O(N)
public int solution(int[] A) {
int res = 1;
if (A.length == 1 && A[0]!=1)
return 0;
int[] B = new int[A.length];
for (int j : A) {
int p = j - 1;
if (A.length > p)
B[p] = j;
}
for (int i = 0; i < B.length - 1; i++) {
if (B[i] + 1 != B[i + 1]) {
res = 0;
break;
}
}
return res;
}

HeapSort Algorithm Indexed 1 through n, and actual code has to be from 0 to n-1

I'm kind of new to algorithms and wanted to implement heap sort algorithm.
The algorithm is given as follows:
Parent(i)
return Math.floor(i/2)
Left(i)
return 2i
Right(i)
return 2i+1
Then there is HEAPIFY method that restores the heep property. Algorithm is as follows:
HEAPIFY(A, i)
l = Left(i)
r = Right(i)
if (l <= heap-size[A] and A[l] > A[i]
then largest = l
else largest = i
if r <= heap-size[A] and A[r] > A[largest]
then largest = r
if largest != i
then exchange A[i] <-> A[largest]
HEAPIFY(A, largest)
My Code that implements this method is:
public static void HEAPIFY(int[] A, int i) {
int l = LEFT(i);
int r = RIGHT(i);
int largest = 0;
if (l < A.length && A[l] > A[i]) {
largest = l;
} else {
largest = i;
}
if (r < A.length && A[r] > A[largest]) {
largest = r;
}
if (largest != i) {
int temp = A[i];
A[i] = A[largest];
A[largest] = temp;
HEAPIFY(A, largest);
}
}
Now My question is in the book algorithm is shown by drawing the tree of heap and array
so for example array is: [16,14,10,8,7,9,3,2,4,1] and for the tree and also for array it is indexed starting from 1 to n, so Array[1] = 16 and in coding Array[0] = 16. Now i can not adjust the heapify method to start either from index 1 and go up to 1 or somehow make it start from 0 and let the heap be indexed from 0 to n-1.
Sorry if its kind of confusing i'm still confused but i would really appreciate some help.
Thank you guys
Now HEAPIFY works and the following code is code to build the heap:
public static void BUILD_HEAP(int[] A) {
heapSize = A.length;
for (int i = (int) Math.floor(A.length / 2.0); i >= 0; i--) {
HEAPIFY(A, i);
}
}
build heap also works and the only method that doesnot work is heapsort.
public static void HEAPSORT(int[] A) {
BUILD_HEAP(A);
for (int i = A.length-1; i >= 1; i--) {
int temp = A[0];
A[0] = A[i];
A[i] = temp;
heapSize = heapSize-1;
HEAPIFY(A,0);
}
}
this has to sort but when i try to traverse the array after the call of heapsort it does not give the sorted array.
any ideas how to fix heapsort?
Parent(i) return Math.floor(i/2)
=> Parent(i) return Math.floor((i - 1) / 2)
Left(i) return 2i
=> Left(i) return 2i + 1
Right(i) return 2i+1
=> Right(i) return 2i + 2
You can work this out either by fiddling around (which is what I actually did) or considering j = i - 1.
If i' = 2 i and j = i - 1 so i = j + 1
j' = i' - 1 = (2i) - 1 = (2(j + 1)) - 1 = 2j + 1
if you want to start form index 1,then you can initialize the array like this:
[-x,16,14,10,8,7,9,3,2,4,1] -x is the array[0],in other words,you can ignore the element which is in array[0].
if you want to start form index 0,then you have to modify the function LEFT(i) and RIGHT(i).
LEFT(i) return 2*i+1;
RIGHT(i) return 2*i+2;

Categories

Resources