Below program is to find all the subsets of an array. Is time complexity of the program is O(2^n)?
Is there any easy way to find the time complexity of recursive function?
Thanks in anticipation
public static void getAllSubSet(int[] arr,int[] subset,int index){
if(index == arr.length)
printarr(subset);
else{
subset[index] = -1;
getAllSubSet(arr, subset, index+1);
subset[index] = arr[index];
getAllSubSet(arr, subset, index+1);
}
}
public static void printarr(int[] set){
for(int i=0;i<set.length;i++){
if(set[i] != -1){
System.out.print(set[i] +" ");
}
}
System.out.println("");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = {1,2,3};
int[] subset = new int[arr.length];
getAllSubSet(arr, subset, 0);
}
Answer to your first question:
The complexity of your function is O(n* 2^n). However if n is very large, you can neglect n.
Answer to your second question:
One of the best ways I find for approximating the complexity of the recursive algorithm is drawing the recursion tree. Once you have the recursive tree, you can find the complexity.
Related
I was attempting to solve the coin change problem (https://leetcode.com/problems/coin-change) and have come up with the following recursive approach:
class Solution {
public int coinChange(int[] coins, int amount) {
int[] min = new int[1];
min[0] = Integer.MAX_VALUE;
recur(coins,amount,min,0);
min[0] = min[0]==Integer.MAX_VALUE?-1:min[0];
return min[0];
}
private void recur(int[] coins,int amount,int[] min,int coinsUsed){
if(amount==0){
min[0] = Math.min(min[0],coinsUsed);
return;
}
if(amount<0){
return;
}
for(int i=0;i<coins.length;++i){
recur(coins,amount-coins[i],min,coinsUsed+1);
}
}
}
Currently the time complexity would be O((coins.length)^n). How can I add memoization to improve this?
Usually top-down with memoization gets a bit complicated. A simple way is to use a 2-d array and solve the problem bottom up. Suppose you have n denominations (index from 1 to n) and the sum is S. Let T[n][S] be the minimal number of coins you need to add up to S and v[n] the value of coin n.
You have two choices either you use coin n or you don't. If you don't
then T[n][S]=T[n-1][S]. If you do then T[n][S]=1+T[n][S-v[n]] since you don't know which is
better then
T[n][S]=min (T[n-1][S],1+T[n][S-v[n]]).
This is true for all n therefore we get the recursive formula.
T[i][s]=min(T[i-1][s],1+T[i][s-v[i]])
Now for the boundary conditions
If i=1 then T[1][s]=s for all 0<= s <= S
T[i][0]=0 for 1<= i<= n
int x,y;
int T[n+1][S+1];
//initialization
for(y=0;y<=S;y++)
T[1][y]=y;
for(x=0;x<=n;x++)
T[x][0]=0;
//solution
for(x=2;x<=n;x++){
for(y=0;y<=S;y++){
if (v[x]>= y )
T[x][y]=min(T[x-1][y],1+T[x][y-v[x]];
else
T[x][y]=T[x-1][y];
}
}
I'm familiar with running time for both of the following methods which is O(N). However, I'm not familiar with space complexity. Since these methods consists simply of assignment statements, comparison statements, and loops, I assume that the space complexity is just O(1), but want to make sure. Thank you.
//first method
public static <E> Node<E> buildList(E[] items) {
Node<E> head = null;
if (items!=null && items.length>0) {
head = new Node<E> (items[0], null);
Node<E> tail = head;
for (int i=1; i<items.length; i++) {
tail.next = new Node<E>(items[i], null);
tail = tail.next;
}
}
return head;
}
//second method
public static <E> int getLength(Node<E> head) {
int length = 0;
Node<E> node = head;
while (node!=null) {
length++;
node = node.next;
}
return length;
}
As described in this post, space complexity is related to the amount of memory used by the algorithm, depending on the size of the input.
For instance an algorithm with O(1) space complexity uses a fixed amount of memory, independently of the input size. This is the case of your second algorithm that basically only uses a few extra variables.
An algorithm with O(n) space complexity uses an amount of memory proportional to its input size. This is the case of your first algorithm that performs one allocation (one new) for each element of the input.
This is question from homework:
Implement a FIFO queue using two stacks.
The total running time of Enqueue and Dequeue functions should be O(n) in the worst case scenario. Also, analyze the running time of the algorithm.
What I did:
void Enqueue(T *value)
{
s1.Push(value);
}
T *Dequeue()
{
if (s2.size > 0)
return s2.Pop();
else if (s1.size > 0)
{
for (int i = 0; i < s1.size; i++)
s2.Push(s1.Pop());
return s2.Pop();
}
else return NULL;
}
Analysis of the algorithm:
Running time of one Enqueue is Theta(1). Total running time of the all Enqueue functions is n * Theta(1) = Theta(n).
Running time of Dequeue in worst case scenario is Theta(n) (when you call it after the last Enqueue, i.e. when all the items inserted). In all other cases the running time is Theta(1).
So, the total running time is:
O(n) + O(n) + n * O(1) = 3 * O(n) = O(n)
Is this correct?
So, the total running time is: O(n) + O(n) + n * O(1) = 3 * O(n) =
O(n)
You're in the right direction, but you usually don't analyze "total running time", you split it to amortized average, worst case, and best case - and analyze it for each operation.
In your algorithm, it is easy to see that:
enqueue() runs in Theta(1) for all cases.
dequeue() runs in Theta(n) worst case and Theta(1) best case.
Noe, for the tricky part - we need to analyzed dequeue() amortised analysis.
First, note that before each Theta(n) (worst case), dequeue() you must have emptied the list, and inserted n elements.
This means, in order for the worst case to happen, you must have done at least n enqueue() operations, each Theta(1).
This gives us amortised time of:
T(n) = (n*CONST1 + CONST2*n) /(n+1)
^ ^ ^
n enqueues 1 "espansive" dequeue #operations
It is easy to see that T(n) is in Theta(1), giving you Theta(1) amortized time complexity.
tl;dr:
enqueue: Theta(1) all cases
dequeue: Theta(1) amortized, Theta(n) worst case
import java.util.Stack;
public class Q5_ImplementQueueUsingStack {
/**
* #param args
* Implement a MyQueue class which implements a queue using two stacks.
*/
public static Stack<Integer> s1 = new Stack<Integer>();
public static Stack<Integer> s2 = new Stack<Integer>();
public static void main(String[] args) {
int[] array = {2,5,10,3,11,7,13,8,9,4,1,6};
for(int i=0;i<5;i++){
enQueue(array[i]);
}
System.out.println(deQueue());
System.out.println(deQueue());
System.out.println(deQueue());
System.out.println(deQueue());
System.out.println(deQueue());
for(int i=0;i<4;i++){
enQueue(array[i+5]);
}
System.out.println(deQueue());
for(int i=0;i<3;i++){
enQueue(array[i+9]);
}
System.out.println(deQueue());
System.out.println(deQueue());
System.out.println(deQueue());
System.out.println(deQueue());
System.out.println(deQueue());
System.out.println(deQueue());
}
public static void enQueue(int data){
s1.push(data);
}
public static int deQueue(){
if(s2.isEmpty())
while(!s1.isEmpty())
s2.push(s1.pop());
return s2.pop();
}
}
Implement the following operations of a queue using stacks.
push(x) -- Push element x to the back of queue.
pop() -- Removes the element from in front of queue.
peek() -- Get the front element.
empty() -- Return whether the queue is empty.
class MyQueue {
Stack<Integer> input;
Stack<Integer> output;
/** Initialize your data structure here. */
public MyQueue() {
input = new Stack<Integer>();
output = new Stack<Integer>();
}
/** Push element x to the back of queue. */
public void push(int x) {
input.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
peek();
return output.pop();
}
/** Get the front element. */
public int peek() {
if(output.isEmpty()) {
while(!input.isEmpty()) {
output.push(input.pop());
}
}
return output.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
return input.isEmpty() && output.isEmpty();
}
}
I just had this as an interview question and was wondering if anyone knows the answer?
Write a method that validates whether a B-tree is correctly sorted. You do NOT need to validate whether
the tree is balanced. Use the following model for a node in the B-tree.
It was to be done in Java and use this model:
class Node {
List<Integer> keys;
List<Node> children;
}
One (space-inefficient but simple) way to do this is to do a generalized inorder traversal of the B-tree to get back the keys in what should be sorted order, then to check whether that sequence actually is in sorted order. Here's some quick code for this:
public static boolean isSorted(Node root) {
ArrayList<Integer> values = new ArrayList<Integer>();
performInorderTraversal(root, values);
return isArraySorted(values);
}
private static void performInorderTraversal(Node root, ArrayList<Integer> result) {
/* An empty tree has no values. */
if (result == null) return;
/* Process the first tree here, then loop, processing the interleaved
* keys and trees.
*/
performInorderTraversal(root.children.get(0), result);
for (int i = 1; i < root.children.size(); i++) {
result.add(root.children.get(i - 1));
performInorderTraversal(root.children.get(i), result);
}
}
private static boolean isArraySorted(ArrayList<Integer> array) {
for (int i = 0; i < array.size() - 1; i++) {
if (array.get(i) >= array.get(i + 1)) return false;
}
return true;
}
This takes time O(n) and uses space O(n), where n is the number of elements in the B-tree. You can cut the space usage down to O(h), where h is the height of the B-tree, by not storing all the elements in the traversal and instead just tracking the very last one, stopping the search early if the next-encountered value is not larger than the previous one. I didn't do that here because it takes more code, but conceptually it's not too hard.
Hope this helps!
Problem
Find a list of non repeating number in a array of repeating numbers.
My Solution
public static int[] FindNonRepeatedNumber(int[] input)
{
List<int> nonRepeated = new List<int>();
bool repeated = false;
for (int i = 0; i < input.Length; i++)
{
repeated = false;
for (int j = 0; j < input.Length; j++)
{
if ((input[i] == input[j]) && (i != j))
{
//this means the element is repeated.
repeated = true;
break;
}
}
if (!repeated)
{
nonRepeated.Add(input[i]);
}
}
return nonRepeated.ToArray();
}
Time and space complexity
Time complexity = O(n^2)
Space complexity = O(n)
I am not sure with the above calculated time complexity, also how can I make this program more efficient and fast.
The complexity of the Algorithm you provided is O(n^2).
Use Hashmaps to improve the algorithm. The Psuedo code is as follows:
public static int[] FindNonRepeatedNumbers(int[] A)
{
Hashtable<int, int> testMap= new Hashtable<int, int>();
for (Entry<Integer, String> entry : testMap.entrySet()) {
tmp=testMap.get(A[i]);
testMap.put(A[i],tmp+1);
}
/* Elements that are not repeated are:
Set set = teatMap.entrySet();
// Get an iterator
Iterator i = set.iterator();
// Display elements
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
if(me.getValue() >1)
{
System.out.println(me.getValue());
}
}
Operation:
What I did here is I used Hashmaps with keys to the hashmaps being the elements of the input array. The values for the hashmaps are like counters for each element. So if an element occurs once then the value for that key is 1 and the key value is subsequently incremented based on recurrence of element in input array.
So finally you just check your hashmap and then display elements with hashvalue 1 which are non-repated elements. The time complexity for this algorithm is O(k) for creating hashmap and O(k) for searching, if the input array length is k. This is much faster than O(n^2). The worst case is when there are no repeated elements at all. The psuedo code might be messy but this approach is the best way I could think of.
Time complexity O(n) means you can't have an inner loop. A full inner loop is O(n^2).
two pointers. begining and end. increment begining when same letters reached and store the start and end pos ,length for reference... increment end otherwise.. keep doing this til end of list..compare all the outputs and you should have the longest continuous list of unique numbers. I hope this is what the question required. Linear algo.
void longestcontinuousunique(int arr[])
{
int start=0;
int end =0;
while (end! =arr.length())
{
if(arr[start] == arr[end])
{
start++;
savetolist(start,end,end-start);
}
else
end++
}
return maxelementof(savedlist);
}