I would like to generate an index from 0 to size - 1, uniformly, but different than any index in the given set excluded.
size is around 100. There are typically 1, 2 or 3 exluded indices. Indices in excluded are unique and not sorted.
Ideally, the header will be with multiple arguments, maybe something like this:
int getRandomIndex(Random rand, int size, int... i)
Or, if this ... multi arguments are slow (are they?) we can pass simple int[] excluded array or something.
How to do it fast? getRandomIndex() is called millions of times.
static int getRandomIndex(Random rand, int size, Integer... excludes) {
List<Integer> excludeList = Arrays.asList(excludes);
int number;
do {
number = rand.nextInt(size);
} while (excludeList.contains(number));
return number;
}
You can allocate array of possible values 0..size-1, remove all known indexes and select random element from the rest.
If indexes array is sorted and all values are unique, you can do it without intermediate array of values :
int getRandomIndex(Random rand, int size, int... ii)
{
int result = rand.nextInt(size - ii.length);
for(int i : ii) {
if(result >= i) {
++result;
}
}
return result;
}
Edit: I found mistake in if condition, corrected.
EDIT:
int getRandomIndex(Random rand, int size, int i) {
int result = rand.nextInt(size - 1);
if(result >= i) {
result++;
}
}
int getRandomIndex(Random rand, int size, int i, int j) {
int result = rand.nextInt(size - 2);
if(i > j) {
int tmp = j;
j = i;
i = tmp;
}
if(result >= i) {
result++;
}
if(result >= j) {
result++;
}
return result;
}
And similar function for (i,j,k).
A function that call rand.next only one time might be faster of any function, that asks for random number several times.
I'd do it a bit differently. To pick a random number less than size but which isn't i or j, you can pick a random number between 0 and size-3 inclusive. If that number is i then return size-2 and if the number is j then return size-1. Otherwise return the original random number.
There is the edge case of i or j being within 2 of size, but I leave that to the interested reader. Actually I think it just works out OK.
This can be generalized to pick a number less than size that isn't in an array of integers. Choose a number less than size - the array length - 1.
You could use a Set fro fast look up
int getRandomIndex(Random rand, int size, Integer... i) {
return getRandomIndex(rand, size, new HashSet<Integer>(Arrays.asList(i)));
}
int getRandomIndex(Random rand, int size, Set<Integer> x) {
int result;
do {
result = (int) (rand.nextDouble() * size);
} while (x.contains(result));
return result;
}
If the set of all indices is predefined then you could have the Set x final static and spare building it every time you call the method.
EIDT
Well If performance is an issue then I would say that your first approach with while(r == i || r == j || r == k) is neither bad nor ugly, just have three overloads of your method and call the appropriate one you need, the call will look exactly the same as with a val-len-array.
You can't have an evaluation faster than (r == i || r == j || r == k)
int getRandomIndex(Random rand, int size, int i)
int getRandomIndex(Random rand, int size, int i, int j)
int getRandomIndex(Random rand, int size, int i, int j, int k)
Assuming many consecutive calls uses the same size and excluded values...
First, initializing an array of all the allowable indices
When getRandomIndex is called, simply pick a random element of this array
Code:
int[] indices;
void init(int size, Integer... excluded)
{
indices = new int[size-excluded.length];
int pos = 0;
Set<Integer> excludedSet = new HashSet<Integer>(Arrays.asList(excluded));
for (int i = 0; i < size; i++)
{
if (!excludedSet.contains(i))
{
indices[pos++] = i;
}
}
}
int getRandomIndex(Random random)
{
return indices[random.nextInt(data.length)];
}
Example usage:
init(100, 50, 23, 10);
Random random = new Random();
for (int i = 0; i < 200; i++)
{
System.out.println(getRandomIndex(random));
}
Related
So the question is
You are given a 0-indexed integer array nums and an integer k.
You are initially standing at index 0. In one move, you can jump at most k steps forward without going outside the boundaries of the array. That is, you can jump from index i to any index in the range [i + 1, min(n - 1, i + k)] inclusive.
You want to reach the last index of the array (index n - 1). Your score is the sum of all nums[j] for each index j you visited in the array.
Return the maximum score you can get.
Example 1:
Input: nums = [1,-1,-2,4,-7,3], k = 2
Output: 7
Explanation: You can choose your jumps forming the subsequence [1,-1,4,3] (underlined above). The sum is 7.
I wrote a recursive solution in which we explore all the possibilies . If the function is called at index ind , then the value at index ind is added to a variable curSum for the next function call.
The base condition is when we reach the last index , we will return curSum+value of last index.
Here is the code:
class Solution {
static int min= Integer.MIN_VALUE;
public int maxResult(int[] nums, int k) {
return max(nums,0,k,0);
}
public int max(int [] nums, int ind, int k, int curSum)
{
if(ind==nums.length-1)
return curSum+nums[ind];
int max=Integer.MIN_VALUE;
for(int i=ind+1;i<=Math.min(nums.length-1,ind+k);i++)
max=Math.max(max, max(nums,i,k,curSum+nums[ind]));
return max;
}
}
Code works fine except the exponential complexity ofcourse.
I tried memoizing it as
class Solution {
static int[] dp;
static int min= Integer.MIN_VALUE;
public int maxResult(int[] nums, int k) {
dp=new int[nums.length];
Arrays.fill(dp,min);
return max(nums,0,k,0);
}
public int max(int [] nums, int ind, int k, int curSum)
{
if(ind==nums.length-1)
return curSum+nums[ind];
if(dp[ind]!=min)
return dp[ind];
int max=Integer.MIN_VALUE;
for(int i=ind+1;i<=Math.min(nums.length-1,ind+k);i++)
max=Math.max(max, max(nums,i,k,curSum+nums[ind]));
return dp[ind]=max;
}
}
But this solution gives the wrong max everytime and I am not quite able to figure out why.
Any hints will be appreciated.
Thanks
You only need to memoize dp[index] instead of calling f(index, currSum).
Take for example present arr.length = 5, k = 2
For index-2 you need wether index 3 or 4 gives better points to you irrespective of your present point.
Better way would be :
class Solution {
static int[] dp;
static int min= Integer.MIN_VALUE;
public int maxResult(int[] nums, int k) {
dp=new int[nums.length];
Arrays.fill(dp,min);
return max(nums,0,k,0);
}
public int max(int [] nums, int ind, int k, int curSum)
{
// base-case
if(ind==nums.length-1)
return curSum+nums[ind];
// if already memoized
if(dp[ind]!=min)
return dp[ind] + curSum;
// if not memoized, calculate value now
int max=Integer.MIN_VALUE;
for(int i=ind+1;i<=Math.min(nums.length-1,ind+k);i++)
max=Math.max(max, max(nums,i,k,nums[ind]);
// memoize here
dp[ind] = max
return dp[ind] + curSum;
}
}
I am a beginner(first year uni student) programmer trying to solve this problem which i'm finding somewhat difficult. If you are to answer this question, don't provide me with a complex daunting algorithm that will leave me scratching my head. I'll really appreciate it if you explain it step my step (both logically/conceptually then through code)
The problem is as follows:image
I have tried to attempt it and my code only works for a certain case that i tested.
package com.company;
import java.lang.Math;
public class Main {
public static int[][] binary_partition(int array[], int k){
int x = (int) Math.pow(2,k);
int[][] partition = new int[((array.length/x)*2)][array.length/x];
int divisor = array.length/x;
if ((array.length % 2) != 0){
return partition;
}
if (divisor >= array.length-1){
return partition;
}
if (k==1){
return partition;
}
int p = 0;
for(int i=0;i<((array.length/x)*2);i++)
{
for (int j = 0; j<array.length/x;j++)
{
partition[i][j] = array[p];
p += 1;
}
}
return partition;
}
public static void main(String[] args){
int[] array = {3, 2, 4, 7, 8, 9, 2, 3};
int[][] result = binary_partition(array,2);
for (int[] x : result){
for (int y : x)
{
System.out.print(y + " ");
}
System.out.println();
}
}
}
Your question is unclear, but this solution creates a function that partitions an array with the right length into 2^k sets.
First, an interesting fact: using the bitshift operator << on an integer increases its value by a power of two. So to find out the size of your partition, you could write
int numPartitions = 1 << k; // Equivalent to getting the integer value of 2^k
With this fact, the function becomes
public static int[][] partition(int[] set, int k) {
if (set == null)
return null; // Don't try to partition a null reference
// If k = 0, the partition of the set is just the set
if (k == 0) {
int[][] partition = new int[1][set.length];
// Copy the original set into the partition
System.arraycopy(set, 0, partition[0], 0, set.length);
return partition;
}
int numPartitions = 1 << k; // The number of sets to partition the array into
int numElements = set.length / numPartitions; // The number of elements per partition
/* Check if the set has enough elements to create a partition and make sure
that the partitions are even */
if (numElements == 0 || set.length % numElements != 0)
return null; // Replace with an error/exception of your choice
int[][] partition = new int[numPartitions][numElements];
int index = 0;
for (int r = 0; r < numPartitions; r++) {
for (int c = 0; c < numElements; c++) {
partition[r][c] = set[index++]; // Assign an element to the partition
}
}
return partition;
}
There are a few lines of your code where the intention is not clear. For example, it is not clear why you are validating divisor >= array.length-1. Checking k==1 is also incorrect because k=1 is a valid input to the method. In fact, all your validation checks are not needed. All you need to validate is that array.length is divisible by x.
The main problem that you have seems to be that you mixed up the lengths of the resulting array.
The resulting array should have a length of array.length / x, and each of the subarrays should have a length of x, hence:
int[][] partition = new int[array.length/x][x];
If you also fix your bounds on the for loops, your code should work.
Your nested for loop can be rewritten as a single for loop:
for(int i = 0 ; i < array.length ; i++)
{
int index = i / x;
int subArrayIndex = i % x;
partition[index][subArrayIndex] = array[i];
}
You just need to figure out which indices a an element array[i] belongs by dividing and getting the remainder.
I'm trying to write this algorithm in Java following the steps below:(I know other solutions, just trying to figure out this one)
int min_diff = LARGE_NUMBER;
int diff;
for (each subset S of size n/2 of A) {
diff = abs(sum(S) – sum(A-S));
if (diff < min_diff) {
min_diff = diff;
TempSet = S;
}
}
print min_diff, TempSet;
I tried to find all subset permutations of size n/2 using the code from this link: https://www.geeksforgeeks.org/print-subsets-given-size-set/
The code in this link print all permutations. I thought first I need to store the arrays in an ArrayList so I can use them in the for loop, but I couldn't get it to work. The code below gives wrong output (every array is 60 60 60 instead of permutations:
static List<int[]> intArrays = new ArrayList<>();
static void combinationUtil(int[]arr, int n, int r, int index, int[] data, int i)
{
if (index == r) {
intArrays.add(data);
return;
}
if (i >= n)
return;
data[index] = arr[i];
combinationUtil(arr, n, r, index + 1, data, i + 1);
combinationUtil(arr, n, r, index, data, i + 1);
}
static void printCombination(int arr[], int n, int r)
{
int data[] = new int[r];
combinationUtil(arr, n, r, 0, data, 0);
for(int[] arr1:intArrays){
System.out.println(Arrays.toString(arr1));
}
}
public static void main(String[] args)
{
int arr[] = { 10, 20, 30, 40,50,60};
int n=arr.length;
int r=n/2;
printCombination(arr, n, r);
}
Can anyone tell me what's wrong with my code? Or how can I solve this problem following the above steps?
Your problem is when you do intArrays.add(data);
intArrays always contains the reference to data array. The array is passed by reference. You gets {60, 60, 60} because is the last state of data array (the last subset).
To fix the problem you must to do intArrays.add(data.Clone()); if exists Clone function or similar in you language or just implement it yourself.
Code in C#. Sorry I don't have any java compiler installed.
static int[] CloneArray(int[] arr)
{
int[] ret = new int[arr.Length];
for (int i = 0; i < arr.Length; ++i) ret[i] = arr[i];
return ret;
}
I am making a few methods that are used for finding the prime factors of a certain number. This is broken down into two functions which both use arrays. However, in both functions the code is very inefficient. First I have to count the length of the array, make a new array of that length and then use almost the exact same code to populate the array.
Is there a way I can make the array unknown width and push integers to the end of the array as I find them?
Here is my code:
public class JavaApplication7{
public static void main(String[] args) {
System.out.println(Arrays.toString(primeFactors(85251)));
}
public static int[] primeFactors(int num){
int[] factors = primesUpTo(num);
int originalNum = num;
int i = 0;
int count = 0;
while(num != 1){
if(num % factors[i] == 0){
num /= factors[i];
i = 0;
count++;
}else{
i++;
}
}
int[] primeFactors = new int[count];
i = 0;
count = 0;
while(originalNum != 1){
if(originalNum % factors[i] == 0){
originalNum /= factors[i];
primeFactors[count] = factors[i];
i = 0;
count++;
}else{
i++;
}
}
return primeFactors;
}
public static int[] primesUpTo(int upTo){
int count = 0;
int num = 2;
while(num <= upTo){
boolean isPrime = true;
for(int div = 2; div <= num / 2; div++){
isPrime = num % div == 0 ? false : isPrime;
}
count += isPrime ? 1 : 0;
num++;
}
int i = 0;
num = 2;
int[] primes = new int[count];
while(num <= upTo){
boolean isPrime = true;
for(int div = 2; div <= num / 2; div++){
isPrime = num % div == 0 ? false : isPrime;
}
if(isPrime){
primes[i] = num;
i++;
}
num++;
}
return primes;
}
}
You could use Arraylists that are more dynamic than Arrays.
However in both functions the code is very inefficient as first i have
to count the length of the array, make a new array of that length and
then use almost the exact same code to populate the array
However, you will find that Arraylists do seem dynamic but underneath they do a similar thing. They start with a size and make a copy of the underlying Array to a bigger one etc.
Another thing you can do if you know some upper bounds to how many numbers you will have to store is to implement you own container class. It can have a big array to hold the numbers and a length variable, for looping through the elements.
For example:
public class NumberContainer(){
private int[] elements;
private int numOfElements;
public NumberContainer(int size){
elements = new int[size];
numOfElements = 0;
}
//add a number
public void add(int x){
elements[numOfElements] = x;
numOfElements++;
}
//get length
public int length(){
return numOfElements;
}
}
....and so on.
This way you don't have to copy an Array to a new large one, allways assuming that you instantiate the NumberContainer with a large enough size.
Hope this helps
You can use a ArrayList which is created empty with no specific size and you can add (-> add(Object o) or remove (-> remove(int index)) anytime you want.
Use an ArrayList if you still need fast retrieval by Index. Otherwise consider a LinkedList, as add = O(1).
For LinkedList
get(int index) is O(n)
add(E element) is O(1)
add(int index, E element) is O(n)
remove(int index) is O(n)
Iterator.remove() is O(1) <--- main benefit of LinkedList<E>
ListIterator.add(E element) is O(1) <--- main benefit of LinkedList<E>
For ArrayList
get(int index) is O(1) <--- main benefit of ArrayList<E>
add(E element) is O(1) amortized, but O(n) worst-case since the array must be resized and copied
add(int index, E element) is O(n - index) amortized, but O(n) worst-case (as above)
remove(int index) is O(n - index) (i.e. removing last is O(1))
Iterator.remove() is O(n - index)
ListIterator.add(E element) is O(n - index)
When to use LinkedList over ArrayList?
I did
boolean isPrime = true;
for (int div = 2; div <= num / 2; div++) {
if (num % div == 0) {
isPrime = false;
break;
}
// Instead isPrime = num % div == 0 ? false : isPrime;
}
and the time needed went from 13 to 1 second.
Actually I wanted to try
public static int guessedPrimeCount(int upTo) {
if (upTo < 10) {
return 10;
}
return (int) (upTo / Math.log10(upTo - 1));
}
public int[] addToPrimes(int[] primes, int count, int p) {
if (count >= primes.length) {
primes = Arrays.copyOf(primes, count + 10);
}
primes[count] = p;
return primes;
}
primes = addToPrimes(primes, count, num);
++count;
The guessedPrimeCount is documented, x/log x, or x/log(x-1).
On adding a new prime p at [count], one in the worst case has to copy the entire array.
You can use an
ArrayList<Integer>
but this requires substantial memory overhead due to auto-boxing.
Or you can use the excellent GNU Trove3 libraries. These contain an TIntArrayList, which takes care of the resizing for you; and is essentially an int[] + a length field. The logic for appending to then is roughly:
double[] array = new double[10]; // Allocated space
int size = 0; // Used space
void add(int v) {
if (size == array.length) {
array = Arrays.copyOf(array, array.length * 2);
}
array[size++] = v;
}
Ok so my problem is basically, I have a matrix for example
010
101
111
just random 1s and 0s. So I have arrays that are rowcount and colcount, which count the number of ones in each row and column. So rowcount for this is {1,2,3} and colcount is {2,2,2}. Now in another method, I am given the arrays rowcount and colcount, and in that method, I am supposed to create a matrix with the counts in rowcount and colcount, but the end matrix can be different. Than the original. I think I'm supposed to exhaust all permutations until a matrix works. The base case must stay the same.
Note: Math.random cannot be used.
private static void recur(int[][] m, int[] rowcount, int[] colcount, int r, int c)
//recursive helper method
{
if(compare(m, rowcount, colcount)) //base case: if new matrix works
{
System.out.println();
System.out.println("RECREATED");
display(m, rowcount, colcount); //we're done!
System.exit(0);
}
else
{
int[] temp_r = new int[m.length];
int[] temp_c = new int[m[0].length];
count(m, temp_r, temp_c);
if(rowcount[r] > temp_r[r] && colcount[c] > temp_c[c])
m[r][c] = 1;
if(r+1 < m.length)
recur(m,rowcount,colcount,r+1,c);
if(rowcount[r] < temp_r[r] || colcount[c] < temp_c[c])
m[r][c] = 0;
if(c+1 < m[0].length)
recur(m,rowcount,colcount,r,c+1);
}
}
private static boolean compare(int[][] m, int[] rowcount, int[] colcount)
{
int[] temp_r = new int[m.length];
int[] temp_c = new int[m[0].length];
count(m, temp_r, temp_c);
for (int x = 0; x < temp_r.length; x++)
{
if(temp_r[x] != rowcount[x])
return false;
}
for (int y = 0; y < temp_c.length; y++)
{
if(temp_c[y] != colcount[y])
return false;
}
return true;
}
public static void count(int[][] matrix, int[] rowcount, int[] colcount)
{
for(int x=0;x<matrix.length;x++)
for(int y=0;y<matrix[0].length;y++)
{
if(matrix[x][y]==1)
{
rowcount[x]++;
colcount[y]++;
}
}
}
Well, I decided I'd implement a solution, but instead of Java (which you haven't actually specified the solution needs to be in), I'm going to use Groovy (which is Java based anyway)! I've tried to use Java syntax where possible, it's not hard to extrapolate the Java code from this (but it is much more verbose!)
Note:
*Generating a random bit matrix, not using Math.random()
*I'm storing my matrix in a string i.e. [[0,1],[1,0]] = "0110"
*My solution relies heavily, on converting Integers to/from BinaryStrings (which is essentially what your matrix is!)
// Generate random matrix
int colSize = 3;
int rowSize = 4;
String matrix = '';
for (int i = 0; i < rowSize; i++){
String bits = Integer.toBinaryString(System.currentTimeMillis().toInteger());
matrix += bits.substring(bits.length() - colSize);
Thread.sleep((System.currentTimeMillis() % 1000) + 1);
}
def (cols1,rows1) = getCounts(matrix, colSize)
println "matrix=$matrix rows1=$rows1 cols1=$cols1"
// Find match (brute force!)
int matrixSize = colSize * rowSize
int start = 0
int end = Math.pow(Math.pow(2, colSize), rowSize) // 2 is number of variations, i.e. 0 and 1
for (int i = start; i <= end; i++){
String tmp = leftPad(Integer.toBinaryString(i), matrixSize, '0')
def (cols2,rows2) = getCounts(tmp, colSize)
if (cols1 == cols2 && rows1 == rows2){
println "Found match! matrix=$tmp"
break;
}
}
println "Finished."
String leftPad(String input, int totalWidth, String padchar){ String.format('%1$' + totalWidth + "s", input).replace(' ',padchar) }
int[][] getCounts(String matrix, int colSize){
int rowSize = matrix.length() / colSize
int[] cols = (1..colSize).collect{0}, rows = (1..rowSize).collect{0}
matrix.eachWithIndex {ch, index ->
def intval = Integer.parseInt(ch)
cols[index % colSize] += intval
rows[(int)index / colSize] += intval
}
[cols,rows]
}
Gives output:
matrix=001100011000 rows1=[1, 1, 2, 0] cols1=[1, 1, 2]
Found match! matrix=001001110000
Finished.
Brute force search logic:
Given a rowcount of [1,2,3]
And a colcount of [2,2,2]
Iterate over all matrix combinations (i.e. numbers 0 - 511 i.e. "000000000" -> "111111111")
Until the new matrix combination's rowcount and colcount matches the supplied rowcount and colcount
OK, your question and comments indicate you are on the right track. The code itself is a bit messy and it has obviously gone through some iterations. That's not great, but it's OK.
You are right, I believe, that you have to 'exhaust' the recursion until you find a new result that matches the existing column/row counts. So, attack the problem logically. First, create a method that can compare a matrix with a row/column count. You call it 'compare(...)'. I assume this method you have already works ;-). This is the method that marks the end of the recursion. When compare returns true, you should return up the recursion 'stack'. You should not do a System.exit(...).
So, the basic rule of recursion, you need an input, output, a method body that contains an exit-condition check, and a recursive call if the condition is not met....
Your problem has a specific issue which complicates things - you need to make copies if the input matrix every time you go down a recursion level. Alternatively you need to 'undo' any changes you make when you come up a level. The 'undo' method is faster (less memory copies).
So, the process is as follows, start with an all-zero matrix. Call your recursive function for the all-zero start point.
int[][] matrix = new int[width][height];
int rpos = 0;
boolean found = recur(matrix, rowcount, colcount, 0, 0);
This is how it will be called, and found will be true if we found a solution.
The difference here from your code is that recur now returns a boolean.
So, our recur method needs to do:
1. check the current matrix - return true if it matches.
2. make meaningful changes (within the limits that we've added)
3. recursively check the change (and add other changes).
Your method does not have an output, so there's no way to escape the recursion. So, add one (boolean in this case).
The way this can work is that we start in the top left, and try it with that bit set, and with it unset. For each contition (set or unset) we recursively test whether the next bit matches when set, or unset, and so on.... :
private static boolean recur(int[][] m, int[] rowcount, int[] colcount,
int row, int col) {
if (compare(m, rowcount, colcount)) {
// our matrix matches the condition
return true;
}
if (row >= m.length) {
return false;
}
int nextcol = col + 1;
int nextrow = row;
if (nextcol >= m[row].length) {
nextcol = 0;
nextrow++;
if (nextrow > m.length) {
return false;
}
}
// OK, so nextrow and nextcol are the following position, and are valid.
// let's set our current position, and tell the next level of recursion to
// start playing from the next spot along
m[row][col] = 1;
if (recur(m, rowcount, colcount, nextrow, nextcol)) {
return true;
}
// now unset it again
m[row][col] = 0;
if (recur(m, rowcount, colcount, nextrow, nextcol)) {
return true;
}
return false;
}
The above code is just hand-written, it may have bugs, etc. but try it. The lesson in here is that you need to test your consitions, and you need a strategy....