Why is the JVM hanging up? - java

I think this can be solved with setting traps/breakpoints - but I'm not quite sure on how to do that. This method is supposed to sort an array of objects (each object contains an int, which is a year), but I get nothing on the terminal, and a busy VM signal... What's going on?
public static movie2[] sortYear(movie2[] sort, int parameter)
{
int[] dest = new int[sort.length];
if(parameter == 1)
{
for(int i = 0; i < sort.length-1; i++)
{
int next = sort[i].getYear();
int insertIndex = 0;
int k = i; //Why do I need this?
while( k > 0 && insertIndex == 0)
{
if(next > dest[k-1])
{
insertIndex = k;
}
else
{
dest[insertIndex] = next;
}
}
sort[i].setYear(dest[i]);
}

Related

Leetcode - Longest Common Prefix - Why is my runtime so slow compared to the solution?

Question: Write a function to find the longest common prefix string amongst an array of strings.
This is a easy question from leetcode and below is my answer VS. the solution answer. The problem is: my answer beats 1.17% of the runtime speed and the solution beats 79.65%. Why is my code so slow?
Our code are pretty much similar until we start to manipulate the initial common string. The solution does this by calling indexof and substring function in String class and mine does it by using a findCommon function, which is defined by me.
Solution:
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0) return "";
String pre = strs[0];
int i = 1;
while(i < strs.length){
while(strs[i].indexOf(pre) != 0)
pre = pre.substring(0,pre.length()-1);
i++;
}
return pre;
}
This is mine:
public static String longestCommonPrefix(String[] strs){
if(strs == null || strs.length == 0)
return "";
String result = strs[0];
for(int index = 1; index < strs.length; index++)
result = findCommon(result, strs[index]);
return result;
}
public static String findCommon(String a, String b){
String common = "";
for(int index = 0; index < Math.min(a.length(), b.length()); index++)
{
if(a.charAt(index) == b.charAt(index))
common += a.charAt(index);
else
break;
}
return common;
}
In my opinion, the solution code only looks simpler because the functions are defined in String library. But it doesn't mean they don't exist.
Take a look at how you're building up the prefix string:
String common = "";
for(int index = 0; index < Math.min(a.length(), b.length()); index++)
{
if(a.charAt(index) == b.charAt(index))
common += a.charAt(index);
else
break;
}
return common;
Every time you execute
common += a.charAt(index);
Java has to create a brand new String object formed by tacking a new character onto the end of the existing string common. This means that the cost of making a prefix string of length p ends up being O(p2). If you have n total strings, then the runtime of your program will be something like O(np2).
Contrast this against the reference solution:
pre = pre.substring(0,pre.length()-1);
In many Java implementations, the act of creating a substring takes time O(1) because the new string can share the underlying character array with the original string (with some indices tweaked to account for the new start index). That means that the cost of working through p prefixes would be O(p) rather than O(p2), which could lead to a large increase in performance for longer strings.
I user trie to solve that problem. You can try to user trie
#define MAX 30 //the total number of alphabet is 26, a...z
struct DicTrie{
bool isTerminal;//是否是单词结束标志
int count; //当前字符串出现次数
int branchCount; //计数当前节点的孩子数
struct DicTrie *next[MAX ]; //每个节点 最多 有 MAX 个孩子节点 结构体嵌套
};
int insertTrie(struct DicTrie *root ,char *targetString)
{
if (!targetString) {
return 0;
}
int len = strlen(targetString);
if (len <= 0) {
return 0;
}
struct DicTrie *head = root;
for (int i = 0; i < len; i ++) {
int res = (int)(targetString[i] - 'a');//当前小写字母对应数字
if (head->next[res] == NULL) { //如果是空节点
head->next[res] = (struct DicTrie *)malloc(sizeof(struct DicTrie));//new DicTrie;//则插入新节点元素
head = head->next[res]; //更新头指针 并初始化
head->count = 0; //
for (int j = 0; j < MAX; j ++) {
head->next[j] = NULL;
head->isTerminal = false;
}
head->branchCount = 1;//一个分支
} else {
head = head->next[res];
head->branchCount ++;//分支累计
}
}
head->count ++;//每次插入一个,响应计数都增加1
head->isTerminal = true;
return head->count;
}
char* longestCommonPrefix(char** strs, int strsSize) {
int len = strsSize;
//边界处理
if (len == 0) {
return "";
}
if (len == 1) {
return strs[0];
}
//组织字典树
struct DicTrie *root = NULL;
root = (struct DicTrie *)malloc(sizeof(struct DicTrie));
root->count = 0;
root->branchCount = 0;
for (int i = 0; i < MAX; i ++) {
root->next[i] = NULL; // 空节点
root->isTerminal = false; //
}
//
for (int i = 0;i < len; i ++) {
insertTrie(root, strs[i]);
}
//
int preIndex = 0;
struct DicTrie *head = root;
bool isFlag = false;
int i = 0;
int count = strlen(strs[0]);//任意一字符串都可以 从strs[0]中查即可
for (preIndex = 0; preIndex< count; preIndex ++) {
int targetIndex = strs[0][preIndex] - 'a';
head = head->next[targetIndex];
if (head->branchCount == len) {
i ++;//拿到合法前缀的计数
isFlag = true;
}
}
if (isFlag) {
preIndex = i;
} else {
preIndex = 0;
}
strs[0][preIndex] = '\0';
return strs[0];
}
the runtime speed is ok.

Keeping track of Collisions per index in an array-based hash table, as well as which values resulted in a collision using OPEN ADDRESSING ONLY

Sorry for the wordy title but it explains my question pretty well.
I am working on an assignment in Java where I need to create my own Hash Table.
The specifications are such that I must use an Array, as well as open-addressing for collision handling (with both double hashing and quadratic hashing implementations).
My implementation works quite well, and using over 200,000 randomly generated Strings I end up with only ~1400 Collisions with both types of collision handling mentioned about (keeping my load factor at 0.6 and increasing my Array by 2.1 when it goes over).
Here is where I'm stumped, however... My assignment calls for 2 specifications that I cannot figure out.
1) Have an option which, when removing a value form the table, instead of using "AVAILABLE" (replacing the index in the array with a junk value that indicates it is empty), I must find another value that previously hashed to this index and resulted in a collision. For example, if value A hashed to index 2 and value B also hashed to index 2 (and was later re-hashed to index 5 using my collision handling hash function), then removing value A will actually replace it with Value B.
2) Keep track of the maximum number of collisions in a single array index. I currently keep track of all the collisions, but there's no way for me to keep track of the collisions at an individual cell.
I was able to solve this problem using Separate Chaining by having each Array Index hold a linked list of all values that have hashed to this index, so that only the first one is retrieved when I call my get(value) method, but upon removal I can easily replace it with the next value that hashed to this index. It's also an easy way to get the max number of collisions per index.
But we were specifically told not to use separate chaining... I'm actually wondering if this is even possible without completely ruining the complexity of the hash table.
Any advice would be appreciated.
edit:
Here are some examples to give you an idea of my class structure:
public class daveHash {
//Attributes
public String[] dTable;
private double loadFactor, rehashFactor;
private int size = 0;
private String emptyMarkerScheme;
private String collisionHandlingType;
private int collisionsTotal = 0;
private int collisionsCurrent = 0;
//Constructors
public daveHash()
{
dTable = new String[17];
rehashFactor = 2.1;
loadFactor = 0.6;
emptyMarkerScheme = "A";
collisionHandlingType = "D";
}
public daveHash(int size)
{
dTable = new String[size];
rehashFactor = 2.1;
loadFactor = 0.6;
emptyMarkerScheme = "A";
collisionHandlingType = "D";
}
My hashing functions:
public long getHashCode(String s, int index)
{
if (index > s.length() - 1)
return 0;
if (index == s.length()-1)
return (long)s.charAt(index);
if (s.length() >= 20)
return ((long)s.charAt(index) + 37 * getHashCode(s, index+3));
return ((long)s.charAt(index) + 37 * getHashCode(s, index+1));
}
public int compressHashCode(long hash, int arraySize)
{
int b = nextPrime(arraySize);
int index = ((int)((7*hash) % b) % arraySize);
if (index < 0)
return index*-1;
else
return index;
}
Collision handling:
private int collisionDoubleHash(int index, long hashCode, String value, String[] table)
{
int newIndex = 0;
int q = previousPrime(table.length);
int secondFunction = (q - (int)hashCode) % q;
if (secondFunction < 0)
secondFunction = secondFunction*-1;
for (int i = 0; i < table.length; i++)
{
newIndex = (index + i*secondFunction) % table.length;
//System.out.println(newIndex);
if (isAvailable(newIndex, table))
{
table[newIndex] = value;
return newIndex;
}
}
return -1;
}
private int collisionQuadraticHash(int index, long hashCode, String value, String[] table)
{
int newIndex = 0;
for (int i = 0; i < table.length; i ++)
{
newIndex = (index + i*i) % table.length;
if (isAvailable(newIndex, table))
{
table[newIndex] = value;
return newIndex;
}
}
return -1;
}
public int collisionHandling(int index, long hashCode, String value, String[] table)
{
collisionsTotal++;
collisionsCurrent++;
if (this.collisionHandlingType.equals("D"))
return collisionDoubleHash(index, hashCode, value, table);
else if (this.collisionHandlingType.equals("Q"))
return collisionQuadraticHash(index, hashCode, value, table);
else
return -1;
}
Get, Put and Remove:
private int getIndex(String k)
{
long hashCode = getHashCode(k, 0);
int index = compressHashCode(hashCode, dTable.length);
if (dTable[index] != null && dTable[index].equals(k))
return index;
else
{
if (this.collisionHandlingType.equals("D"))
{
int newIndex = 0;
int q = previousPrime(dTable.length);
int secondFunction = (q - (int)hashCode) % q;
if (secondFunction < 0)
secondFunction = secondFunction*-1;
for (int i = 0; i < dTable.length; i++)
{
newIndex = (index + i*secondFunction) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return newIndex;
}
}
}
else if (this.collisionHandlingType.equals("Q"))
{
int newIndex = 0;
for (int i = 0; i < dTable.length; i ++)
{
newIndex = (index + i*i) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return newIndex;
}
}
}
return -1;
}
}
public String get(String k)
{
long hashCode = getHashCode(k, 0);
int index = compressHashCode(hashCode, dTable.length);
if (dTable[index] != null && dTable[index].equals(k))
return dTable[index];
else
{
if (this.collisionHandlingType.equals("D"))
{
int newIndex = 0;
int q = previousPrime(dTable.length);
int secondFunction = (q - (int)hashCode) % q;
if (secondFunction < 0)
secondFunction = secondFunction*-1;
for (int i = 0; i < dTable.length; i++)
{
newIndex = (index + i*secondFunction) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return dTable[newIndex];
}
}
}
else if (this.collisionHandlingType.equals("Q"))
{
int newIndex = 0;
for (int i = 0; i < dTable.length; i ++)
{
newIndex = (index + i*i) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return dTable[newIndex];
}
}
}
return null;
}
}
public void put(String k, String v)
{
double fullFactor = (double)this.size / (double)dTable.length;
if (fullFactor >= loadFactor)
resizeTable();
long hashCode = getHashCode(k, 0);
int index = compressHashCode(hashCode, dTable.length);
if (isAvailable(index, dTable))
{
dTable[index] = v;
size++;
}
else
{
collisionHandling(index, hashCode, v, dTable);
size++;
}
}
public String remove(String k)
{
int index = getIndex(k);
if (dTable[index] == null || dTable[index].equals("AVAILABLE") || dTable[index].charAt(0) == '-')
return null;
else
{
if (this.emptyMarkerScheme.equals("A"))
{
String val = dTable[index];
dTable[index] = "AVAILABLE";
size--;
return val;
}
else if (this.emptyMarkerScheme.equals("N"))
{
String val = dTable[index];
dTable[index] = "-" + val;
size--;
return val;
}
}
return null;
}
Hopefully this can give you an idea of my approach. This does not include the Separate Chaining implementation I mentioned above. For this, I had the following inner classes:
private class hashList
{
private class hashNode
{
private String element;
private hashNode next;
public hashNode(String element, hashNode n)
{
this.element = element;
this.next = n;
}
}
private hashNode head;
private int length = 0;
public hashList()
{
head = null;
}
public void addToStart(String s)
{
head = new hashNode(s, head);
length++;
}
public int getLength()
{
return length;
}
}
And my methods were modified appropriate to access the element in the head node vs the element in the Array. I took this out, however, since we are not supposed to use Separate Chaining to solve the problem.
Thanks!!

Getting every combination of Queens?

public class SomeQueens {
static Stack<Integer> s= new Stack<Integer>();
static int Solved = 0;
static int current = 0;
public static int solve(int n) { // n is 8
while(current < n) { // should I use current < n instead
for (int i = current; i < n; i++) {
if(validPosition(i)) {
s.push(i);
current = 0;
}
}
if(!validPosition(current)) {
if(s.empty()) {
break;
}
if(!s.empty()) {
s.pop();
current++;
}
}
if(s.size() == n) {
s.pop();
current++;
printSolution(s);// this is a method, but it shouldn't matter for this
Solved++;
}
}
return Solved;
}
public static boolean validPosition(int column) {
for( int row = 0; row < s.size(); row++)
if(s.get(row) == column || ((column - s.get(row)) == (s.size() - row)) ||
((s.get(row) - column) == (s.size() - row)) )
return false; // there's a conflict
return true; // no conflict;
}
//it's called by int num = solve(n);
//sop("There're" + num + "sols to the" + n "queens prob");
This is a subsection of my program for NQueens, but I seem to always get: There are 0 solutions to the 8-queens problem. I tried debugging with system.out.prints in the main method, which led me to guess that there would be something wrong in my boolean method, but I don't think it's doing anything wrong.
I'm unsure if my while statement is incorrect or if the break inside the while loop is initialized before anything is even done. Thanks for the help and guidance and I'm sorry if my program and explanation makes no sense
Here is why you instantly get a zero:
s.push(0);
while(s.size() > n) // n is 8
{
//...
}
return Solved;
When the program arrives at the while-condition s has a size of one and n is 8. This will instantly fail and cause the method to return a zero.
But that's not the only problem with the algorithm. You should seriously rethink it.

java codility Frog-River-One

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;
}

Finding the local min/max in a 1D-Array/Histogram

I'm trying to find the indices of all the local minima and maxima within an Array.
Example:
int[] array = {5,4,3,3,3,3,3,2,2,2, 6,6,8,5,5,5,3,3,2,1, 1,4,4,7};
// | | |
// Indices: 0,1,2,3,4,5,6,7,8,9, 10,1,2,3,4,5,6,7,8,9, 20,1,2,3
// Minima: 8, 20
// Maxima: 12
I came up with an algorithm about which I have few questions:
Is there a much better one? :)
I used an Enum with methods to achieve this dualism that UP and STRAIGHT_UP are both "UP". Seems messy to me. Any suggestions?
Do you have better method-names? direction() (+return value) kind of implies that STRAIGHT is not a dir. But at the same time it is, since its an element in the Emum. Hm.
It works for the given array. Do you see a situation where it does not?
-
import java.util.ArrayList;
public class MinMaxFinder {
private int[] array;
private ArrayList<Integer> minima;
private ArrayList<Integer> maxima;
private enum Direction{
UP, DOWN, STRAIGHT_UP, STRAIGHT_DOWN, STRAIGHT;
public Direction direction(){
if(this==UP || this==STRAIGHT_UP){
return UP;
}else if(this==DOWN || this==STRAIGHT_DOWN){
return DOWN;
}else{
return STRAIGHT;
}
}
public boolean isStraight(){
if(this==STRAIGHT_DOWN || this==STRAIGHT_UP || this==STRAIGHT){
return true;
}else{
return false;
}
}
public boolean hasDifferentDirection(Direction other){
if(this!=STRAIGHT && other!=STRAIGHT && this.direction() != other.direction() ){
return true;
}
return false;
}
}
public MinMaxFinder(int[] array){
this.array = array;
}
public void update() {
minima = new ArrayList<Integer>();
maxima = new ArrayList<Integer>();
Direction segmentDir = Direction.DOWN;
int indexOfDirectionChange = 0;
int prevVal = array[0];
int arrayLength = array.length;
for(int i=1; i<arrayLength; i++){
int currVal = array[i];
Direction currentDir = currVal<prevVal?Direction.DOWN:(currVal>prevVal?Direction.UP:Direction.STRAIGHT);
prevVal = currVal;
if(currentDir.hasDifferentDirection(segmentDir)){
int changePos = (indexOfDirectionChange+i-1)/2;
if(currentDir.direction() == Direction.DOWN){
maxima.add(changePos);
}else{
minima.add(changePos);
}
segmentDir = currentDir;
indexOfDirectionChange = i;
}else if( currentDir.isStraight() ^ segmentDir.isStraight() ){
indexOfDirectionChange = i;
if(currentDir.isStraight() && segmentDir.direction()==Direction.UP){
segmentDir=Direction.STRAIGHT_UP;
}else if(currentDir.isStraight() && segmentDir.direction()==Direction.DOWN){
segmentDir=Direction.STRAIGHT_DOWN;
}else{
segmentDir = currentDir;
}
}
}
}
public ArrayList<Integer> getMinima() {
return minima;
}
public ArrayList<Integer> getMaxima() {
return maxima;
}
}
Consider an array of first differences d[i] = a[i] - a[i-1].
If d[i] is positive, then a increased over the last step and if d[i] is negative then a decreased. So, a change in sign of d from positive to negative indicates a was increasing, now decreasing, a local max. Similarly, negative to positive indicates a local min.
Something like this "should" work and it's probably conceptually less complicated.
Scans the array once and registers mins and maxs.
Things worth mentioning:
1) The if(direction < 0){}else{} can probably be removed, but I didn't have time to think about the details.
2) The key idea is, depending on the first "direction" (whether we see a min or a max first), the for loops order changes.
3) in case of multiple items, it will always keep the last element (highest index).
if(a.length < 2){
return;
}
List<Integer> mins = new ArrayList<Integer>();
List<Integer> maxs = new ArrayList<Integer>();
int i=1;
int prev = 0;
int direction = 0;
for(int j=1, k = 0;j<a.length && (direction = a[j]-a[k]) == 0;j++, k++);
if(direction == 0){
//Array contains only same value.
return;
}
if(direction < 0){
while(i<a.length){
for(;i<a.length && a[prev] >= a[i];i++,prev++);
mins.add(prev);
for(;i<a.length && a[prev] <= a[i];i++,prev++);
maxs.add(prev);
i++;prev++;
}
}
else{
while(i<a.length){
for(;i<a.length && a[prev] <= a[i];i++,prev++);
maxs.add(prev);
for(;i<a.length && a[prev] >= a[i];i++,prev++);
mins.add(prev);
i++;prev++;
}
}
//maxs and mins now contain what requested
I think i got it. Thanks guys! Your ideas helped me a lot!
The following solution will do for me:
ArrayList<Integer> mins = new ArrayList<Integer>();
ArrayList<Integer> maxs = new ArrayList<Integer>();
int prevDiff = array[0] - array[1];
int i=1;
while(i<array.length-1){
int currDiff = 0;
int zeroCount = 0;
while(currDiff == 0 && i<array.length-1){
zeroCount++;
i++;
currDiff = array[i-1] - array[i];
}
int signCurrDiff = Integer.signum(currDiff);
int signPrevDiff = Integer.signum(prevDiff);
if( signPrevDiff != signCurrDiff && signCurrDiff != 0){ //signSubDiff==0, the case when prev while ended bcoz of last elem
int index = i-1-(zeroCount)/2;
if(signPrevDiff == 1){
mins.add( index );
}else{
maxs.add( index );
}
}
prevDiff = currDiff;
}

Categories

Resources