Related
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.
I have solved the hackerrank Sock Merchant problem But I want to reduce the complexity of the code(I am not sure that it is possible or not).
John works at a clothing store. He has a large pile of socks that he must pair by color for sale. Given an array of integers representing the color of each sock, determine how many pairs of socks with matching colors there are.
For example, there are n=7 socks with colors ar= [1,2,1,2,1,3,2]. There is one pair of color 1 and one of color 2. There are three odd socks left, one of each color. The number of pairs is 2.
Function Description
Complete the sockMerchant function in the editor below. It must return an integer representing the number of matching pairs of socks that are available.
sockMerchant has the following parameter(s):
n: the number of socks in the pile
ar: the colors of each sock
Input Format
The first line contains an integer n, the number of socks represented in ar.
The second line contains n space-separated integers describing the colors ar[i] of the socks in the pile.
Constraints
1 <= n <= 100
1 <= ar[i] <= 100 where 0 <= i < n
Output Format
Return the total number of matching pairs of socks that John can sell.
Sample Input
9
10 20 20 10 10 30 50 10 20
Sample Output
3
My solutions :
package com.hackerrank.test;
public class Solution {
public static void main(String[] args) {
//Initialize array
int[] arr = new int[]{10, 20, 20, 10, 10, 30, 50, 10, 20};
//Array fr will store frequencies of element
System.out.println("---------------------------------------");
System.out.println(" sockMerchant output " + sockMerchant(9, arr));
System.out.println("---------------------------------------");
}
static int sockMerchant(int n, int[] ar) {
int pairs = 0;
int frequencyArray[] = new int[ar.length];
int frequencyTemp = -1;
for (int i = 0; i < ar.length; i++) {
int count = 1;
for (int j = i + 1; j < ar.length; j++) {
if (ar[i] == ar[j]) {
count++;
frequencyArray[j] = frequencyTemp;
}
}
if (frequencyArray[i] != frequencyTemp) {
frequencyArray[i] = count;
}
}
for (int i = 0; i < frequencyArray.length; i++) {
if (frequencyArray[i] != frequencyTemp) {
int divide = frequencyArray[i] / 2;
pairs += divide;
}
}
return pairs;
}
}
And the output is :
---------------------------------------
sockMerchant frequency 3
---------------------------------------
You can solve this in a single pass (O(n)) using a HashSet, which has O(1) put and lookup time. Each element is already in the set, in which case it gets removed and the pair counter is incremented, or it's not, in which case you add it:
int[] arr = new int[]{10, 20, 20, 10, 10, 30, 50, 10, 20};
HashSet<Integer> unmatched = new HashSet<>();
int pairs = 0;
for(int i = 0; i < arr.length; i++) {
if(!unmatched.add(arr[i])) {
unmatched.remove(arr[i]);
pairs++;
}
}
This works for java 8!!
static int sockMerchant(int n, int[] ar) {
Set<Integer> list = new HashSet<Integer>();
int count = 0;
for(int i= 0; i < n; i++){
if(list.contains(ar[i])){
count++;
list.remove(ar[i]);
}
else{
list.add(ar[i]);
}
}
return count;
}
It can also be solved using a dictionary as follows in Swift:
func sockMerchant(n: Int, ar: [Int]) -> Int {
var dictionary: [Int: Int] = [:]
var totalNumberOfPairs: Int = 0
// Store all array elements in a dictionary
// with element as key and occurrence as value
ar.forEach{
dictionary[$0] = (dictionary[$0] ?? 0) + 1
}
// Iterate over the dictionary while checking for occurrence greater or equal 2.
// If found add the integer division of the occurrence to the current total number of pairs
dictionary.forEach { (key, value) in
if value >= 2 {
totalNumberOfPairs = totalNumberOfPairs + (value / 2)
}
}
return totalNumberOfPairs
}
Here my solution with JAVA for Sock Merchant test on HackerRank
import java.io.*;
import java.util.*;
public class sockMerchant {
public static void main(String[] args) {
Scanner en = new Scanner(System.in);
int n=en.nextInt();
int[] hash = new int[300];
for(int i=0; i<n; i++){
hash[en.nextInt()]++;
}
long res=0;
for(int f: hash){
res+=f/2;
}
System.out.println(res);
}
}
Py3 solution for the problem using dictionaries
def sockMerchant(n, ar):
pair = 0
d = {}
for i in ar:
if i in d:
d[i] += 1
if i not in d:
d[i] = 1
print(d)
for x in d:
u = d[x]//2
pair += u
return pair
Code for python 3
n = 9
ar = [10, 20, 20, 10, 10, 30, 50, 10, 20]
def sockMerchant(n, ar):
totalpair = 0
test= list(set(ar))
for i in test:
pair = 0
for j in ar:
if i==j:
pair+=1
if pair>=2:
totalpair=totalpair+int(pair/2)
return totalpair
print(sockMerchant(n,ar))
We can use a Hash Table, for it. As Hash Table's Complexity is O(1)
Look at below code snippet, i created a dictionary in python i.e. Hash Table having key and value. In dictionary, there only exists a unique Key for each value. So, at start dictionary will be empty. We will loop over the provided list and check values in dictionary keys. If that value is not in dictionary key, it means it is unique, add it to the dictionary. if we find value in dictionary key, simply increment pairs counter and remove that key value pair from hash table i.e. dictionary.
def sockMerchant(n, ar):
hash_map = dict()
pairs = 0
for x in range(len(ar)):
if ar[x] in hash_map.keys():
del hash_map[ar[x]]
pairs += 1
else:
hash_map.setdefault(ar[x])
return pairs
This is my simple code for beginners to understand using c++ which prints the count of numbers of pair in the user-defined vector:
#include <bits/stdc++.h>
using namespace std;
vector<string> split_string(string);
// Complete the sockMerchant function below.
int sockMerchant(int n, vector<int> ar) {
int count=0;
vector<int> x;
for(int i=0;i<n;i++){
if(ar[i]!=0)
{
for(int j=i+1;j<n;j++)
{
if(ar[i]==ar[j]){
count++;
ar[j]=0;
break;
}
}}
}
return count;
}
int main()
{
int a,b;
vector<int> v;
cin>>a;
for(int i=0;i<a;i++){
cin>>b;
v.push_back(b);
}
cout<<sockMerchant(a,v);
}
function sockMerchant(n, ar) {
//Need to initiate a count variable to count pairs and return the value
let count = 0
//sort the given array
ar = ar.sort()
//loop through the sorted array
for (let i=0; i < n-1; i++) {
//if the current item equals to the next item
if(ar[i] === ar[i+1]){
//then that's a pair, increment our count variable
count++
//also increment i to skip the next item
i+=1
}
}
//return the count value
return count
}
sockMerchant(9, [10, 20, 20, 10, 10, 30, 50, 10, 20])
For Javascript
function sockMerchant(n, ar) {
// Create an initial variable to hold the pairs
let pairs = 0;
// create an object to temporarily assign pairs
const temp = {};
// loop through the provided array
for (let n of ar) {
// check if current value already exist in your temp object
if (temp[n] in temp) {
// if current value already exist in temp
// delete the value and increase pairs
delete temp[n];
pairs += 1;
} else {
// else add current value to the object
temp[n] = n;
}
}
// return pairs
return pairs;
}
package com.java.example.sock;
import java.io.IOException;
/**
*
* #author Vaquar Khan
*
*/
public class Solution1 {
// Complete the sockMerchant function below.
/*
* John works at a clothing store. He has a large pile of socks that he must pair by color for sale. Given an array of integers representing the color of each sock, determine how many pairs
* of socks with matching colors there are.
* For example, there are socks with colors . There is one pair of color and one of color . There are three odd socks left, one of each color. The number of pairs is .
*/
static int sockMerchant(int n, int[] ar) {
int counter = 0;
int count = 0;
//
for (int i = 0; i < ar.length; i++) {
count = 1;
//
for (int j = i + 1; j < ar.length; j++) {
if (ar[i] == ar[j]) {
count++;
}
}
if (count % 2 == 0) {
counter++;
}
}
return counter;
}
public static void main(String[] args) throws IOException {
int array[] = { 10, 20, 20 ,10 ,10, 30, 50, 10 ,20};
System.out.println(sockMerchant(9, array));
}
}
Refer below one using HashMap and having complexity O(1)
static int sockMerchant(int n, int[] ar) {
int pairs=0;
Map<Integer, Integer> map = new HashMap<>();
for(int i=0;i<n;i++){
if(map.containsKey(ar[i])){
int count=map.get(ar[i]);
map.put(ar[i],++count);
}
else{
map.put(ar[i],1);
}
}
for(int i : map.values()){
pairs=pairs+(i/2);
}
return pairs;
}
static int sockMerchant(int n, int[] ar) {
int pairs = 0;
for (int i = 0; i < ar.length; i++) {
int counter = 0;
for (int j = 0; j < ar.length; j++) {
if (j < i && ar[j] == ar[i]) break;
if(ar[j]==ar[i]) counter++;
}
pairs+=counter/2;
}
return pairs;
}
def sockMerchant(n, ar):
socks = dict()
pairs = 0
for i in ar:
if i in socks:
socks[i] = socks[i]+1
if i not in socks:
socks[i] = 1
if socks[i]%2 == 0:
pairs += 1
return pairs
This problem can be done easily with a hashset. We can take advantage of the HashSet's ability to not store duplicate elements. Here is the code below.
Set<Integer> set = new HashSet<>();
int pairCount = 0;
for(int i = 0; i < arr.length; i++) {
if(set.add(a[i])
set.add(a[i])
else {
pairCount++;
set.remove(a[i]);
}
}
return pairCount;
/*
* Complete the 'sockMerchant' function below.
*
* The function is expected to return an INTEGER.
* The function accepts following parameters:
* 1. INTEGER n
* 2. INTEGER_ARRAY ar
*/
function sockMerchant(n, ar) {
// Write your code here
let count = [];
for (var i = 0; i < ar.length; i++) {
if (count.hasOwnProperty(ar[i])) {
count[ar[i]]++;
}
else {
count[ar[i]] = 1;
}
}
let number = 0;
for (const key in count) {
number += parseInt(count[key] / 2);
}
return number;
}
My answer in C
int sockMerchant(int n, int ar_count, int* ar) {
int matchcounter =0;// each number repeating count
int paircounter=0;//total pair
int size=0;int i,j,k;
bool num_av=false;//number available or not in new array
int numberarray[n];//creating new (same length) array of length n
for(i=0;i<n;i++){
num_av=false;
for(k=0;k<=size;k++){
if(numberarray[k] == ar[i]){
num_av=true;
break;
}
}
if(!num_av){
size+=1;
numberarray[size-1]=ar[i];
for(j=0;j<n;j++){
if(ar[i]==ar[j]){
matchcounter++;
}
}
paircounter += matchcounter/2;
matchcounter=0;
}
}
return paircounter;
}
I wanted to solve this using Array. Here is my solution for Sock Merchant problem on HackerRank (Java 8):
....
import org.apache.commons.lang3.ArrayUtils;
import java.util.Arrays;
class Result {
public static int sockMerchant(int n, List<Integer> ar) {
int[] arr = ar.stream().mapToInt(i->i).toArray();
int counter = 0;
for(int i = 0; i<n; i++) {
if(arr[i]>0) {
int t = arr[i];
arr[i] = -1;
int j = ArrayUtils.indexOf(arr, t);
if(j == -1) {
continue;
} else {
arr[j] = -1;
counter += 1;
}
} else {
continue;
}
}
return counter;
}
}
This has a O(n) time complexity.
Code for Javascript
const set = new Set()
let count = 0;
for(let i = 0; i < i; i++) {
if (set.has(ar[i])) {
count++;
set.delete(ar[i])
} else {
set.add(ar[i])
}
}
You can count the number of times a number appears in the list and divide them by 2
def sockMerchant(n, ar):
unq = set(ar)
count = 0
for i in unq:
count_vals = ar.count(i)
if count_vals>1:
count = count + int(count_vals/2)
return count
The more easiest way I preferred. Answer in Kotlin
var counter = 0
for (i in 0 until n) {
if (arr[i] != 0) {
loop# for (j in i + 1 until n) {
if (arr[i] == arr[j]) {
counter++
arr[j] = 0
break#loop
}
}
}
}
Commenting for better programming
it can also be solved using the built in Set data type as below (my try) -
function sockMerchant(n, ar) {
// Write your code here
let numberSet = [...new Set(ar)];
let pairs = 0;
for(let i=0;i<numberSet.length;i++){
let count = 0;
ar.filter(x => {
if(x == numberSet[i])
count++;
});
pairs+= count / 2 >= 1 ? Math.trunc(count / 2) : 0;
}
return pairs;
}
Using Python 3:
def sockMerchant(n, ar):
flag = 0
for i in range(n):
if ar[i:].count(ar[i])%2==0:
flag+=1
return flag
Think how you would do it in real life. If someone handed you these socks one-by-one, you'd like think, "Do I have one of these already?" If not, you'd set it down and move on to check on the next sock. When you find one you've already set down, you'd move the pair to the side and count that as another found pair.
Programmatically you may take advantage of a HashSet given it's quick access (constant) and that it only allows for one entry per unique key. Therefore, you can attempt add to the set. Failure to do so means it already exists, count and remove the pair, and continue.
Time-complexity: O(n) [n = number of socks]
Space-complexity: O(m) [m = number of UNIQUE sock types]
Java 8:
public static int sockMerchant(int n, List<Integer> ar)
{
Set<Integer> uniqueSockFound = new HashSet<Integer>();
int countedPairs = 0;
//Iterate through each sock checking if a match has been found already or not
for(Integer sock: ar)
{
//If adding the sock to the set is a success, it doesn't exist yet
//Otherwise, a pair exists, so remove the item and increment the count of pairs
if(!uniqueSockFound.add(sock))
{
countedPairs++;
uniqueSockFound.remove(sock);
}
}
//Return count of pairs
return countedPairs;
}
Here is my solution and it worked for the given set of inputs.
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int size = sc.nextInt();
int[] arr = new int[size];
for (int i = 0 ; i < size ; i++) {
arr[i] = sc.nextInt();
}
int flag = 0;
for (int j = 0; j < size; j++) {
int count = 0;
for(int i = j + 1; i < size ; i++) {
if (arr[j] == arr[i]) {
count++;
}
}
flag += count / 2;
}
System.out.println(flag);
}
}
I solve it with golang
func sockMerchant(n int32, ar []int32) int32 {
// Write your code here
var indexPairs []int;
var count int32;
var operation bool;
for i := 0; i< len(ar)-1; i++{
for j := i+1; j< len(ar); j++{
//check indexPairs
operation = true;
for k := 0; k< len(indexPairs); k++{
if indexPairs[k] == i || indexPairs[k]==j{
operation = false;
}
}
if operation {
if(ar[i]==ar[j]){
count ++;
indexPairs = append(indexPairs, i, j)
}
}
}
}
return count;
}```
using PYTHON language
from itertools import groupby
def sockmerchant(n,ar):
c=0
a=[]
ar.sort()
for k,g in groupby(ar): # in this same elements group into one list
a.append(len(list(g)))
for i in a:
c=c+(i//2)
return c
n=int(input())
ar=list(map(int,input().split(' ')))
print(sockMerchant(n,ar))
function sockMerchant(n, ar){
let res = 0;
let arr= {};
for (let element of ar){
arr[element] = arr[element]+1 || 1
if(arr[element]%2 == 0){
res++;
}
}
return res;
}
sockMerchant(4,[10,10,20,20]);
public static int sockMerchant(int n, List<Integer> ar) {
int pair = 0;
List<Integer> matchedIndices = new ArrayList<>();
for (int i = 0; i < n; i++) {
if (matchedIndices.contains(i)) {
continue;
}
for (int j = 0; j < n; j++) {
if (j == i || matchedIndices.contains(j)) {
continue;
}
if (ar.get(i) == ar.get(j)) {
pair++;
matchedIndices.add(i);
matchedIndices.add(j);
break;
}
}
}
return pair;
}
I will give an example of solving this problem in C++ using unordered_map. It's overkill, to be honest, and it's done with unordered_set as well (removing the element as a replacement for a boolean in the map). But this more clearly shows the coding path to first do everything right, and only after that take an optimization step and convert to unordered_set.
using namespace std;
/*
* Complete the 'sockMerchant' function below.
*
* The function is expected to return an INTEGER.
* The function accepts following parameters:
* 1. INTEGER n
* 2. INTEGER_ARRAY ar
*/
int sockMerchant(int n, vector<int> ar) {
if (n<1 && n>100 ) return 0;
unordered_map<int, bool> scExtract;
int result=0;
// false --first sock finded
// true --second sock funded
for (auto sCol:ar) {
if (sCol<1 && sCol>100 ) return 0;
if (scExtract.find(sCol) != scExtract.end()) {
if ( scExtract[sCol]) {
scExtract[sCol]=false;
} else {
scExtract[sCol]=true;
result++;
}
} else {
scExtract.insert(pair<int, bool>(sCol, false));
}
}
return result;
}
I have to write a function "alternatingSum(a)" that takes an array of numbers and returns the alternating sum (where the sign alternates from positive to negative or vice versa).
For example:
int[] a = { 5, 3, 8, 4 };
Assert(alternatingSum(a) == 6); // because 5-3+8-4 == 6
So far I have tried to take the array and check to see if the index is odd (not including i=0) then subtract it from the i+1, and if it is even do the same thing except add the two. Am I on the right track with this?
Here is my code:
class foo {
public static int alternatingSum(int[] a){
int sum=0;
for (int i=0;i<a.length;i++){
if (i==0){
sum+=a[0]-a[1];
}
if (i%2 == 0){
sum+=(a[i]+a[i+1]);
}
if (i%2 == 1){
sum+=(a[i]-a[i+1]);
}
}
return sum;
}
public static void testAlternatingSum(){
System.out.println("testing code");
int[] a = { 5, 3, 8, 4 };
assert (alternatingSum(a) == 6); // because 5-3+8-4 == 6
}
public static void main(String[] args){
testAlternatingSum();
}
}
a for loop
I would just keep a boolean flag for even (and toggle it with every loop iteration). If it's an even number, than we're performing addition. But if it's not an even number (it's odd) then we can perform an unary negative operation. That might look something like,
int sum = 0;
boolean even = true;
for (int i = 0; i < a.length; i++) {
sum += even ? a[i] : -a[i];
even = !even
}
return sum;
for-each loop
and you could also use a for-each loop and write it like
boolean even = true;
int sum = 0;
for (int value : a) {
sum += even ? value : -value;
even = !even;
}
return sum;
Easy to read..
int[] alternatingSums(int[] a) {
int sum1 = 0;
int sum2 = 0;
for(int i =0; i < a.length; i++){
if((i % 2) != 1){
sum1 += a[i];
}else{
sum2 += a[i];
}
}
int[] result = {sum1 , sum2};
return result;
}
I have been trying to solve a Java exercise on a Codility web page.
Below is the link to the mentioned exercise and my solution.
https://codility.com/demo/results/demoH5GMV3-PV8
Can anyone tell what can I correct in my code in order to improve the score?
Just in case here is the task description:
A small frog wants to get to the other side of a river. The frog is currently located at position 0, and wants to get to position X. Leaves fall from a tree onto the surface of the river.
You are given a non-empty zero-indexed array A consisting of N integers representing the falling leaves. A[K] represents the position where one leaf falls at time K, measured in minutes.
The goal is to find the earliest time when the frog can jump to the other side of the river. The frog can cross only when leaves appear at every position across the river from 1 to X.
For example, you are given integer X = 5 and array A such that:
A[0] = 1
A[1] = 3
A[2] = 1
A[3] = 4
A[4] = 2
A[5] = 3
A[6] = 5
A[7] = 4
In minute 6, a leaf falls into position 5. This is the earliest time when leaves appear in every position across the river.
Write a function:
class Solution { public int solution(int X, int[] A); }
that, given a non-empty zero-indexed array A consisting of N integers and integer X, returns the earliest time when the frog can jump to the other side of the river.
If the frog is never able to jump to the other side of the river, the function should return −1.
For example, given X = 5 and array A such that:
A[0] = 1
A[1] = 3
A[2] = 1
A[3] = 4
A[4] = 2
A[5] = 3
A[6] = 5
A[7] = 4
the function should return 6, as explained above. Assume that:
N and X are integers within the range [1..100,000];
each element of array A is an integer within the range [1..X].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(X), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
And here is my solution:
import java.util.ArrayList;
import java.util.List;
class Solution {
public int solution(int X, int[] A) {
int list[] = A;
int sum = 0;
int searchedValue = X;
List<Integer> arrayList = new ArrayList<Integer>();
for (int iii = 0; iii < list.length; iii++) {
if (list[iii] <= searchedValue && !arrayList.contains(list[iii])) {
sum += list[iii];
arrayList.add(list[iii]);
}
if (list[iii] == searchedValue) {
if (sum == searchedValue * (searchedValue + 1) / 2) {
return iii;
}
}
}
return -1;
}
}
You are using arrayList.contains inside a loop, which will traverse the whole list unnecessarily.
Here is my solution (I wrote it some time ago, but I believe it scores 100/100):
public int frog(int X, int[] A) {
int steps = X;
boolean[] bitmap = new boolean[steps+1];
for(int i = 0; i < A.length; i++){
if(!bitmap[A[i]]){
bitmap[A[i]] = true;
steps--;
if(steps == 0) return i;
}
}
return -1;
}
Here is my solution. It got me 100/100:
public int solution(int X, int[] A)
{
int[] B = A.Distinct().ToArray();
return (B.Length != X) ? -1 : Array.IndexOf<int>(A, B[B.Length - 1]);
}
100/100
public static int solution (int X, int[] A){
int[]counter = new int[X+1];
int ans = -1;
int x = 0;
for (int i=0; i<A.length; i++){
if (counter[A[i]] == 0){
counter[A[i]] = A[i];
x += 1;
if (x == X){
return i;
}
}
}
return ans;
}
A Java solution using Sets (Collections Framework) Got a 100%
import java.util.Set;
import java.util.TreeSet;
public class Froggy {
public static int solution(int X, int[] A){
int steps=-1;
Set<Integer> values = new TreeSet<Integer>();
for(int i=0; i<A.length;i++){
if(A[i]<=X){
values.add(A[i]);
}
if(values.size()==X){
steps=i;
break;
}
}
return steps;
}
Better approach would be to use Set, because it only adds unique values to the list. Just add values to the Set and decrement X every time a new value is added, (Set#add() returns true if value is added, false otherwise);
have a look,
public static int solution(int X, int[] A) {
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < A.length; i++) {
if (values.add(A[i])) X--;
if (X == 0) return i;
}
return -1;
}
do not forget to import,
import java.util.HashSet;
import java.util.Set;
Here's my solution, scored 100/100:
import java.util.HashSet;
class Solution {
public int solution(int X, int[] A) {
HashSet<Integer> hset = new HashSet<Integer>();
for (int i = 0 ; i < A.length; i++) {
if (A[i] <= X)
hset.add(A[i]);
if (hset.size() == X)
return i;
}
return -1;
}
}
Simple solution 100%
public int solution(final int X, final int[] A) {
Set<Integer> emptyPosition = new HashSet<Integer>();
for (int i = 1; i <= X; i++) {
emptyPosition.add(i);
}
// Once all the numbers are covered for position, that would be the
// moment when the frog will jump
for (int i = 0; i < A.length; i++) {
emptyPosition.remove(A[i]);
if (emptyPosition.size() == 0) {
return i;
}
}
return -1;
}
Here's my solution.
It isn't perfect, but it's good enough to score 100/100.
(I think that it shouldn't have passed a test with a big A and small X)
Anyway, it fills a new counter array with each leaf that falls
counter has the size of X because I don't care for leafs that fall farther than X, therefore the try-catch block.
AFTER X leafs fell (because it's the minimum amount of leafs) I begin checking whether I have a complete way - I'm checking that every int in count is greater than 0.
If so, I return i, else I break and try again.
public static int solution(int X, int[] A){
int[] count = new int[X];
for (int i = 0; i < A.length; i++){
try{
count[A[i]-1]++;
} catch (ArrayIndexOutOfBoundsException e){ }
if (i >= X - 1){
for (int j = 0; j< count.length; j++){
if (count[j] == 0){
break;
}
if (j == count.length - 1){
return i;
}
}
}
}
return -1;
}
Here's my solution with 100 / 100.
public int solution(int X, int[] A) {
int len = A.length;
if (X > len) {
return -1;
}
int[] isFilled = new int[X];
int jumped = 0;
Arrays.fill(isFilled, 0);
for (int i = 0; i < len; i++) {
int x = A[i];
if (x <= X) {
if (isFilled[x - 1] == 0) {
isFilled[x - 1] = 1;
jumped += 1;
if (jumped == X) {
return i;
}
}
}
}
return -1;
}
Here's what I have in C#. It can probably still be refactored.
We throw away numbers greater than X, which is where we want to stop, and then we add numbers to an array if they haven't already been added.
When the count of the list has reached the expected number, X, then return the result. 100%
var tempArray = new int[X+1];
var totalNumbers = 0;
for (int i = 0; i < A.Length; i++)
{
if (A[i] > X || tempArray.ElementAt(A[i]) != 0)
continue;
tempArray[A[i]] = A[i];
totalNumbers++;
if (totalNumbers == X)
return i;
}
return -1;
below is my solution. I basically created a set which allows uniques only and then go through the array and add every element to set and keep a counter to get the sum of the set and then using the sum formula of consecutive numbers then I got 100% . Note : if you add up the set using java 8 stream api the solution is becoming quadratic and you get %56 .
public static int solution2(int X, int[] A) {
long sum = X * (X + 1) / 2;
Set<Integer> set = new HashSet<Integer>();
int setSum = 0;
for (int i = 0; i < A.length; i++) {
if (set.add(A[i]))
setSum += A[i];
if (setSum == sum) {
return i;
}
}
return -1;
}
My JavaScript solution that got 100 across the board. Since the numbers are assumed to be in the range of the river width, simply storing booleans in a temporary array that can be checked against duplicates will do. Then, once you have amassed as many numbers as the quantity X, you know you have all the leaves necessary to cross.
function solution(X, A) {
covered = 0;
tempArray = [];
for (let i = 0; i < A.length; i++) {
if (!tempArray[A[i]]) {
tempArray[A[i]] = true;
covered++
if(covered === X) return i;
}
}
return -1;
}
Here is my answer in Python:
def solution(X, A):
# write your code in Python 3.6
values = set()
for i in range (len(A)):
if A[i]<=X :
values.add(A[i])
if len(values)==X:
return i
return -1
Just tried this problem as well and here is my solution. Basically, I just declared an array whose size is equal to position X. Then, I declared a counter to monitor if the necessary leaves have fallen at the particular spots. The loop exits when these leaves have been met and if not, returns -1 as instructed.
class Solution {
public int solution(int X, int[] A) {
int size = A.length;
int[] check = new int[X];
int cmp = 0;
int time = -1;
for (int x = 0; x < size; x++) {
int temp = A[x];
if (temp <= X) {
if (check[temp-1] > 0) {
continue;
}
check[temp - 1]++;
cmp++;
}
if ( cmp == X) {
time = x;
break;
}
}
return time;
}
}
It got a 100/100 on the evaluation but I'm not too sure of its performance. I am still a beginner when it comes to programming so if anybody can critique the code, I would be grateful.
Maybe it is not perfect but its straightforward. Just made a counter Array to track the needed "leaves" and verified on each iteration if the path was complete. Got me 100/100 and O(N).
public static int frogRiver(int X, int[] A)
{
int leaves = A.Length;
int[] counter = new int[X + 1];
int stepsAvailForTravel = 0;
for(int i = 0; i < leaves; i++)
{
//we won't get to that leaf anyway so we shouldnt count it,
if (A[i] > X)
{
continue;
}
else
{
//first hit!, keep a count of the available leaves to jump
if (counter[A[i]] == 0)
stepsAvailForTravel++;
counter[A[i]]++;
}
//We did it!!
if (stepsAvailForTravel == X)
{
return i;
}
}
return -1;
}
This is my solution. I think it's very simple. It gets 100/100 on codibility.
set.contains() let me eliminate duplicate position from table.
The result of first loop get us expected sum. In the second loop we get sum of input values.
class Solution {
public int solution(int X, int[] A) {
Set<Integer> set = new HashSet<Integer>();
int sum1 = 0, sum2 = 0;
for (int i = 0; i <= X; i++){
sum1 += i;
}
for (int i = 0; i < A.length; i++){
if (set.contains(A[i])) continue;
set.add(A[i]);
sum2 += A[i];
if (sum1 == sum2) return i;
}
return -1;
}
}
Your algorithm is perfect except below code
Your code returns value only if list[iii] matches with searchedValue.
The algorithm must be corrected in such a way that, it returns the value if sum == n * ( n + 1) / 2.
import java.util.ArrayList;
import java.util.List;
class Solution {
public int solution(int X, int[] A) {
int list[] = A;
int sum = 0;
int searchedValue = X;
int sumV = searchedValue * (searchedValue + 1) / 2;
List<Integer> arrayList = new ArrayList<Integer>();
for (int iii = 0; iii < list.length; iii++) {
if (list[iii] <= searchedValue && !arrayList.contains(list[iii])) {
sum += list[iii];
if (sum == sumV) {
return iii;
}
arrayList.add(list[iii]);
}
}
return -1;
}
}
I think you need to check the performance as well. I just ensured the output only
This solution I've posted today gave 100% on codility, but respectivly #rafalio 's answer it requires K times less memory
public class Solution {
private static final int ARRAY_SIZE_LOWER = 1;
private static final int ARRAY_SIZE_UPPER = 100000;
private static final int NUMBER_LOWER = ARRAY_SIZE_LOWER;
private static final int NUMBER_UPPER = ARRAY_SIZE_UPPER;
public static class Set {
final long[] buckets;
public Set(int size) {
this.buckets = new long[(size % 64 == 0 ? (size/64) : (size/64) + 1)];
}
/**
* number should be greater than zero
* #param number
*/
public void put(int number) {
buckets[getBucketindex(number)] |= getFlag(number);
}
public boolean contains(int number) {
long flag = getFlag(number);
// check if flag is stored
return (buckets[getBucketindex(number)] & flag) == flag;
}
private int getBucketindex(int number) {
if (number <= 64) {
return 0;
} else if (number <= 128) {
return 1;
} else if (number <= 192) {
return 2;
} else if (number <= 256) {
return 3;
} else if (number <= 320) {
return 4;
} else if (number <= 384) {
return 5;
} else
return (number % 64 == 0 ? (number/64) : (number/64) + 1) - 1;
}
private long getFlag(int number) {
if (number <= 64) {
return 1L << number;
} else
return 1L << (number % 64);
}
}
public static final int solution(final int X, final int[] A) {
if (A.length < ARRAY_SIZE_LOWER || A.length > ARRAY_SIZE_UPPER) {
throw new RuntimeException("Array size out of bounds");
}
Set set = new Set(X);
int ai;
int counter = X;
final int NUMBER_REAL_UPPER = min(NUMBER_UPPER, X);
for (int i = 0 ; i < A.length; i++) {
if ((ai = A[i]) < NUMBER_LOWER || ai > NUMBER_REAL_UPPER) {
throw new RuntimeException("Number out of bounds");
} else if (ai <= X && !set.contains(ai)) {
counter--;
if (counter == 0) {
return i;
}
set.put(ai);
}
}
return -1;
}
private static int min(int x, int y) {
return (x < y ? x : y);
}
}
This is my solution it got me 100/100 and O(N).
public int solution(int X, int[] A) {
Map<Integer, Integer> leaves = new HashMap<>();
for (int i = A.length - 1; i >= 0 ; i--)
{
leaves.put(A[i] - 1, i);
}
return leaves.size() != X ? -1 : Collections.max(leaves.values());
}
This is my solution
public func FrogRiverOne(_ X : Int, _ A : inout [Int]) -> Int {
var B = [Int](repeating: 0, count: X+1)
for i in 0..<A.count {
if B[A[i]] == 0 {
B[A[i]] = i+1
}
}
var time = 0
for i in 1...X {
if( B[i] == 0 ) {
return -1
} else {
time = max(time, B[i])
}
}
return time-1
}
A = [1,2,1,4,2,3,5,4]
print("FrogRiverOne: ", FrogRiverOne(5, &A))
Actually I re-wrote this exercise without seeing my last answer and came up with another solution 100/100 and O(N).
public int solution(int X, int[] A) {
Set<Integer> leaves = new HashSet<>();
for(int i=0; i < A.length; i++) {
leaves.add(A[i]);
if (leaves.contains(X) && leaves.size() == X) return i;
}
return -1;
}
I like this one better because it is even simpler.
This one works good on codality 100% out of 100%. It's very similar to the marker array above but uses a map:
public int solution(int X, int[] A) {
int index = -1;
Map<Integer, Integer> map = new HashMap();
for (int i = 0; i < A.length; i++) {
if (!map.containsKey(A[i])) {
map.put(A[i], A[i]);
X--;
if (X == 0) {index = i;break;}
}
}
return index;
}
%100 with js
function solution(X, A) {
let leafSet = new Set();
for (let i = 0; i < A.length; i += 1) {
if(A[i] <= 0)
continue;
if (A[i] <= X )
leafSet.add(A[i]);
if (leafSet.size == X)
return i;
}
return -1;
}
With JavaScript following solution got 100/100.
Detected time complexity: O(N)
function solution(X, A) {
let leaves = new Set();
for (let i = 0; i < A.length; i++) {
if (A[i] <= X) {
leaves.add(A[i])
if (leaves.size == X) {
return i;
}
}
}
return -1;
}
100% Solution using Javascript.
function solution(X, A) {
if (A.length === 0) return -1
if (A.length < X) return -1
let steps = X
const leaves = {}
for (let i = 0; i < A.length; i++) {
if (!leaves[A[i]]) {
leaves[A[i]] = true
steps--
}
if (steps === 0) {
return i
}
}
return -1
}
C# Solution with 100% score:
using System;
using System.Collections.Generic;
class Solution {
public int solution(int X, int[] A) {
// go through the array
// fill a hashset, until the size of hashset is X
var set = new HashSet<int>();
int i = 0;
foreach (var a in A)
{
if (a <= X)
{
set.Add(a);
}
if (set.Count == X)
{
return i;
}
i++;
}
return -1;
}
}
https://app.codility.com/demo/results/trainingXE7QFJ-TZ7/
I have a very simple solution (100% / 100%) using HashSet. Lots of people check unnecessarily whether the Value is less than or equal to X. This task cannot be otherwise.
public static int solution(int X, int[] A) {
Set<Integer> availableFields = new HashSet<>();
for (int i = 0; i < A.length; i++) {
availableFields.add(A[i]);
if (availableFields.size() == X){
return i;
}
}
return -1;
}
public static int solutions(int X, int[] A) {
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < A.length; i++) {
if (values.add(A[i])) {
X--;
}
if (X == 0) {
return i;
}
}
return -1;
}
This is my solution. It uses 3 loops but is constant time and gets 100/100 on codibility.
class FrogLeap
{
internal int solution(int X, int[] A)
{
int result = -1;
long max = -1;
var B = new int[X + 1];
//initialize all entries in B array with -1
for (int i = 0; i <= X; i++)
{
B[i] = -1;
}
//Go through A and update B with the location where that value appeared
for (int i = 0; i < A.Length; i++)
{
if( B[A[i]] ==-1)//only update if still -1
B[A[i]] = i;
}
//start from 1 because 0 is not valid
for (int i = 1; i <= X; i++)
{
if (B[i] == -1)
return -1;
//The maxValue here is the earliest time we can jump over
if (max < B[i])
max = B[i];
}
result = (int)max;
return result;
}
}
Short and sweet C++ code. Gets perfect 100%... Drum roll ...
#include <set>
int solution(int X, vector<int> &A) {
set<int> final;
for(unsigned int i =0; i< A.size(); i++){
final.insert(A[i]);
if(final.size() == X) return i;
}
return -1;
}
Given two strings of length n,P = p1...pn and Q = q1...qn, we define M(i, j, k) as the number of mismatches between pi...pi+k-1 and qj..qj+k-1. That is in set notation, M(i, j, k) refers to the size of the set { 0<=x<k | pi+x not equal to qj+x| }.
Given an integer K, your task is to find the maximum length L such that there exists pair of indices (i,j) for which we have M(i, j, L) <= K. Of course, we should also have i+L-1 <=n and j+L-1 <=n.
Input
First line of input contains a single integer T (1 <=T <=10). T test cases follow.
Each test case consists of an integer K and two strings P and Q separated by a single space.
Output
For each test case output a single integer L which is the maximum value for which there exists pair of indices (i,j) such that M(i, j, L) <=K.
Constraints
0 <= K <= length of the string P
Both P & Q would have the same length
The size of each of the string would be at the max 1500
All characters in P & Q are lower-case English letters.
Sample Input
3
2 tabriz torino
0 abacba abcaba
3 helloworld yellomarin
Sample Output
4
3
8
Explanation:
First test-case: If we take "briz" from the first string, and "orin" from the second string, then the number of mismatches between these two substrings is equal to 2, and the length of these substrings are 4. That's we have chosen i=3, j=2, L=4, and we have M(3,2,4) = 2.
Second test-case: Since K=0, we should find the longest common substring for the given input strings. We can choose "aba" as the result, and we don't have longer common substring between two strings. So, the answer is 3 for this test-case. That's we have chosen i=1, j=4, and L=3, and we have M(1,4,3)=0.
Third test-case: We can choose "hellowor" from first string and "yellomar" from the second string. So, we have chosen i=1, j=1, and L=8, and we have M(1,1,8)=3. Of course we can also choose i=2, j=2, and L=8 and we still have M(2,2,8)=3.
here is my implementation
import java.io.*;
import java.util.*;
class Solution {
public static int mismatch(String a, String b, int ii, int jj, int xx) {
int i, j = 0;
for (i = 0; i < xx; i++) {
if (a.charAt(ii) != b.charAt(jj)) {
j++;
}
ii++;
jj++;
}
return j;
}
public static boolean find(int x, String a, String b, int kx) {
int nn = a.length();
for (int i = 0; i <= (nn - x); i++) {
for (int j = 0; j <= (nn - x); j++) {
int k;
k = mismatch(a, b, i, j, x);
if (k == kx) {
return true;
}
}
}
return false;
}
public static void main(String args[]) throws IOException {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
while (t > 0) {
int k, n;
String a, b;
k = scanner.nextInt();
a = scanner.next();
b = scanner.next();
n = a.length();
int i = (n + k) / 2;
int st = k, en = n
while (i != k || i != n) {
boolean ch = false, chh = false;
ch = find(i, a, b, k);
if (i != n) {
chh = find(i + 1, a, b, k);
}
if (i == n && ch == true) {
System.out.println(i);
break;
}
if (ch == true && chh == false) {
System.out.println(i);
break;
}
if (ch) {
st = i;
i = (i + en + 1) / 2;
} else {
en = i;
i = (st + i) / 2;
}
}
t--;
}
}
}
the above implementation is taking 5.1 sec for input 0f 1500 string length.But maximum time limit in java is 5sec.if any one can improve this code,please kindly share yor thougths
Your code doesn't take 5.1s on the site. They stop running your code as soon as it exceeds the time limit. Your code might be taking even minutes. So, even if you optimize it with this algorithm you will again get 5.1s in details section. So work on your algo, not optimization!
You could make a boolean array compare[n,n], for which compare[i,j]=(a[i]==b[j]). Later use it instead of making repeating comparisons. You'll have incomparably less comparisons and addressing.
public static int mismatch(String a, String b, int ii, int jj, int xx) {
int i, j = 0;
for (i = 0; i < xx; i++) {
if (! compare[ii,jj]) {
j++;
}
ii++;
jj++;
}
return j;
}