2-d Binary Search with Time Complexity - time-complexity

I don't understand how the following program that finds all negative numbers in a 2-d array is using binary search?
I thought binary search worked by taking a sorted list/array, going to middle, and checking if middle value was >, <, or == to the searched for value, and repeating that in the half containing the searched for value. This program checks iteratively for each row in the program (starting at top right of array) if that value is less than 0, and moves down next row if it is.
Also, why does this program what complexity O(row+col)? I thought binary search algorithms have complexity O(log(n)).
#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
class Solution {
public:
int countNegatives(vector<vector<int>>& grid) {
int row = grid.size()-1;
int col = grid[0].size()-1;
int i = 0; int j = col; int count = 0;
while ((i <= row) && (j>=0)){
if (grid[i][j] < 0){
count++;
j--;
if (j < 0){
i++;
j = col;
}
}
else{
i++;
j = col;
}
}
return count;
}
};

Related

Binary search to solve 'Kth Smallest Element in a Sorted Matrix'. How can one ensure the correctness of the algorithm,

I'm referring to the leetcode question: Kth Smallest Element in a Sorted Matrix
There are two well-known solutions to the problem. One using Heap/PriorityQueue and other is using Binary Search. The Binary Search solution goes like this (top post):
public class Solution {
public int kthSmallest(int[][] matrix, int k) {
int lo = matrix[0][0], hi = matrix[matrix.length - 1][matrix[0].length - 1] + 1;//[lo, hi)
while(lo < hi) {
int mid = lo + (hi - lo) / 2;
int count = 0, j = matrix[0].length - 1;
for(int i = 0; i < matrix.length; i++) {
while(j >= 0 && matrix[i][j] > mid) j--;
count += (j + 1);
}
if(count < k) lo = mid + 1;
else hi = mid;
}
return lo;
}
}
While I understand how this works, I have trouble figuring out one issue.
How can we be sure that the returned lo is always in the matrix?
Since the search space is min and max value of the array, the mid need NOT be a value that is in the array. However, the returned lo always is.
Why is this happening?
For the sake of argument, we can move the calculation of count to a separate function like the following:
bool valid(int mid, int[][] matrix, int k) {
int count = 0, m = matrix.length;
for (int i = 0; i < m; i++) {
int j = 0;
while (j < m && matrix[i][j] <= mid) j++;
count += j;
}
return (count < k);
}
This predicate will do exactly same as your specified operation. Here, the loop invariant is that, the range [lo, hi] always contains the kth smallest number of the 2D array.
In other words, lo <= solution <= hi
Now, when the loop terminates, it is evident that lo >= hi
Merging those two properties, we get, lo = solution = hi, since solution is a member of array, it can be said that, lo is always in the array after loop termination and will rightly point to the kth smallest element.
Because We are finding the lower_bound using binary search and there cannot be any number smaller than the number(lo) in the array which could be the kth smallest element.

Selection sort implementation, I am stuck at calculating time complexity for number of swaps

static int count = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
swap(arr, i, j);
count++;
}
}
}
Is this the correct implementation for selection sort? I am not getting O(n-1) complexity for swaps with this implementation.
Is this the correct implementation for selection sort?
It depends, logically what you are doing is correct. It sort using "find the max/min value in the array". But, in Selection Sort, usually you didn't need more than one swap in one iteration. You just save the max/min value in the array, then at the end you swap it with the i-th element
I am not getting O(n-1) complexity for swaps
did you mean n-1 times of swap? yes, it happen because you swap every times find a larger value not only on the largest value. You can try to rewrite your code like this:
static int count=0;
static int maximum=0;
for(int i=0;i<arr.length-1;i++){
maximum = i;
for(int j=i+1;j<arr.length;j++){
if(arr[j] > arr[maximum]){
maximum = j;
}
}
swap(arr[maximum],arr[i]);
count++;
}
Also, if you want to exact n-1 times swap, your iteration for i should changed too.

My quicksort crashes on already sorted data

I wanted to check the performance time for different data in array (random, already sorted, sorted in descending order).
void Quicksort(int *T, int Lo, int Hi)
{
if (Lo<Hi){
int x=T[Lo];
int i=Lo, j=Hi;
do
{
while (T[i] < x) ++i;
while (T[j] > x) --j;
if (i<=j)
{
int tmp = T[i];
T[i] = T[j];
T[j] = tmp;
++i; --j;
}
} while(i < j);
if (Lo < j) Quicksort(T, Lo, j);
if (Hi > i) Quicksort(T, i, Hi);
}
}
Here are the functions used to generate and fill the testing array:
int* createArr(int length){
int* Arr= new int[length];
return Arr;
}
void Random(int *A, int length){
for (int i=0;i<length;i++){
A[i]=rand();
}
}
void Order(int *A, int length){
for (int i=0;i<length;i++){
A[i]=i;
}
}
void Backwards(int *A, int length){
for (int i=0;i<length;i++){
A[i]=length-i;
}
}
It works fine for random numbers, but when I try to fill it in ascending order and sort, it crashes with stack overflow. Can anyone give me a hint of why is it happening?
When you choose the [Lo] item as a partioning value (a pivot), and the array is already sorted, then you get a partitioning 1 to (length–1). This causes the next (recursive) call on a longer part of the array to handle just one item less then the previous level. So, as #AlexanderM noted, you will get as deep into the recursion as the length of your array. If the array is big, it will almost certainly cause the stack overflow.
Try using a tail reursion: check which part is shorter and sort it with a resursive call, then continue on the current level with the longer part. To do that replace the very first if with while and replace
if (Lo < j) Quicksort(T, Lo, j);
if (Hi > i) Quicksort(T, i, Hi);
with
if (j-Lo < Hi-i)
{
Quicksort(T, Lo, j);
Lo = i;
}
else
{
Quicksort(T, i, Hi);
Hi = j;
}
This won't make the program any faster – it will still need O(n^2) time on an already-sorted array, but will protect against linear stack memory usage, keeping it at worst O(log n).
For further directions concerning better performance see Wikipedia article Quicksort, part Choice of pivot.

Finding the number of factors using a while loop

so i have this method that finds the number of factors of a given number. It works fine and everything but i am using a for loop and my teacher is wanting me to change it into a while loop to make it more efficient, ive tried to change it but i keep getting endless loop here is the code i have using a for loop what might be a good to change it to a while loop without using a break and only having one return statement in the whole method
public static int numberOfFactors(int num){
int i;
int total=0;
for(i=1;i<=num;i++){
if(num%i==0)
total++;
}
return (total);}
I fail to see how:
i = 1;
while(i <= num) {
// do things
i++;
}
Is any more efficient than:
for( i=1; i<=num; i++) {
// do things
}
As far as I can tell? It's not! I'd love to know why your teacher thinks it is.
That said, here's what you can do to make it more efficient:
Calculate the square root of num and put it in sqrtnum as an integer, rounded down.
Change your loop to for(i=1; i<sqrtnum; i++) (note <, not <=)
If num%i==0, increment total by 2, instead of 1.
After the loop, check if sqrtnum*sqrtnum == num - if so, increment total by 1.
In this way, you only have to loop through a fraction of the numbers ;)
Not any more efficient but....
public static int numberOfFactors(int num) {
int total = 0;
int i = 1;
while(i <= num) {
if(num%i == 0)
total++;
i++;
}
return total;
}

Create a Fraction array

I have to Create a dynamic array capable of holding 2*n Fractions.
If the dynamic array cannot be allocated, prints a message and calls exit(1).
It next fills the array with reduced random Fractions whose numerator
is between 1 and 20, inclusive; and whose initial denominator
is between 2 and 20, inclusive.
I ready did the function that is going to create the fraction and reduced it. this is what I got. When I compiled and run this program it crashes I cant find out why. If I put 1 instead of 10 in the test.c It doesn't crash but it gives me a crazy fraction. If I put 7,8,or 11 in the test.c it will crash. I would appreciate if someone can help me.
FractionSumTester.c
Fraction randomFraction(int minNum, int minDenom, int max)
{
Fraction l;
Fraction m;
Fraction f;
l.numerator = randomInt(minNum, max);
l.denominator = randomInt(minDenom, max);
m = reduceFraction(l);
while (m.denominator <= 1)
{
l.numerator = randomInt(minNum, max);
l.denominator = randomInt(minDenom, max);
m = reduceFraction(l);
}
return m;
}
Fraction *createFractionArray(int n)
{
Fraction *p;
int i;
p = malloc(n * sizeof(Fraction));
if (p == NULL)
{
printf("error");
exit(1);
}
for(i=0; i < 2*n ; i++)
{
p[i] = randomFraction(1,2,20);
printf("%d/%d\n", p[i].numerator, p[i].denominator);
}
return p;
}
this is the what I am using to test this two functions.
test.c
#include "Fraction.h"
#include "FractionSumTester.h"
#include <stdio.h>
int main()
{
createFractionArray(10);
return 0;
}
In your createFractionArray() function, you malloc() space for n items. Then, in the for loop, you write 2*n items into that space... which overruns your buffer and causes the crash.