I have a matrix of 1's (just a 2D vector of ints) and I am trying to randomly select an index so that I can turn that 1 to a 0. My goal is to select every index of the matrix exactly once so that after running a for loop with exactly as many iterations as there are indices, the matrix will be filled with 0s (the 0 doesn't actually matter, the number that replaces the 1 and the 1 itself are arbitrary).
My current approach is very slow. It has been to run a while loop that checks each pass to see if there are still any 1's left. This is obviously incredibly inefficient, but I am not sure how to do this only once for each index and ensure there are no repeats so that I can change to a for loop. Any advice would be very helpful!
Just generate a random sequence of the matrix indices as #Jonny mentioned in the comment. Then iterate through each element of this sequence. The following is a Java implementation I just wrote in case it helps:
import java.util.Random;
public class Test {
public static void randomSelectMatrixIndex(int[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
int[] indices = new int[rows*cols];
System.out.println("Index array before shuffle: ");
for (int i=0; i<indices.length; i++) {
indices[i] = i;
System.out.print(i+" ");
}
System.out.println();
System.out.println();
shuffle(indices);
System.out.println("Index array after shuffle: ");
for (int j=0; j<indices.length; j++) {
System.out.print(indices[j]+" ");
matrix[indices[j]/cols][indices[j]%cols] = 0;
}
System.out.println();
System.out.println();
}
private static void shuffle(int[] indices) {
Random ran = new Random();
for (int i=indices.length; i>0; i--) {
int randomIndex = ran.nextInt(i);
int temp = indices[i-1];
indices[i-1] = indices[randomIndex];
indices[randomIndex] = temp;
}
}
private static void printMatrix(int[][] matrix) {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) throws Exception {
int[][] matrix = {{1,1,1,1,1}, {1,1,1,1,1}, {1,1,1,1,1}, {1,1,1,1,1}};
System.out.println("Matrix before random select: ");
printMatrix(matrix);
System.out.println();
randomSelectMatrixIndex(matrix);
System.out.println("Matrix after random select: ");
printMatrix(matrix);
}
}
You use this algorithm, which is a bit more efficient, although still not very efficient after a lot of iterations (note that for best result, use a evenly distributed random number generator):
select random index -> check if 1
| | |
| repeat |False |True
|--------------------| |--Change value at index to 0
|
|
the end
I wonder if there is something one could change to make it more efficient...
Simple. Create a vector of pointers using nested loops so that there's a pointer to every single element in the matrix. Randomly select a pointer. Change value to 0. Remove pointer from vector. Repeat until vector is empty. Matrix is now empty.
Related
Im trying to create a minesweeper like simulation when 0 is clear and X is a mine the user inputs the number of mines and using a random generator places it in the 2D array. When i run it the grid print but i get java.lang.ArrayIndexOutOfBoundsException: 4 and not sure how to fix it. I have never worked with 2D arrays before.
import java.util.Scanner;
import java.util.Random;
public class Minesweeper {
private static int count = 0; /* used to count the number of mines */
public static void main ( String [] args) {
int r = 12;
int c = 12;
int ground [][] = new int [r][c]; //2D array 12 x 12
int a = 0; // variable to print 0's as an integer instead of a string
Scanner sc=new Scanner(System.in); // scanner for the user to input number of mines
System.out.print("Enter mines: ");
Random myRandom = new Random();
int N; // N is the variable for the number of mines
N = sc.nextInt(); // scanner to input the number
for (int k = 0; k < ground.length; k++) { // nested loop to print a 12 x 12 grid
for (int j = 0; j < ground.length; j++) {
System.out.print(" " + a + " " ); // prints the 0s
}
System.out.println();
}
while(count <= N) { // loop to count the mine numbers the user chose
/* if count < N, we need to put more mines */
do {
r = myRandom.nextInt(12); // generate the mines in random places
c = myRandom.nextInt(12);
} while(mineOrNot(r, c) == false);
count += 1;// count to place the right amount of mines
}
}
// function to make sure no 2 mines are in the same location
public static boolean mineOrNot(int r, int c) {
int ground [][] = new int [r][c];
// if theres no mines its ok to place one
if(ground[r][c] == 0) {
ground[r][c] = 1; // it is ok, put a mine at here
return true;
}
else
return false;
}
}
Since I don't code in Java, I can only give you the basics of why you're receiving this error. It's basically a right of passage for starting out with arrays, and even experienced programmers run into this issue from time to time in certain cases.
Array Indexing in Java
Basically, what's happening is you're attempting to access a part of this array that does not exist within the range you've set for it.
E.G. You're accessing element 13, null, and attempting to use it, causing the error.
Throw a breakpoint in if you can (don't use Java, I imagine Oracle has this functionality) and step through each iteration and try and count exactly the ticks over your array.
It should remain from 0 - 11, since array indexes in Java start at 0.
So your 1 - 12 cells become index
0 - 11.
This is driving me nuts:(
Problem statement:
An unsorted array is inputed.Next the user gives a collection of numbers and the program should print the occurrence of the given number in that array.
This should run at O(n) time complexicity.
Example:
Input array:[1, 1, 1, 2, 2, 0]
Collection of numbers:
1
2
1
0
Output:
3
2
3
1
Constrains:Array can be of size 10^5 and collection of number can be of size 10^5
P.S:I have made a code with O(n^2)
#include<stdio.h>
#include<stdlib.h>
void main(){
int *n,size,key,count=0;
scanf("%d",&size);
n=(int*)malloc(size*sizeof(int));
for(int i=0;i<size;i++){
scanf("%d",&n[i]);
}
scanf("%d",&key);
for(int i=0;i<key;i++){
count=0;
int temp=0;
scanf("%d",&temp);
for(int j=0;j<size;j++){
if(temp==n[j])
count+=1;
}
printf("\n");
if(count==0){
printf("NOT PRESENT");
}
else{
printf("%d",count);
}
}
}
Any help is welcomed :)
The range of elements is small. So create an array of counters for the possible values and increment the count for each value you find. For example, if you find 2, increment counter[2].
Then given your collection of numbers, just do an array lookup to get the count.
The time complexity is O(max(m,n)) where m is the size of the array and n is the size of the collection. The space required is O(p) where p is the range of the integers that may appear in the array. We'll use p0 to denote the lower bound of this range.
The solution is simple:
Construct an array C of size p and set all values to zero
Walk over the input array and for each value k - increase C[k-p0] by 1. Now you have a count of each value.
Walk over the collection and for each value k - print C[k-p0]
You can simply make a array of 10^5 and initialize it with 0. Now iterate over array and increment the value in array. Like you encounter a 5 increment arr[5] and now you can answer the queries in O(1) time.
Below is a code in java.
import java.util.Scanner;
public class test
{
public static void main(String args[])
{
Scanner in=new Scanner(System.in());
int n=s.nextInt();
int arr[]=new int[100001]; //Array is initialized 0
for(int i=0;i<n;i++)
{
int num=s.nextInt();
arr[num]++;
}
while(s.hasnextInt())
{
int p=s.nextInt();
System.out.println(arr[p]);
}
}
}
A very simple way to do this would be to have your resulting array's keys be where the values are.
My C skills are kind of weak, but here is how in pseudo-C (you'll have to tweak it to make it work properly:
int size = 10*10*10*10*10;
int[size] input = getInput();
int[size] results = new int[size](0); // fill array with zeros
for(int i = 0; i < size; i++) {
if (input[i] === -1)
break; // assuming -1 signifies the end of the input
output[input[i]]++; // increment the value at the index that matches the number by one
}
for(int i = 0; i < size; i++) {
if (output[i] === 0)
continue; // number wasn't in array
printf('%d', output[i]);
}
Basically, you put the input of the array in the matching index of output.
So, if your input is 5,3,2,1,1,5,3,2,1, you would put into output:
output[5]++;
output[3]++;
output[2]++;
output[1]++;
output[1]++;
output[5]++;
output[3]++;
output[2]++;
output[1]++;
resulting in an array that looks like this:
[0, 3, 2, 2, 0, 1]
Then you just output it, skipping the zeros because they weren't present.
Given two sorted arrays of integers, a and b, and an integer c, I have to find i,j such that:
a[i] + b[j] <= c
and a[i] + b[j] is large as possible.
The best solution I can think of is in O(nlogn) time, taking every integer from first array and finding the lower bound of "c-a[i]".
Can anyone suggest me a better way to do this (maybe in O(n) time)?
Thinking a bit about it, then you could ask yourself:
"Is it necessary, each time, to search in the sorted b-array for successive values from a[]?"
I think you dont have to search the whole array b[] next time.......u have to search in between starting of array b and the lowest bound u found till now....for the next element in a[].It would definitely reduce your time complexity...and when u find the given target 'c' you must stop your search.
The below solution is in linear Time Complexity O(n), Space Complexity O(1)
public class ClosestPair {
public static void main(String[] args)
{
int ar2[] = {4, 5, 7};
int ar1[] = {10, 20, 30, 40};
int x = 10 ;
closest(ar1,ar2,x);
}
public static void closest(int[] ar1, int[] ar2, int x)
{ int diff=Integer.MAX_VALUE;
int first_num=0;
int second_num=0;
int second_diff=Integer.MAX_VALUE;
for(int i=0; i<ar1.length; i++)
{
if(x==ar1[i] )
{
System.out.println("no pair possible");
return;
}
}
for(int i=0; i<ar2.length; i++)
{
if(x==ar2[i])
{
System.out.println("no pair possible");
return;
}
}
for(int i=0; i<ar2.length; i++)
{
if(Math.abs(x-ar2[i])<=diff)
{
diff=Math.abs(x-ar2[i]);
first_num=ar2[i];
}
}
diff=x-first_num;
for(int i=0; i<ar1.length; i++)
{
if(Math.abs(diff-ar1[i])<=second_diff)
{
second_diff= Math.abs(diff-ar1[i]);
second_num= ar1[i];
}
}
System.out.println(first_num + " "+ second_num);
}
}
Very basic query here from a beginner...
I'm looking to find the frequency of a number within an array...
In the (mangled) code below I have tried to calculate the occurances of the number 5 in the array
I'm running into problem in formulating the for loop
Heres my code attempt:
//Compute the frequency of 5 in the array named numbers
public class find //Begin class
{
public static void main (String []args) //Begin main
{
double numbers[] = {6,7,12,5,4,2,4,6,9,5,7,11,1,23,32,45,5}; //Initialise and populate array
int total = 0;
int counter = 0;
for (int x : numbers)
{
if (numbers[] == 5; counter ++)
{System.out.println( numbers[i] + " ");
}
}
// end code
// *****************
int numbers[] = {6,7,12,5,4,2,4,6,9,5,7,11,1,23,32,45,5};
for(int x : numbers) {
if(x == 5)
counter++;
}
System.out.println(counter);
I can see that you were trying to use a for each loop in your implementation.
#Code Whisperer provides a good alternative to that, but if you do want to use a for each loop then you have to make sure you loop type and array type match. In your case, your array is type double but your loop type is int. Within each iteration, you're selecting an individual value in the array, so you don't need to include any brackets.
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == 5) {
counter++;
System.out.println(counter); // shows how many 5s you have so far
}
}
Loop through array, compare every element in the array to 5. If it is 5, increment counter by 1.
We have an array and it is unsorted. We know the range is [0,n].
We want to remove duplicates but we cannot use extra arrays and it must run in linear time.
Any ideas? Just to clarify, this is not for homework!
If the integers are limited 0 to n, you can move through the array, placing numbers by their indices. Every time you replace a number, take the value that used to be there and move it to where it should be. For instance, let's say we have an array of size 8:
-----------------
|3|6|3|4|5|1|7|7|
-----------------
S
Where S is our starting point, and we'll use C to keep track of our "current" index below.
We start with index 0, and move 3 to the 3 index spot, where 4 is. Save 4 in a temp var.
-----------------
|X|6|3|3|5|1|7|7| Saved 4
-----------------
S C
We then put 4 in the index 4, saving what used to be there, 5.
-----------------
|X|6|3|3|4|1|7|7| Saved 5
-----------------
S C
Keep going
-----------------
|X|6|3|3|4|5|7|7| Saved 1
-----------------
S C
-----------------
|X|1|3|3|4|5|7|7| Saved 6
-----------------
S C
-----------------
|X|1|3|3|4|5|6|7| Saved 7
-----------------
S C
When we try to replace 7, we see a conflict, so we simply don't place it. We then continue from the starting index S, increment it by 1:
-----------------
|X|1|3|3|4|5|6|7|
-----------------
S
1 is fine here, 3 needs to move
-----------------
|X|1|X|3|4|5|6|7|
-----------------
S
But 3 is a duplicate, so we throw it away and keep iterating through the rest of the array.
So basically, we move each entry at most 1 time, and iterate through the entire array. That's O(2n) = O(n)
void printRepeating(int arr[], int size)
{
int i;
printf("The repeating elements are: \n");
for(i = 0; i < size; i++)
{
if(arr[abs(arr[i])] >= 0)
arr[abs(arr[i])] = -arr[abs(arr[i])];
else
printf(" %d ", abs(arr[i]));
}
}
Assume int a[n] is an array of integers in the range [0,n-1]. Note that this differs slightly from the stated problem, but I make this assumption to make clear how the algorithm works. The algorithm can be patched up to work for integers in the range [0,n].
for (int i=0; i<n; i++)
{
if (a[i] != i)
{
j = a[i];
k = a[j];
a[j] = j; // Swap a[j] and a[i]
a[i] = k;
}
}
for (int i=0; i<n; i++)
{
if (a[i] == i)
{
printf("%d\n", i);
}
}
Can you sort? Sort with Radix Sort - http://en.wikipedia.org/wiki/Radix_sort with complexity O(arraySize) for given case and then remove duplicates from sorted array O(arraySize).
Walk through the array assign array[array[i]] = -array[array[i]]; if not negative; if its already negative then its duplicate, this will work since all values are within 0 and n.
Extending #Joel Lee's code for completion.
#include <iostream>
void remove_duplicates(int *a, int size)
{
int i, j, k;
bool swap = true;
while(swap){
swap = false;
for (i=0; i<size; i++){
if(a[i] != i && a[i] != a[a[i]]){
j = a[i];
k = a[j];
a[i] = k;
a[j] = j;
swap = true;
}
}
}
}
int main()
{
int i;
//int array[8] = {3,6,3,4,5,1,7,7};
int array[8] = {7,4,6,3,5,4,6,2};
remove_duplicates(array, sizeof(array)/sizeof(int));
for (int i=0; i<8; i++)
if(array[i] == i)
std::cout << array[i] << " ";
return 0;
}
With ES6 I think this can be solved with only a few lines reducing the array into an object and then using object.keys to get array without duplicates. This probably takes more memory. I'm not sure.
I did it like this:
var obj = array.reduce(function (acc, elem) {
acc[elem] = true;
return acc;
},{});
var uniqueArray = Object.keys(obj);
This has the added bonus (or disadvantage) of sorting the array. It works with strings too.
Use the array a a container with negative sign as an indicator, this will corrupt the input though.