Suppose I have a 1D array, and I want to find peaks. The difference from classic peak finding is that I need to check not only its neighbors, but I need to check n left neighbors and n right neighbors. For example my array is following:
[1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1]
And n = 4. I need to check every subarray with length 4 + 1 + 4 and see if the middle element is the maximum.
In the case:
[5,6,7,8,9,8,7,6,5], 9 is the peak.
But this does not sound very efficient. So what can be a better solution? When I find a peak, I can ignore the next n elements I think.
Try to avoid unimportant comparison. Example
public class NewClass12 {
static int [] arr = {1,2,3,4,5,3,2,1,0,9,7,6,5,4,3,2,1};
public static void main(String [] args){
int n = 4; //bounds
boolean peakFound = false;
int peak = 0;
//iterate of data
for(int k = n; k<=arr.length-n+1;k++){
//check data within bounds
for (int i = 1;i <=n;i++){
if(arr[k]<arr[k-i] || arr[k]<arr[k+i]){
peakFound = false;
break;
}
else{
peakFound = true;
peak = arr[k];
}
}
if(peakFound)
System.out.println(peak);
}
}
}
Related
Write a function:
class Solution{
public int solution(int[] A);
}
that, given an array A of N integers, returns the smallest positive integer(greater than 0)
that does not occur in A.
For example, given A = [1,3,6,4,1,2], the function should return 5.
Given A = [1,2,3], the function should return 4.
Given A = [-1, -3], the function should return 1.
Write an efficient algorithm for the following assumptions.
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [-1,000,000..1,000,000].
I wrote the following algorithm in Java:
public class TestCodility {
public static void main(String args[]){
int a[] = {1,3,6,4,1,2};
//int a[] = {1,2,3};
//int b[] = {-1,-3};
int element = 0;
//checks if the array "a" was traversed until the last position
int countArrayLenght = 0;
loopExtern:
for(int i = 0; i < 1_000_000; i++){
element = i + 1;
countArrayLenght = 0;
loopIntern:
for(int j = 0; j < a.length; j++){
if(element == a[j]){
break loopIntern;
}
countArrayLenght++;
}
if(countArrayLenght == a.length && element > 0){
System.out.println("Smallest possible " + element);
break loopExtern;
}
}
}
}
It does the job but I am pretty sure that it is not efficient. So my question is, how to improve this algorithm so that it becomes efficient?
You should get a grasp on Big O, and runtime complexities.
Its a universal construct for better understanding the implementation of efficiency in code.
Check this website out, it shows the graph for runtime complexities in terms of Big O which can aid you in your search for more efficient programming.
http://bigocheatsheet.com/
However, long story short...
The least amount of operations and memory consumed by an arbitrary program is the most efficient way to achieve something you set out to do with your code.
You can make something more efficient by reducing redundancy in your algorithms and getting rid of any operation that does not need to occur to achieve what you are trying to do
Point is to sort your array and then iterate over it. With sorted array you can simply skip all negative numbers and then find minimal posible element that you need.
Here more general solution for your task:
import java.util.Arrays;
public class Main {
public static int solution(int[] A) {
int result = 1;
Arrays.sort(A);
for(int a: A) {
if(a > 0) {
if(result == a) {
result++;
} else if (result < a){
return result;
}
}
}
return result;
}
public static void main(String args[]){
int a[] = {1,3,6,4,1,2};
int b[] = {1,2,3};
int c[] = {-1,-3};
System.out.println("a) Smallest possible " + solution(a)); //prints 5
System.out.println("b) Smallest possible " + solution(b)); //prints 4
System.out.println("c) Smallest possible " + solution(c)); //prints 1
}
}
Complexity of that algorithm should be O(n*log(n))
The main idea is the same as Denis.
First sort, then process but using java8 feature.
There are few methods that may increase timings.(not very sure how efficient java 8 process them:filter,distinct and even take-while ... in the worst case you have here something similar with 3 full loops. One additional loop is for transforming array into stream). Overall you should get the same run-time complexity.
One advantage could be on verbosity, but also need some additional knowledge compared with Denis solution.
import java.util.function.Supplier;
import java.util.stream.IntStream;
public class AMin
{
public static void main(String args[])
{
int a[] = {-2,-3,1,2,3,-7,5,6};
int[] i = {1} ;
// get next integer starting from 1
Supplier<Integer> supplier = () -> i[0]++;
//1. transform array into specialized int-stream
//2. keep only positive numbers : filter
//3. keep no duplicates : distinct
//4. sort by natural order (ascending)
//5. get the maximum stream based on criteria(predicate) : longest consecutive numbers starting from 1
//6. get the number of elements from the longest "sub-stream" : count
long count = IntStream.of(a).filter(t->t>0).distinct().sorted().takeWhile(t->t== supplier.get()).count();
count = (count==0) ? 1 : ++count;
//print 4
System.out.println(count);
}
}
There are many solutions with O(n) space complexity and O(n) type complexity. You can convert array to;
set: array to set and for loop (1...N) check contains number or not. If not return number.
hashmap: array to map and for loop (1...N) check contains number or not. If not return number.
count array: convert given array to positive array count array like if arr[i] == 5, countArr[5]++, if arr[i] == 1, countArr[1]++ then check each item in countArr with for loop (1...N) whether greate than 1 or not. If not return it.
For now, looking more effective algoritm like #Ricola mentioned. Java solution with O(n) time complexity and O(1) space complexity:
static void swap(final int arr[], final int i,final int j){
final int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static boolean isIndexInSafeArea(final int arr[], final int i){
return arr[i] > 0 && arr[i] - 1 < arr.length && arr[i] != i + 1 ;
}
static int solution(final int arr[]){
for (int i = 0; i < arr.length; i++) {
while (isIndexInSafeArea(arr,i) && arr[i] != arr[arr[i] - 1]) {
swap(arr, i, arr[i] - 1);
}
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] != i + 1) {
return i+1;
}
}
return arr.length + 1;
}
I am trying to calculate the Big-O time complexity for these 3 algorithms, but seems like I have a lack of knowledge on this topic.
1st:
private void firstAlgorithm(int size) {
int[] array = new int[size];
int i=0; int flag=0;
while(i<size) {
int num=(int)(Math.random()*(size));
if (num==0 && flag==0) {
flag=1;
array[i]=0;
i++;
} else if(num==0 && flag==1) {
continue;
} else if(!checkVal(num, array)) {
array[i]=num;
i++;
}
}
}
private static boolean checkVal(int val, int[] arr) {
int i = 0;
for (int num:arr) {
if (num==val) {
return true;
}
}
return false;
}
2nd:
private void secondAlgorithm(int size) {
int i = 0;
int[] array = new int[size];
boolean[] booleanArray = new boolean[size];
while (i < array.length) {
int num = (int) (Math.random() * array.length);
if (!booleanArray[num]) {
booleanArray[num] = true;
array[i] = num;
i++;
}
}
}
3rd:
private void thirdAlgorithm(int size) {
int[] array = new int[size];
for (int i = 0; i < array.length; i++) {
int num = (int) (Math.random() * (i - 1));
if (i > 0) {
array = swap(array, i, num);
}
}
}
private static int[] swap(int[] arr, int a, int b) {
int i = arr[a];
arr[a] = arr[b];
arr[b] = i;
return arr;
}
Would be nice, if you could explain your results.
In my opinion, 1st - O(n^2) because of two loops, 2nd don't know, 3rd O(n)
THank you
I assume that in all your algorithms, where you are generating a random number, you meant to take the remainder of the generated number, not multiplying it with another value (example for the first algorithm: Math.random() % size). If this is not the case, then any of the above algorithms have a small chance of not finishing in a reasonable amount of time.
The first algorithm generates and fills an array of size integers. The rule is that the array must contain only one value of 0 and only distinct values. Checking if the array already contains a newly generated value is done in O(m) where m is the number of elements already inserted in the array. You might do this check for each of the size elements which are to be inserted and m can get as large as size, so an upper bound of the running-time is O(size^2).
The second algorithm also generates and fills an array with random numbers, but this time the numbers need not be distinct, so no need to run an additional O(m) check each iteration. The overall complexity is given by the size of the array: O(size).
The third algorithm generates and fills an array with random numbers and at each iteration it swaps some elements based on the given index, which is a constant time operation. Also, reassigning the reference of the array to itself is a constant time operation (O(1)). It results that the running-time is bounded by O(size).
I was trying to solve this practice problem, it is also quoted below.
The Chef is planning a buffet for the DirectiPlex inauguration party,
and everyone is invited. On their way in, each guest picks up a sheet
of paper containing a random number (this number may be repeated). The
guests then sit down on a round table with their friends.
The Chef now decides that he would like to play a game. He asks you to pick a random person from your table and have them read their
number out loud. Then, moving clockwise around the table, each person
will read out their number. The goal is to find that set of numbers
which forms an increasing subsequence. All people owning these
numbers will be eligible for a lucky draw! One of the software
developers is very excited about this prospect, and wants to maximize
the number of people who are eligible for the lucky draw. So, he
decides to write a program that decides who should read their number
first so as to maximize the number of people that are eligible for the
lucky draw. Can you beat him to it?
Input The first line contains t, the number of test cases (about 15). Then t test cases follow. Each test case consists of two
lines:
The first line contains a number N, the number of guests invited to
the party.
The second line contains N numbers a1, a2, ..., an separated by
spaces, which are the numbers written on the sheets of paper in
clockwise order.
Output For each test case, print a line containing a single number which is the maximum number of guests that can be eligible for
participating the the lucky draw.
Here's the solution that I have come up with
// http://www.codechef.com/problems/D2/
import java.io.*;
import java.util.*;
public class D2
{
public static void main(String [] args)
throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int numTestCases = Integer.parseInt(br.readLine());
for(int _t=0; _t<numTestCases; ++_t)
{
int N = Integer.parseInt(br.readLine());
StringTokenizer strtok = new StringTokenizer(br.readLine());
int [] originalArray = new int[N*2];
for(int i=0; i<N; ++i)
{
//this concatenates the array with itself at the time of reading the input itself
originalArray[i] = originalArray[N+i] = Integer.parseInt(strtok.nextToken());
}
//Now we calculate the length of the longest increasing sequence
int maxWinners = new LongestIncreasingSequence(originalArray).lengthOfLongestIncreasingSequence();
System.out.println(maxWinners);
}
}
}
class LongestIncreasingSequence
{
private int [] array;
private int [] longest;
private int subsequence_size;
public LongestIncreasingSequence(int [] A)
{
array = A;
longest = new int[array.length / 2];
longest[0] = array[0];
subsequence_size = 1;
}
public int lengthOfLongestIncreasingSequence()
{
for(int i=1; i<array.length; ++i)
{
if(array[i] < longest[0])
{
longest[0] = array[i];
}
else if(array[i] > longest[subsequence_size - 1])
{
longest[subsequence_size++] = array[i];
}
else
{
//Make the replacement with binary search
longest[getReplacementIndex(array[i])] = array[i];
}
}
return subsequence_size;
}
//Method to find the correct index using binary search
private int getReplacementIndex(int elem)
{
int left, right, mid;
left = 0; right = subsequence_size - 1;
while(right - left > 1)
{
mid = 1 + (right - left) / 2;
if(array[mid] >= elem)
{
if(mid != right) right = mid;
else --right;
}
else
{
left = mid;
}
}
return right;
}
}
The complexity is O(n(log(n)) I'm finding the Longest Increasing Sequence by concatenating the array with itself.
This however doesn't pass the time requirement, can someone help me speed up this implementation.
I would not do N rotations, but instead determine the longest (cyclic) run in one go. It is certainly doable, you just have to take care warping around at the end of the array.
I'm trying to write an algorithm that will let me iterate over all desired points within an n-dimensional space to find the minimum of a function f(x) where x is a vector of size n.
Obviously, searching a 2-d or 3-d space is fairly straightforward, you can simply do:
for(int i = 0; i < x; i++) {
for(int j = 0; j < y; j++) {
//and so on for however many dimensions you want
Unfortunately, for my problem, the dimensionality of the space is not fixed (I'm writing a generalised minimum finder for many functions in a statistical program) and so I'd have to write loops for each value of n I want to use - which might ultimately be rather large.
I've been trying to get my head around how I could do this using recursion but can't quite see the solution - although I'm sure there is one there.
The solution doesn't have to be recursive, but it must be general and efficient (the inner most line in that nested loop is going to get called an awful lot...).
The way I'm representing the volume to search is a 2d array of double:
double[][] space = new double[2][4];
This would represent a 4d space with the minimum and maximum bound in each dimension in position 0 or 1 of the array, respectively. Eg:
dim 0 1 2 3
min(0):-10 5 10 -0.5
max(1): 10 55 99 0.2
Any ideas?
Here is the general idea:
interface Callback {
void visit(int[] p); // n-dimensional point
}
// bounds[] - each number the limits iteration on i'th axis from 0 to bounds[i]
// current - current dimension
// callback - point
void visit(int[] bounds, int currentDimension, int[] p, Callback c) {
for (int i = 0; i < bounds[currentDimension]; i++) {
p[currentDimension] = i;
if (currentDimension == p.length - 1) c.visit(p);
else visit(bounds, currentDimension + 1, p, c);
}
}
/// now visiting
visit(new int[] {10, 10, 10}, 0, new int[3], new Callback() {
public void visit(int[] p) {
System.out.println(Arrays.toString(p));
}
});
I'd stick with reucrsion, and use Object as a parameter, with an extra parameter of dim, and cast it when you reach a depth of 1 to the relevant array [in my example, it is an int[]]
public static int getMin(Object arr, int dim) {
int min = Integer.MAX_VALUE;
//stop clause, it is 1-dimensional array - finding a min is trivial
if (dim == 1) {
for (int x : ((int[])arr)) {
min = Math.min(min,x);
}
//else: find min among all elements in an array of one less dimenstion.
} else {
for (Object o : ((Object[])arr)) {
min = Math.min(min,getMin(o,dim-1));
}
}
return min;
}
example:
public static void main(String[] args) {
int[][][] arr = { { {5,4},{2}, {35} } , { {2, 1} , {0} } , {{1}}};
System.out.println(getMin(arr, 3));
}
will produce:
0
The advantage of this approach is no need for any processing of the array - you just send it as it is, and send the dimension as a parameter.
The downside - is type [un]safety, since we dynamically cast the Object to an array.
Another option is to iterate from 0 to x*y*z*... like you do when converting a number between binary and decimal representations. This is a non-recursive solution, so you won't run into performance issues.
ndims = n;
spacesize = product(vector_sizes)
int coords[n];
for (i = 0; i < spacesize; i++) {
k = i;
for (j = 0; j < ndims; j++ ) {
coords[j] = k % vector_sizes[j];
k /= vector_sizes[j];
}
// do something with this element / these coords
}
n-dimensional arrays can be flattened into one-dimensional arrays. What you need is to do the math for these things:
Calculate the size of the unidimensional array needed.
Figure out the formulas needed to translate back from the n-dimensional index to the unidimensional one.
This is what I'd do:
Represent n-dimensional array sizes and indexes as int[]. So, the size of a 5x7x13x4 4-dimensional array represented as the 4-element array `{ 5, 7, 13, 4 }'.
An n-dimensional array is represented as a unidimensional array whose size is the product of the sizes of each of the dimensions. So a 5x7x13x4 array would be represented as a flat array of size 1,820.
An n-dimensional index is translated into a unique index in the flat array by multiplication and addition. So, the index <3, 2, 6, 0> into the 5x7x13x4 array is translated as 3 + 2*5 + 6*5*7 + 0*5*7*13 == 223. To access that 4-dimensional index, access index 223 in the flat array.
You can also translate backwards from flat array indexes to n-dimensional indexes. I'll leave that one as an exercise (but it's basically doing n modulo calculations).
Isn't the function just:
Function loopDimension(int dimensionNumber)
If there is no more dimension, stop;
for(loop through this dimension){
loopDimension(dimensionNumber + 1);
}
This runs through a List of List of values (Integers) and picks the minimum of each List:
import java.util.*;
/**
MultiDimMin
#author Stefan Wagner
#date Fr 6. Apr 00:37:22 CEST 2012
*/
public class MultiDimMin
{
public static void main (String args[])
{
List <List <Integer>> values = new ArrayList <List <Integer>> ();
Random r = new Random ();
for (int i = 0; i < 5; ++i)
{
List<Integer> vals = new ArrayList <Integer> ();
for (int j = 0; j < 25; ++j)
{
vals.add (100 - r.nextInt (200));
}
values.add (vals);
}
showAll (values);
List<Integer> res = multiDimMin (values);
show (res);
}
public static int minof (List <Integer> in)
{
int res = in.get (0);
for (int v : in)
if (res > v) res = v;
return res;
}
public static List<Integer> multiDimMin (List <List <Integer>> in)
{
List<Integer> mins = new ArrayList <Integer> ();
for (List<Integer> li : in)
mins.add (minof (li));
return mins;
}
public static void showAll (List< List <Integer>> lili)
{
for (List <Integer> li : lili) {
show (li);
System.out.println ();
}
}
public static void show (List <Integer> li)
{
for (Integer i: li) {
System.out.print (" " + i);
}
System.out.println ();
}
}
I've just been looking at the following piece of code
package test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(final String[] args) {
final int sizeA = 3;
final int sizeB = 5;
final List<int[]> combos = getAllCombinations(sizeA-1, sizeB);
int counter = 1;
for(final int[] combo : combos) {
System.out.println("Combination " + counter);
System.out.println("--------------");
for(final int value : combo) {
System.out.print(value + " ");
}
System.out.println();
System.out.println();
++counter;
}
}
private static List<int[]> getAllCombinations(final int maxIndex, final int size) {
if(maxIndex >= size)
throw new IllegalArgumentException("The maximum index must be smaller than the array size.");
final List<int[]> result = new ArrayList<int[]>();
if(maxIndex == 0) {
final int[] array = new int[size];
Arrays.fill(array, maxIndex);
result.add(array);
return result;
}
//We'll create one array for every time the maxIndex can occur while allowing
//every other index to appear, then create every variation on that array
//by having every possible head generated recursively
for(int i = 1; i < size - maxIndex + 1; ++i) {
//Generating every possible head for the array
final List<int[]> heads = getAllCombinations(maxIndex - 1, size - i);
//Combining every head with the tail
for(final int[] head : heads) {
final int[] array = new int[size];
System.arraycopy(head, 0, array, 0, head.length);
//Filling the tail of the array with i maxIndex values
for(int j = 1; j <= i; ++j)
array[size - j] = maxIndex;
result.add(array);
}
}
return result;
}
}
I'm wondering, how do I eliminate recursion from this, so that it returns a single random combination, rather than a list of all possible combinations?
Thanks
If I understand your code correctly your task is as follows: give a random combination of numbers '0' .. 'sizeA-1' of length sizeB where
the combination is sorted
each number occurs at least once
i.e. in your example e.g. [0,0,1,2,2].
If you want to have a single combination only I'd suggest another algorithm (pseudo-code):
Randomly choose the step-up positions (e.g. for sequence [0,0,1,1,2] it would be steps (1->2) & (3->4)) - we need sizeA-1 steps randomly chosen at sizeB-1 positions.
Calculate your target combination out of this vector
A quick-and-dirty implementation in java looks like follows
// Generate list 0,1,2,...,sizeB-2 of possible step-positions
List<Integer> steps = new ArrayList<Integer>();
for (int h = 0; h < sizeB-1; h++) {
steps.add(h);
}
// Randomly choose sizeA-1 elements
Collections.shuffle(steps);
steps = steps.subList(0, sizeA - 1);
Collections.sort(steps);
// Build result array
int[] result = new int[sizeB];
for (int h = 0, o = 0; h < sizeB; h++) {
result[h] = o;
if (o < steps.size() && steps.get(o) == h) {
o++;
}
}
Note: this can be optimized further - the first step generates a random permutation and later strips this down to desired size. Therefore it is just for demonstration purpose that the algorithm itself works as desired.
This appears to be homework. Without giving you code, here's an idea. Call getAllCombinations, store the result in a List, and return a value from a random index in that list. As Howard pointed out in his comment to your question, eliminating recursion, and returning a random combination are separate tasks.