Space complexity of two recursive functions - algorithm

I've got an interesting case doing LeetCode - I'm not sure what is Space complexity of this function. On the one hand when it calls itself, there are not traverse functions in the stack, so I believe space complexity is O(n).
But but if the recursion stack is empty should I say that this is not O(n^2) but O(n)?
Any help much appreciated!
class Solution {
int count = 0;
long targetSum;
public int pathSum(TreeNode root, int targetSum) {
if (root == null) return 0;
this.targetSum = targetSum;
traverse(root, (long)0);
pathSum(root.left, targetSum);
pathSum(root.right, targetSum);
return count;
}
private void traverse(TreeNode root, long currSum) {
if (root == null) return;
if (currSum + root.val == this.targetSum) {
this.count++;
}
traverse(root.left, currSum + root.val);
traverse(root.right, currSum + root.val);
}
}

Related

What's the time complexity of this BFS alg that returns a 2D ArrayList?

I'm trying to figure out what time complexity this method would be to get better at computing time complexities. I was told by someone else that this would be a worst case O(n^2) (n being elements in the tree) but I'm confused since the outer while loop would only go the amount of levels, not total elements.
Any help would be great!
public List<List> returnLevelOrder(TreeNode root) {
<List<List> ret = new ArrayList<List> ();
Queue<Integer> queue = new List<Integer>();
if(root==null){
return ret;
}
queue.add(root);
while(!queue.empty()) {
ArrayList<Integer> level = new ArrayList<Integer>();
int levelSize = queue.size();
while(levelSize >0) {
TreeNode currNode = queue.poll();
level.add(currNode.val);
levelSize--;
if(currNode.left != null) {
queue.add(currNode.left.val);
}
if(currNode.right != null) {
queue.add(currNode.right.val);
}
}
ret.add(level);
}
return ret;
}
It is O(n) - you visit all the elements once - it is an iterative tree traversal.

time complexity, Java

Please see the code that I wrote based on a school example.
public class Test {
public static void main(String [] args)
{
int number = 0;
int [] array = new int[number+1];
array[number] = 0;
methodName(number, array);
}
public static void methodName(int n, int[] b )
{
if (n == 0)
{
System.out.println(" b is : " + b);
return;
}
else
{
b[n-1] = 0;
methodName(n-1, b);
b[n-1] = 1;
methodName(n-1, b);
}
}
}
I am trying to calculate the best and worst case time complexity of this code.
As far as I understand the best case would be O(1).
And I'm having a difficulty determining the worst case.
There are four basic operations in the else loop.
I know that this is a progressively growing function and I have a feeling it is close to being O(!n).
Thank you for your time.
IF methodName is not getting called from anywhere else than main,
then it would always be O(1)

SINGLE Recursive function for Print/Fetch kth smallest element in Binary search tree

I am trying to print the kth smallest element in an BST.
The first solution is using in-order traversal.
Next solution is finding the index of the current node by calculation the size of its left subtree.
Complete algo:
Find size of left subtree:
1.If size = k-1, return current node
2.If size>k return (size-k)th node in right subtree
3.If size<k return kth node in left subtree
This can be implemented using a separate count function which looks something like
public class Solution {
public int kthSmallest(TreeNode root, int k) {
//what happens if root == null
//what happens if k > total size of tree
return kthSmallestNode(root,k).val;
}
public static TreeNode kthSmallestNode(TreeNode root,int k){
if(root==null) return root;
int numberOfNodes = countNodes(root.left);
if(k == numberOfNodes ) return root;
if(k<numberOfNodes ) return kthSmallestNode(root.left,k);
else return kthSmallestNode(root.right,k-numberOfNodes );
}
private static int countNodes(TreeNode node){
if(node == null) return 0;
else return 1+countNodes(node.left)+countNodes(node.right);
}
}
But I see that we count the size for same trees multiple times, so one way is to maintain an array to store thes sizes like the DP way.
But I want to write a recursive solution for this.And here is the code I have written.
class Node {
int data;
Node left;
Node right;
public Node(int data, Node left, Node right) {
this.left = left;
this.data = data;
this.right = right;
}
}
public class KthInBST
{
public static Node createBST(int headData)
{
Node head = new Node(headData, null, null);
//System.out.println(head.data);
return head;
}
public static void insertIntoBst(Node head, int data)
{
Node newNode = new Node(data, null, null);
while(true) {
if (data > head.data) {
if (head.right == null) {
head.right = newNode;
break;
} else {
head = head.right;
}
} else {
if (head.left == null) {
head.left = newNode;
break;
} else {
head = head.left;
}
}
}
}
public static void main(String[] args)
{
Node head = createBST(5);
insertIntoBst(head, 7);
insertIntoBst(head, 6);
insertIntoBst(head, 2);
insertIntoBst(head, 1);
insertIntoBst(head, 21);
insertIntoBst(head, 11);
insertIntoBst(head, 14);
insertIntoBst(head, 3);
printKthElement(head, 3);
}
public static int printKthElement(Node head, int k)
{
if (head == null) {
return 0;
}
int leftIndex = printKthElement(head.left, k);
int index = leftIndex + 1;
if (index == k) {
System.out.println(head.data);
} else if (k > index) {
k = k - index;
printKthElement(head.right, k);
} else {
printKthElement(head.left, k);
}
return index;
}
}
This is printing the right answer but multiple times, I figured out why it is printing multiple times but not understanding how to avoid it.
And also If I want to return the node instead of just printing How do I do it?
Can anyone please help me with this?
Objective:
Recursively finding the kth smallest element in a binary search tree and returning the node corresponding to that element.
Observation:
The number of elements smaller than the current element is the size of the left subtree so instead of recursively calculating its size, we introduce a new member in class Node, that is, lsize which represents the size of the left subtree of current node.
Solution:
At each node we compare the size of left subtree with the current value of k:
if head.lsize + 1 == k: current node in our answer.
if head.lsize + 1 > k: elements in left subtree are more than k, that is, the k the smallest element lies in the left subtree. So, we go left.
if head.lsize + 1 < k: the current element alongwith all the elements in the left subtree are less than the kth element we need to find. So, we go to the right subtree but also reduce k by the amount of elements in left subtree + 1(current element). By subtracting this from k we make sure that we have already taken into account the number of elements which are smaller than k and are rooted as the left subtree of current node (including the current node itself).
Code:
class Node {
int data;
Node left;
Node right;
int lsize;
public Node(int data, Node left, Node right) {
this.left = left;
this.data = data;
this.right = right;
lsize = 0;
}
}
public static void insertIntoBst(Node head, int data) {
Node newNode = new Node(data, null, null);
while (true) {
if (data > head.data) {
if (head.right == null) {
head.right = newNode;
break;
} else {
head = head.right;
}
} else {
head.lsize++; //as we go left, size of left subtree rooted
//at current node will increase, hence the increment.
if (head.left == null) {
head.left = newNode;
break;
} else {
head = head.left;
}
}
}
}
public static Node printKthElement(Node head, int k) {
if (head == null) {
return null;
}
if (head.lsize + 1 == k) return head;
else if (head.lsize + 1 > k) return printKthElement(head.left, k);
return printKthElement(head.right, k - head.lsize - 1);
}
Changes:
A new member lsize has been introduced in class Node.
Slight modification in insertIntoBst.
Major changes in printKthElement.
Corner case:
Add a check to ensure that k is between 1 and the size of the tree otherwise a null node will be returned resulting in NullPointerException.
This is working on the test cases I have tried, so far. Any suggestions or corrections are most welcome.
:)

How do you find the nth node in a binary tree?

I want to find the nth node/element in a binary tree. Not the nth largest/smallest, just the nth in inorder order for example.
How would this be done? Is it possible to keep it to one function? Many functions employ an external variable to keep track of the iterations outside of the recursion, but that seems... lazy, for lack of a better term.
You can augment the binary search tree into an order statistic tree, which supports a "return the nth element" operation
Edit: If you just want the ith element of an inorder traversal (instead of the ith smallest element) and don't want to use external variables then you can do something like the following:
class Node {
Node left
Node right
int data
}
class IterationData {
int returnVal
int iterationCount
}
IterationData findNth(Node node, IterationData data, int n) {
if(node.left != null) {
data = findNth(node.left, data, n)
}
if(data.iterationCount < n) {
data.iterationCount++
if(data.iterationCount == n) {
data.returnVal = node.data
return data
} else if(node.right != null) {
return findNth(node.right, data, n)
} else {
return data
}
}
}
You'll need some way to return two values, one for the iteration count and one for the return value once the nth node is found; I've used a class, but if your tree contains integers then you could use an integer array with two elements instead.
In order iterative traversal, keep track of nodes passed in external variable.
public static Node inOrderInterativeGet(Node root, int which){
Stack<Node> stack = new Stack<Node>();
Node current = root;
boolean done = false;
int i = 1;
if(which <= 0){
return null;
}
while(!done){
if(current != null){
stack.push(current);
current = current.getLeft();
}
else{
if(stack.empty()){
done = true;
}
else{
current = stack.pop();
if(i == which){
return current;
}
i++;
current = current.getRight();
}
}
}
return null;
}
One way to do it is to have a size property which is left_subtree + right_subtree + 1:
class Node:
def __init__(self, data=None, left=None, right=None,
size=None):
self.data = data
self.left = left
self.right = right
self.size = size
def select(node, k):
"""Returns node with k-th position in-order traversal."""
if not node:
return None
t = node.left.size if node.left else 0
if t > k:
return select(node.left, k)
elif t < k:
return select(node.right, k - t - 1)
else:
return node
If you don't like global variable, pass to recursive function additional parameter - some int variable, let's call it auto_increment or just ai. ai stores order of current node. Also, recursive function should return maximal value of ai of current vertex subtree,because after visiting whole subtree next 'free' value will be max_ai_in_subreee+1 Something like that
int rec(int vertex,int ai){
traverseOrder[vertex] = ai
if(getChildren(vertex)!=null) return ai;
else{
for(childrens){
ai = rec(child,ai+1);
}
return ai;// subtree visited, return maximal free value upstairs.
}
}
If your function already returns some useful data, it may return some complex object which contains {useful data+ai}
Start from some vertex looks like rec(start_vertex,1);
Below is full code that you can use to find the nth element using inorder in a Binary Tree.
public class NthNodeInInoeder {
static public class Tree {
public int data;
public Tree left,right;
public Tree(int data) {
this.data = data;
}
}
static Tree root;
static int count = 0;
private static void inorder(Tree root2, int num) {
if (root2 == null)
return;
Tree node = root2;
Stack<Tree> stack = new Stack<>();
while (node != null || stack.size() > 0) {
while (node != null) {
stack.push(node);
node = node.left;
}
node = stack.pop();
count++;
if (count == num) {
System.out.println(node.data);
break;
}
node = node.right;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
root = new Tree(10);
root.left = new Tree(20);
root.right = new Tree(30);
root.left.left = new Tree(40);
root.left.right = new Tree(50);
int num = sc.nextInt();
inorder(root, num);
sc.close();
}
}

O(1) lookup in non-contiguous memory?

Is there any known data structure that provides O(1) random access, without using a contiguous block of memory of size O(N) or greater? This was inspired by this answer and is being asked for curiosity's sake rather than for any specific practical use case, though it might hypothetically be useful in cases of a severely fragmented heap.
Yes, here's an example in C++:
template<class T>
struct Deque {
struct Block {
enum {
B = 4*1024 / sizeof(T), // use any strategy you want
// this gives you ~4KiB blocks
length = B
};
T data[length];
};
std::vector<Block*> blocks;
T& operator[](int n) {
return blocks[n / Block::length]->data[n % Block::length]; // O(1)
}
// many things left out for clarity and brevity
};
The main difference from std::deque is this has O(n) push_front instead of O(1), and in fact there's a bit of a problem implementing std::deque to have all of:
O(1) push_front
O(1) push_back
O(1) op[]
Perhaps I misinterpreted "without using a contiguous block of memory of size O(N) or greater", which seems awkward. Could you clarify what you want? I've interpreted as "no single allocation that contains one item for every item in the represented sequence", such as would be helpful to avoid large allocations. (Even though I do have a single allocation of size N/B for the vector.)
If my answer doesn't fit your definition, then nothing will, unless you artificially limit the container's max size. (I can limit you to LONG_MAX items, store the above blocks in a tree instead, and call that O(1) lookup, for example.)
You can use a trie where the length of the key is bounded. As lookup in a trie with a key of length m is O(m), if we bound the length of the keys then we bound m and now lookup is O(1).
So think of the a trie where the keys are strings on the alphabet { 0, 1 } (i.e., we are thinking of keys as being the binary representation of integers). If we bound the length of the keys to say 32 letters, we have a structure that we can think of as being indexed by 32-bit integers and is randomly-accessible in O(1) time.
Here is an implementation in C#:
class TrieArray<T> {
TrieArrayNode<T> _root;
public TrieArray(int length) {
this.Length = length;
_root = new TrieArrayNode<T>();
for (int i = 0; i < length; i++) {
Insert(i);
}
}
TrieArrayNode<T> Insert(int n) {
return Insert(IntToBinaryString(n));
}
TrieArrayNode<T> Insert(string s) {
TrieArrayNode<T> node = _root;
foreach (char c in s.ToCharArray()) {
node = Insert(c, node);
}
return _root;
}
TrieArrayNode<T> Insert(char c, TrieArrayNode<T> node) {
if (node.Contains(c)) {
return node.GetChild(c);
}
else {
TrieArrayNode<T> child = new TrieArray<T>.TrieArrayNode<T>();
node.Nodes[GetIndex(c)] = child;
return child;
}
}
internal static int GetIndex(char c) {
return (int)(c - '0');
}
static string IntToBinaryString(int n) {
return Convert.ToString(n, 2);
}
public int Length { get; set; }
TrieArrayNode<T> Find(int n) {
return Find(IntToBinaryString(n));
}
TrieArrayNode<T> Find(string s) {
TrieArrayNode<T> node = _root;
foreach (char c in s.ToCharArray()) {
node = Find(c, node);
}
return node;
}
TrieArrayNode<T> Find(char c, TrieArrayNode<T> node) {
if (node.Contains(c)) {
return node.GetChild(c);
}
else {
throw new InvalidOperationException();
}
}
public T this[int index] {
get {
CheckIndex(index);
return Find(index).Value;
}
set {
CheckIndex(index);
Find(index).Value = value;
}
}
void CheckIndex(int index) {
if (index < 0 || index >= this.Length) {
throw new ArgumentOutOfRangeException("index");
}
}
class TrieArrayNode<TNested> {
public TrieArrayNode<TNested>[] Nodes { get; set; }
public T Value { get; set; }
public TrieArrayNode() {
Nodes = new TrieArrayNode<TNested>[2];
}
public bool Contains(char c) {
return Nodes[TrieArray<TNested>.GetIndex(c)] != null;
}
public TrieArrayNode<TNested> GetChild(char c) {
return Nodes[TrieArray<TNested>.GetIndex(c)];
}
}
}
Here is sample usage:
class Program {
static void Main(string[] args) {
int length = 10;
TrieArray<int> array = new TrieArray<int>(length);
for (int i = 0; i < length; i++) {
array[i] = i * i;
}
for (int i = 0; i < length; i++) {
Console.WriteLine(array[i]);
}
}
}
Well, since I've spent time thinking about it, and it could be argued that all hashtables are either a contiguous block of size >N or have a bucket list proportional to N, and Roger's top-level array of Blocks is O(N) with a coefficient less than 1, and I proposed a fix to that in the comments to his question, here goes:
int magnitude( size_t x ) { // many platforms have an insn for this
for ( int m = 0; x >>= 1; ++ m ) ; // return 0 for input 0 or 1
return m;
}
template< class T >
struct half_power_deque {
vector< vector< T > > blocks; // max log(N) blocks of increasing size
int half_first_block_mag; // blocks one, two have same size >= 2
T &operator[]( size_t index ) {
int index_magnitude = magnitude( index );
size_t block_index = max( 0, index_magnitude - half_first_block_mag );
vector< T > &block = blocks[ block_index ];
size_t elem_index = index;
if ( block_index != 0 ) elem_index &= ( 1<< index_magnitude ) - 1;
return block[ elem_index ];
}
};
template< class T >
struct power_deque {
half_power_deque forward, backward;
ptrdiff_t begin_offset; // == - backward.size() or indexes into forward
T &operator[]( size_t index ) {
ptrdiff_t real_offset = index + begin_offset;
if ( real_offset < 0 ) return backward[ - real_offset - 1 ];
return forward[ real_offset ];
}
};
half_power_deque implements erasing all but the last block, altering half_first_block_mag appropriately. This allows O(max over time N) memory use, amortized O(1) insertions on both ends, never invalidating references, and O(1) lookup.
How about a map/dictionary? Last I checked, that's O(1) performance.

Resources