hi i need to find the time and space complexity of the program, pls help, if possible please suggest the optimization that can be performed,
.........................................................................................................................................................................................
public class Sol {
public int findMaxRectangleArea(int [][] as) {
if(as.length == 0)
return 0;
int[][] auxillary = new int[as.length][as[0].length];
for(int i = 0; i < as.length; ++i) {
for(int j = 0; j < as[i].length; ++j) {
auxillary[i][j] = Character.getNumericValue(as[i][j]);
}
}
for(int i = 1; i < auxillary.length; ++i) {
for(int j = 0; j < auxillary[i].length; ++j) {
if(auxillary[i][j] == 1)
auxillary[i][j] = auxillary[i-1][j] + 1;
}
}
int max = 0;
for(int i = 0; i < auxillary.length; ++i) {
max = Math.max(max, largestRectangleArea(auxillary[i]));
}
return max;
}
private int largestRectangleArea(int[] height) {
Stack<Integer> stack =
new Stack<Integer>();
int max = 0;
int i = 0;
while(i < height.length) {
if(stack.isEmpty() ||
height[i] >= stack.peek()) {
stack.push(height[i]);
i++;
}
else {
int count = 0;
while(!stack.isEmpty() &&
stack.peek() > height[i]) {
count++;
int top = stack.pop();
max = Math.max(max, top * count);
}
for(int j = 0; j < count + 1; ++j) {
stack.push(height[i]);
}
i++;
}
}
int count = 0;
while(!stack.isEmpty()) {
count++;
max = Math.max(max, stack.pop() * count);
}
return max;
}
thank you in advance
To find the space complexity take a look at the variables you declare and are larger than a single primitive variable. In fact I believe your space complexity will be determined my the array auxilary and the Stack stack. The size of the first one is pretty clear and I don't completely understand the second one but I see it's size will never be greater than the one of the array. So I would say the space complexity is O(size of(auxilary)) or O(N * M) where N=as.length() and M = as[0].length.
Now the time complexity is a bit trickier. You have two cycles over the whole auxilary array so for sure time complexity is at least O( N * M). You also have another cycle that invokes largestRectangleArea for each row of auxilary. If I get the code in this function correctly it seems this function is again linear, but I am not sure here. Since you know the logic better probably you will be able to compute its complexity better.
Hope this helps.
Related
This code is radix sort in Java.
Now I can sort. But I want to reduce its functionality if there is no change in the
array, let it stop the loop and show the value.
Where do I have to fix it? Please guide me, thanks in advance.
public class RadixSort {
void countingSort(int inputArray[], int size, int place) {
//find largest element in input array at 'place'(unit,ten's etc)
int k = ((inputArray[0] / place) % 10);
for (int i = 1; i < size; i++) {
if (k < ((inputArray[i] / place) % 10)) {
k = ((inputArray[i] / place) % 10);
}
}
//initialize the count array of size (k+1) with all elements as 0.
int count[] = new int[k + 1];
for (int i = 0; i <= k; i++) {
count[i] = 0;
}
//Count the occurrence of each element of input array based on place value
//store the count at place value in count array.
for (int i = 0; i < size; i++) {
count[((inputArray[i] / place) % 10)]++;
}
//find cumulative(increased) sum in count array
for (int i = 1; i < (k + 1); i++) {
count[i] += count[i - 1];
}
//Store the elements from input array to output array using count array.
int outputArray[] = new int[size];
for (int j = (size - 1); j >= 0; j--) {
outputArray[count[((inputArray[j] / place) % 10)] - 1] = inputArray[j];
count[(inputArray[j] / place) % 10]--;//decrease count by one.
}
for (int i = 0; i < size; i++) {
inputArray[i] = outputArray[i];//copying output array to input array.
}
System.out.println(Arrays.toString(inputArray));
}
void radixSort(int inputArray[], int size) {
//find max element of inputArray
int max = inputArray[0];
for (int i = 1; i < size; i++) {
if (max < inputArray[i]) {
max = inputArray[i];
}
}
//find number of digits in max element
int d = 0;
while (max > 0) {
d++;
max /= 10;
}
//Use counting cort d no of times
int place = 1;//unit place
for (int i = 0; i < d; i++) {
System.out.print("iteration no = "+(i+1)+" ");
countingSort(inputArray, size, place);
place *= 10;//ten's , hundred's place etc
}
}
1
I'm going to resist typing out some code for you and instead go over the concepts since this looks like homework.
If I'm understanding you correctly, your problem boils down to: "I want to check if two arrays are equivalent and if they are, break out of a loop". Lets tackle the latter part first.
In Java, you can use the keyword"
break;
to break out of a loop.
A guide for checking if two arrays are equivalent in java can be found here:
https://www.geeksforgeeks.org/compare-two-arrays-java/
Sorry if this doesnt answer your question. Im just gonna suggest a faster way to find the digits of each element. Take the log base 10 of the element and add 1.
Like this : int digits = (int) Math.log10(i)+1;
I'm currently working my way up in the algorithmical problems. But I guess I still don't fully understand how to count algorithm complexity. I would say that my code have complexity O(n^3) because of three main loops inside them working on the data set, could someone confirm this or if I'm wrong show me on this bit of code how it should be counted?
public class BigOhN3 {
private Integer[] result;
private long time;
BigOhN3(Integer[] list) {
long start = System.currentTimeMillis();
int coefficientSum = calculateCoefficient(list);
result = new Integer[list.length];
//Main loop
for(int i = 0; i < list.length; i++) {
int coefficientSumIndexI = coefficientSum;
for(int j = 0; j < list.length; j++) {
Integer[] listIndexJ = list.clone();
if(j == i && j < list.length - 1) {
j++;
}
int a = listIndexJ[i];
int b = listIndexJ[j];
listIndexJ[i] = b;
listIndexJ[j] = a;
int coefficientSumIndexJ = calculateCoefficient(listIndexJ);
if(coefficientSumIndexJ < coefficientSumIndexI) {
coefficientSumIndexI = coefficientSumIndexJ;
result[i] = coefficientSumIndexJ;
}
}
if(result[i] == null) {
result[i] = coefficientSum;
}
}
time = System.currentTimeMillis() - start;
}
public long getTime() {
return time;
}
private int calculateCoefficient(Integer[] list) {
int sum = 0;
for(int i = 0; i < list.length - 1; i++) {
int item = list[i] - list[i + 1];
if(item < 0) {
item = item * (-1);
}
sum = sum + item;
}
return sum;
}
Integer[] getResult() {
return result;
}
}
It's O(n^3) indeed. But even if there was no most inner loop, it would be O(n^3) due to cloning a list (an array actually) takes at least O(n) as you need at least to read all elements. This means, that the complexity of the algorithm is:
O(n)*O(n)*(O(n)+O(n)) = O(n^3)
n times execute a loop a.
for each execution of a, execute loop b n times.
for each execution of b copy an array which takes O(n) and run the third loop which executes n times.
I am trying to calculate how many times two people in a group have the same birthday when given a size of the group. I am also given how many times the simulation is ran. I am trying to return the correct percentage for how many times we have two people share the same birthday out of the given amount of simulations.
I created an array first and then called a method to put the elements in a hashMap which would then show when there are two of the same values in the hashMap. However, I am not getting the correct percentage when running on Android Studio. In fact I am getting a percentage way off. I also declared a global static match variable of type int above this block.
/**
* sameBday: Create a word count mapping from an array
*/
public void sameBday(int[] valueHolder) {
Map<Integer, Integer> myMap = new HashMap<Integer, Integer>();
for(int number: valueHolder){
if(!myMap.containsKey(number)){
myMap.put(number, 1);
}
else if(myMap.containsKey(number)){
myMap.put(number, myMap.get(number) + 1);
match++;
break;
}
}
}
public double calculate(int size, int count) {
double percentage = 0.0;
int[] myArray = new int[size];
for(int i = 1; i <= count; i++){
Random r = new Random(i);
for(int j = 0; j < size; j++){
myArray[j] = r.nextInt(365) + 1;
}
sameBday(myArray);
if(i == count){
percentage = (match * (100.0/i));
}
}
return percentage;
}
Well your code is full of weird things, but that's OK we all did that. The first thing is Map, you don't need it. You can create just good old for loop and by additional check you will not compare the same person (it is i != j condition), but if you really want to do this by map you need to at the end of adding number (as key) to map check if some value of key is higher than 1, if true it's a match.
How to do something at the end of loop?
if(i == count){
percentage = (match * (100.0/i));
}
No, just do this after loop :)
//At the beginning there is int match = 0;
public void sameDayBirthday(int[] birthdays) {
for(int i = 0; i < birthdays.length; i++) {
for(int j = 0; j < birthdays.length; j++) {
if(birthdays[i] == birthdays[j] && i != j) {
match++;
return;
}
}
}
}
public double calculate(int size, int count) {
int[] birthdays = new int[size];
Random r = new Random();
for(int i = 1; i <= count; i++){ //looping through i counts (or 20 counts in this case
for(int j = 0; j < size; j++){ //looping through j times every i iteration
birthdays[j] = r.nextInt(365) + 1;
}
sameDayBirthday(birthdays);
}
return (match * (100.0/(double) count));
}
This code by calling calculate(23, 1000000) got me 50.7685% chance, for 22 persons 47.48690%
I am sorry if I offend you I didn't mean it. Leave a comment if you have questions.
I would use a HashSet and skip the sameBday function:
public double calculate(int size, int count) {
int match = 0;
Random r = new Random();
for(int i = 1; i <= count; i++){ //looping through i counts (or 20 counts in this case
Set<Integer> birthdays = new HashSet<Integer>(size);
for(int j = 0; j < size; j++){ //looping through j times every i iteration
Integer birthday = r.nextInt(365) + 1;
if (birthdays.contains(birthday)) {
match++;
break;
} else {
birthdays.add(birthday);
}
}
}
return (match * (100.0/count));
}
This is a easy question. a link
I just tried the simple insertionSorting-like method to solve it, however it failed.
public class Solution {
public void moveZeroes(int[] nums) {
for(int i = 0; i < nums.length; i++)
if(nums[i] == 0){
for(int j = i; j<nums.length-1; j++)
nums[j] = nums[j+1];
nums[nums.length-1] = 0;
}
}
}
Could anyone help me to debug my method?
So i went through your code and re-wrote it to work. If you're moving zeroes to the end this should work perfectly fine for you. Cheers.
What this code does is iterates over your array until it hits a zero. Upon hitting a zero it loops, moving the 0 one place to the right over and over, switching spots with the value to the right of it, until the 0 is moved to the end of the array.
example: 5-loop cycle
[0,1,0,2,3] > [1,0,0,2,3] > [1,0,0,2,3] > [1,0,2,0,3] > [1,0,2,3,0]
int[] array = new int[] {0,1,0,12,3};
for (int x = 0; x < array.length; x++) {
if (array[x] == 0) {
for (int y = x; y < array.length; y++) {
if (y != array.length-1) {
// Store our replacement as temp
int temp = array[y+1];
// Move 0 to the right +1
array[y+1] = array[y];
// Set current position to what used to be right+1
array[y] = temp;
}
}
}
}
I'll share the javascript solution for the Move Zeroes problem from leetcode. It has O(n) time complexity.
Optimized for many zeroes
const snowball1 = nums => {
let i = 0;
let j = 0;
while (i<nums.length) {
if(nums[i] != 0) {
nums[j] = nums[i];
j++;
}
i++;
}
console.log(j);
nums.fill(0, j);
return nums;
}
Optimized for fewer zeroes
const snowball2 = nums => {
for(let i = nums.length; i--;){
if(nums[i]===0){
nums.splice(i,1)
nums.push(0);
}
}
return nums
}
Example
console.log(snowball1([0,0,1,0,0,3,0,12,0]));
console.log(snowball2([0,1,0,3,12]));
I'll try to write a very intuitive and easy approach to this problem. This problem can be solved using 2 indexes, one of which is the read pointer(rp) and the other is the write pointer(wp).
If rp reads a value of 0, it sets the wp to this index. The rp then keeps incrementing until it finds a non-zero value. If it does it overwrites the value at wp and this process fills the non-zero values in the beginning.
We then just need to fill the remaining spots with zeros till the end. Here's a short solution in python:
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
wp=rp=0
while(rp<len(nums)):
if(nums[rp]!=0):
nums[wp]=nums[rp]
wp+=1
rp+=1
for i in range(wp,len(nums)):
nums[i]=0
Please find the optimal solution wrt space O(N) and time O(1) below
public void moveZeroes(int[] nums) {
// [0,1,0,3,12]
int j = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
j++;
}
}
}
This question has been asked before. However I just want to know what is wrong with my code. It passes most of the test cases but not all of them on lintcode.
Given an array of integers, the majority number is the number that occurs more than half of the size of the array. Find it.
public class Solution {
/**
* #param nums: a list of integers
* #return: find a majority number
*/
public int majorityNumber(ArrayList<Integer> nums) {
// write your code
Collections.sort(nums);
int j = 0, count = 0, out = 0, size = nums.size();
for(int i = 0; i < size; i++) {
if(nums.get(j) == nums.get(i)) {
count++;
if(count > size/2){
out = nums.get(i);
}
} else {
count = 1;
j = i;
}
}
return out;
}
}
EDIT
I changed the code to j = i & count = 1 as suggested by an answer.
For example for the input [1,1,1,2,2,2,2] the output should be 2.
My code works in this case. It doesn't work in large input cases.
I don't want another solution, as I have already found many O(n) solutions on other sites. I just want to fix my own code and know what I am doing wrong.
There's a smart solution that runs in O(n) worst case time, and no additional space:
public static int majorityNumber(List<Integer> nums) {
int candidate = 0;
int count = 0;
for (int num : nums) {
if (count == 0)
candidate = num;
if (num == candidate)
count++;
else
count--;
}
return candidate;
}
Note that it assumes the existence of a majority value, otherwise it returns an arbitrary value.
In your else block do:
...
else {
count = 1;
j = i;
}
Debug your code and print the values of i and j. I'm sure that will not be what you wanted to do.
You wanted to read each element and count it's frequency. That would be a O(n*n)(because the array is sorted O(n log(n))) solution.
ArrayList<Integer> readNums = new ArrayList();
for(int i = 0; i < a.length; ++i)
{
int currentNum = a[i];
if(list.contains(currentNum)
continue;//to check if you already processed that num
else
list.add(currentNum);
int count = 0;
for(int j = i + 1; j < a.length; ++j)
{
if(currentNum == a[j])
count ++;
}
if(count > size / 2)
reqNum = currentNum;
}
This is what you wanted to do.
A better method would be to use a space of O(n) and track the frequencies and then process the array in O(n).
HashMap<Integer, Intege> map = new HashMap();
for(int i = 0; i < a.length; ++i)
{
int currentNum = a[i];
int count = 1;
if(map.containsKey(currentNum))
{
count = map.getValue(currentNum);
map.put(currentNum, count + 1);
count ++;
}
else
{
map.put(currentNum, count);
}
if(count > size / 2)
reqNum = currentNum;
}