i am writing the function to check if the given value is included in the matrix in . This matrix has the following properties:
•Integers in each row are sorted in ascending from left to right.
•Integers in each column are sorted in ascending from top to bottom
public static boolean searchMatrix(int target, int[][] matrix)
{
for(int i = 0;i <= matrix[0].length;i++)
{
for (int j=i; j<matrix.length;j++)
{
if(target == matrix[i][j])
return true;
}
}
return false;
}
i want to know weather this program has time complexity of O(N).
if not what changes should i make to get into O(N).
I think the search can be done in linear time. Consider the following 4×4 matrix as a visual:
1 2 4 6
2 3 5 7 ascending from left to right
3 4 6 8 and from top to bottom
4 5 6 9
If we were searching for the value 5 we could begin in the upper left, and then walk to the right until we have either found the value, or encountered a number which is greater than the target of 5. In this case, we hit 6. Then, we can rollback to 4, and advance down to a higher row. It is guaranteed that every previous value in the first row is less than the target and that every value in the next row from that column onwards is greater than the value on the first row.
This is a roughly linear approach. A good analogy would be walking around the perimeter of a mountain, looking for a certain elevation. If at each spot we either don't find the height we want, or find only points too high, we keep walking.
The way you have it written (brute force computation) has a worst case time complexity of O(N^2). Since you say that the arrays are sorted, you can instead implement binary search which will have a worst case time complexity of N(2*log(N)).
Assuming a n x m matrix, your algorithm is O(n * m), because it (potentially) iterates all rows and columns (ie all elements).
However, there exists an algorithm that is O(log(m + n)).
Because this is for an on-line coding interview (I am psychic), I will give you hints only:
Given elements at coordinate (x, y), what can know about where the target might be?
What could you do if you treated x and y separately?
you say the matrix is sorted ,may you can use binary search to find the target . and use two individual one layer loop , firstly search row ,then column.it's o(N/2).
As stated your algorithm is O(N*M) or O(N^2) for a square matrix.
You can do it with a single loop:
Basically starting from the top right you check the cell if the number is too big move left if the number is too small move down. If you fall off the edge on either side the number's not there.
boolean searchMatrix(int target, int[][] mat)
{
int i = 0, j = mat[0].length;
while (i < mat.length && j >= 0)
{
if (mat[i][j] == target)
{
return true;
}
else if (mat[i][j] < target)
{
i++;
}
else
{
j--;
}
}
return false;
}
Related
I have been struggling to solve an array problem with linear time,
The problem is:
Assuming we are given an array A [1...n] write an algorithm that return true if:
There are two numbers in the array x,y that have the following:
x < y
x repeats more than n/3 times
y repeats more than n/4 times
I have tried to write the following java program to do so assuming we have a sorted array but I don't think it is the best implementation.
public static boolean solutionManma(){
int [] arr = {2,2,2,3,3,3};
int n = arr.length;
int xCount = 1;
int yCount = 1;
int maxXcount= xCount,maxYCount = yCount;
int currX = arr[0];
int currY = arr[n-1];
for(int i = 1; i < n-2;i++){
int right = arr[n-2-i+1];
int left = arr[i];
if(currX == left){
xCount++;
}
else{
maxXcount = Math.max(xCount,maxXcount);
xCount = 1;
currX = left;
}
if(currY == right){
yCount++;
}
else {
maxYCount = Math.max(yCount,maxYCount);
yCount = 1;
currY = right;
}
}
return (maxXcount > n/3 && maxYCount > n/4);
}
If anyone has an algorithm idea for this kind of issue (preferably O(n)) I would much appreciate it because I got stuck with this one.
The key part of this problem is to find in linear time and constant space the values which occur more than n/4 times. (Note: the text of your question says "more than" and the title says "at least". Those are not the same condition. This answer is based on the text of your question.)
There are at most three values which occur more than n/4 times, and a list of such values must also include any value which occurs more than n/3 times.
The algorithm we'll use returns a list of up to three values. It only guarantees that all values which satisfy the condition are in the list it returns. The list might include other values, and it does not provide any information about the precise frequencies.
So a second pass is necessary, which scans the vector a second time counting the occurrences of each of the three values returned. Once you have the three counts, it's simple to check whether the smallest value which occurs more than n/3 times (if any) is less than the largest value which occurs more than n/4 times.
To construct the list of candidates, we use a generalisation of the Boyer-Moore majority vote algorithm, which finds a value which occurs more than n/2 times. The generalisation, published in 1982 by J. Misra and D. Gries, uses k-1 counters, each possibly associated with a value, to identify values which might occur more than 1/k times. In this case, k is 4 and so we need three counters.
Initially, all of the counters are 0 and are not associated with any value. Then for each value in the array, we do the following:
If there is a counter associated with that value, we increment it.
If no counter is associated with that value but some counter is at 0, we associate that counter with the value and increment its count to 1.
Otherwise, we decrement every counter's count.
Once all the values have been processed, the values associated with counters with positive counts are the candidate values.
For a general implementation where k is not known in advance, it would be possible to use a hash-table or other key-value map to identify values with counts. But in this case, since it is known that k is a small constant, we can just use a simple vector of three value-count pairs, making this algorithm O(n) time and O(1) space.
I will suggest the following solution, using the following assumption:
In an array of length n there will be at most n different numbers
The key feature will be to count the frequency of occurance for each different input using a histogram with n bins, meaning O(n) space. The algorithm will be as follows:
create a histogram vector with n bins, initialized to zeros
for index ii in the length of the input array a
2.1. Increase the value: hist[a[ii]] +=1
set found_x and found_y to False
for the iith bin in the histogram, check:
4.1. if found_x == False
4.1.1. if hist[ii] > n/3, set found_x = True and set x = ii
4.2. else if found_y == False
4.2.1. if hist[ii] > n/4, set y = ii and return x, y
Explanation
In the first run over the array you document the occurance frequency of all the numbers. In the run over the histogram array, which also has a length of n, you check the occurrence. First you check if there is a number that occurred more than n/3 times and if there is, for the rest of the numbers (by default larger than x due to the documentation in the histogram) you check if there is another number which occurred more than n/4 times. if there is, you return the found x and y and if there isn't you simply return not found after covering all the bins in the histogram.
As far as time complexity, you goover the input array once and you go over the histogram with the same length once, therefore the time complexity is O(n) is requested.
Problem 15:
Starting in the top left corner of a 2×2 grid, there are 6 routes (without backtracking) to the bottom right corner.
How many routes are there through a 20×20 grid?
So my attempt at Problem 15 is kinda bruteforcy because I try to get permutations of all of the possible valid paths by going from right to left and changing the predecessor of the first change of direction. For example, when I have a 2x2 grid (look at the Problem 15 link graphics) the first path I'll take is right - right - down - down and the last one I'll take is down - down - right - right, which is also my termination criteria. I add the possible valid paths into a list and also use that list to determine whether the valid path has been already added or not. And to permutate a path I'll do what I've mentioned earlier: I go from right to left in my array (Which in the graphic would be the bottom right corner where the arrowhead points at) and change the first element of which the next element is different from itself. So right - right - down - down would become right - right - right - down, which is obviously invalid since you have to have the same amount of rights and downs to be able to reach the end corner. So what I thought is to make another loop going from left to right and change as many elements as needed to get a valid path. So in this example right - right - right - down becomes down - right - right - down.
Also, what I forgot is that I'm not counting the points, I'm counting the edges from top left corner to bottom right corner.
So I have already written some code, but it doesn't work at all.
package projecteuler;
import java.util.ArrayList;
public class Projecteuler {
public static final int GRIDSIZE = 2;
public static void main(String[] args) {
ArrayList<boolean[]> paths = new ArrayList<>();
paths.add(new boolean[GRIDSIZE * 2]);
for(int i = 0; i < GRIDSIZE; i++) {
paths.get(0)[i] = true;
paths.get(0)[GRIDSIZE * 2 - 1 - i] = false;
}
boolean[] buf = paths.get(0).clone();
printArr(buf);
boolean tmp;
while(!checkTerminate(paths)) {
while(paths.contains(buf)) {
tmp = buf[buf.length - 1];
for(int i = buf.length - 1; buf[i - 1] != tmp && 0 < i; i--) {
buf[i] = !buf[i];
for(int j = 0; checkValid(buf) && j < i; j++)
buf[j] = !buf[j];
}
}
paths.add(buf.clone());
printArr(buf);
}
System.out.println(paths.size());
}
public static boolean checkTerminate(ArrayList<boolean[]> paths) {
boolean[] endPath = new boolean[GRIDSIZE * 2];
for(int i = 0; i < GRIDSIZE; i++) {
endPath[i] = false;
endPath[GRIDSIZE * 2 - 1 - i] = true;
}
return paths.contains(endPath);
}
public static boolean checkValid(boolean[] arr) {
int countR = 0,
countL = 0;
for(int i = 0; i < arr.length; i++)
if(arr[i])
countR++;
else
countL++;
return countR == countL;
}
public static void printArr(boolean[] arr) {
for(int i = 0; i < arr.length; i++)
System.out.print(arr[i] ? "right " : "down ");
System.out.println();
}
}
It somehow doesn't change anything anywhere.
right right down down
right right down down
right right down down
right right down down ...
and so on is all it's outputting. It seems that the code simply doesn't permutate my path, but also doesn't get stuck in any of the for loops. My best guess would be that my function criteria are placed in the wrong sequence
I also thought of a solution with backtracking like we did for a labyrinth two years ago in school, but I want to see if this approach is anywhere viable or not before redoing everything.
EDIT:
I'll try to implement the images of the 2 x 2 grid example asap, but the ProjectEuler website is under maintainance at the moment.
The solution is given by the number of combinations of "down" and "right" movements we can have. Since there is no backtracking, there are N downwards and N rightwards movements in total (in any route, for an NxN grid). There are 2N movements in total.
We can obtain this using the binomial coefficient, nCr (pronounced "n choose r"), which is the number of ways of choosing r objects from n objects (each of which can be two things). In our case an "object" is either a downward or rightward movement. This is given by
Thus the number we want is:
For N = 2 this gives 6. For N = 20 this gives 137846528820.
Let a step in right be termed as R and a step down is termed as D.
In order to reach from top-left to bottom-right on a n rows and m column grid, you will have to go right m times and go down n times.
Essentially, you will have to get all the possible arrangements of m R's and n D's.
Example: For a 2 by 2 grid, the number of unique permutations of the word RRDD will be the number of ways in which you can go, viz.
RRDD
RDRD
DRDR
DDRR
Google the formula to calculate the permutations of letters with repetition, which is given by:
n! / ( r1! * r2! ... ), where sum of all r's is n.
This question on Math SE pops up first when looking for repetitive letter permutation count, and the second answer explains better in my opinion.
So, to return the count AND even to return the paths, you don't need to traverse the maze at all. Just do the formula calculation for first one and print the permutations for second problem.
Giving the paths when certain steps are off grid will be the only case that requires you to actually traverse the maze.
UPDATE:
It helps to visualize the formula for permutation of repeated letters.
Here is a slide that demonstrates that case. See how the 2 E's end up duplicating the arrangements when generating the permutations. In general, any letter that's repeated r times will cause r! duplication because wherever in the arrangement that letter is put, it can be replaced with another same letter without giving a new permutation.
That way, if we divide the total n! permutations with r!, we get the actual unique permutations.
Image Source
So I've been trying to implement this algorithm but I'm not so sure on where to start. Basically from what I understood you can implement it in two ways, by sorting it that the top level is the minimum (minHeap) or that the top level is the max of everything (maxHeap). I googled a lot about any of the two ways and I could not get a grip on how to actually implement it. I do not get the idea in general I would say, can anyone please explain how this works? Like how the minHeap one should work, or the maxHeap one.
Thank you in advance!
I'm assuming that you have a basic understanding of binary heap implementation in an array.
Let's say you have an array of integers that you want to sort into ascending order. One way is to rearrange items in the array so that they form a max-heap.
Then, you swap the top item (the largest item in the array) with the last item in the heap, decrease the heap count by 1, and sift the item from the top down into its new place in the heap. At the end, the first item in the array will be the next largest item. You repeat that for every item and your array is sorted.
Let's take a small example. Given the array [4,7,6,1,3,5,2], you rearrange them into a heap using Floyd's algorithm.
for (int i = array.length/2; i >= 0; i--)
{
siftDown(i);
}
This is an O(n) operation.
When you're done, the array is arranged in a binary heap. In this case, the heap would be [7,4,6,1,3,5,2], or:
7
4 6
1 3 5 2
So, we swap the root item with the last item, giving us: [2,4,6,1,3,5,7]. We decrease the count and sift 2 down to its proper place, giving: [6,4,5,1,3,2,7], or the heap representation:
6
4 5
1 3 2
(I omitted the 7 because we decreased the count. But it's still at the end of the array.)
Again, swap the top item with the last item in the heap: [2,4,5,1,3,6,7], decrease the count, and sift down: [5,4,2,1,3,6,7]:
5
4 2
1 3
If you continue that for the remaining five items in the heap, you'll end up with a sorted array.
The code for this is pretty simple:
int count = array.length-1;
while (count > 0)
{
swap(array[0], array[count]);
--count;
siftDown(0);
}
If you want to do a descending sort, you can either do the above with a max-heap and then reverse the array (an O(1) operation), or you can build a min-heap to start.
The siftDown method just moves the item down to its proper place, following the rules for binary heap construction:
void siftDown(int index)
{
// Left child is at index*2+1. Right child is at index*2+2;
while (true)
{
// first find the largest child
int largestChild = index*2+1;
// if left child is larger than count, then done
if (largestChild >= count)
{
break;
}
// compare with right child
if (largestChild+1 < count && array[largestChild] < array[largestChild+1])
{
++largestChild;
}
// If item is smaller than the largest child, then swap and continue.
if (array[index] < array[largestChild])
{
swap(array[index], array[largestChild]);
index = largestChild;
}
else
{
break;
}
}
I was confronted not so long ago to an algorithmic problem.
I needed to find if a value stored in an array was at it "place".
An example will be easier to understand.
Let's take an Array A = {-10, -3, 3, 5, 7}. The algorithm would return 3, because the number 3 is at A[2] (3rd place).
On the contrary, if we take an Array B = {5, 7, 9, 10}, the algorithm will return 0 or false or whatever.
The array is always sorted !
I wasn't able to find a solution with a good complexity. (Looking at each value individualy is not good !) Maybe it is possible to resolve that problem by using an approach similar to merge sorting, by cuting in half and verifying on those halves ?
Can somebody help me on this one ?
Java algorithm would be the best, but pseudocode would also help me a lot !
Here is an algorithm (based on binary search) to find all matching indices that has a best-case complexity of O(log(n)) and a worst case complexity of O(n):
1- Check the element at position m = array.length / 2
2- if the value array[m] is strictly smaller than m, you can forget about the left half of the array (from index 0 to index m-1), and apply recursively to the right half.
3- if array[m]==m, add one to the counter and apply recursively to both halves
4- if array[m]>m, forget about the right half of the array and apply recursively to the left half.
Using threads can accelerate things here. I suppose that there is no repetitions in the array.
Since there can be no duplicates, you can use the fact that the function f(x): A[x] - x is monotonous and apply binary search to solve the problem in O(log n) worst-case complexity.
You want to find a point where that function A[x] - x takes value zero. This code should work:
boolean binarySearch(int[] data, int size)
{
int low = 0;
int high = size - 1;
while(high >= low) {
int middle = (low + high) / 2;
if(data[middle] - 1 == middle) {
return true;
}
if(data[middle] - 1 < middle) {
low = middle + 1;
}
if(data[middle] - 1 > middle) {
high = middle - 1;
}
}
return false;
}
Watch out for the fact that arrays in Java are 0-indexed - that is the reason why I subtract -1 from the array.
If you want the find the first number in the array that is at its own place, you just have to iterate the array:
static int find_in_place(int[] a) {
for (int i=0; i<a.length; i++) {
if (a[i] == i+1) {
return a[i];
}
}
return 0;
}
It has a complexity of O(n), and an average cost of n/2
You can skip iterating if there is no such element by adding a special condition
if(a[0]>1 && a[a.length-1]>a.length){
//then don't iterate through the array and return false
return false;
} else {
//make a loop here
}
Using binary search (or a similar algorithm) you could get better than O(n). Since the array is sorted, we can make the following assumptions:
if the value at index x is smaller than x-1 (a[x] <= x), you know that all previous values also must be smaller than their index (because no duplicates are allowed)
if a[x] > x + 1 all following values must be greater than their index (again no duplicates allowed).
Using that you can use a binary approach and pick the center value, check for its index and discard the left/right part if it matches one of the conditions above. Of course you stop when a[x] = x + 1.
simply use a binary search for the 0 and use for compare the value in the array minus index of the array. O(log n)
If i have 1 core integers elements in arrays which having only 0,1 in random manner. & i want to sort this array without using existing algorithm. or sorting method and using minimal iteration.
How i can do that..
please help me out.
Maybe you can count the number of 0 and 1 and create a new array with the same amount of 0 and 1 but choosing the order you add them.
method 1:count all 0's and then set it from the front and then set 1's size - count(0) times.
method 2: Start from both ends of the array and swap 1s from left to 0s in right until reach the middle of the array.
while (begin < end) {
// If find 0 at left, keep moving
if (0 == toSort[begin]) {
begin++;
}
// if a 1 occurs at left, move from right until find a zero
else if (1 == toSort[end]) {
end--;
}
// Here we found a 1 at left and 0 at right, so swap
else {
toSort[begin] = 0;
toSort[end] = 1;
}
}
time complexity: O(n).