Big O complexities of my Huffman Algorithm - algorithm

Can someone please tell me the Space and time Complexities, in Bog O notation, of this Huffman code with a little explanation. Would be very much appreciated, thanks. And please do mention the Big O of each method separately, would be great. Thanks.
package HuffmanProject;
import java.util.*;
class MyHCode {
public static void main(String[] args) {
String test = "My name is Zaryab Ali";
int[] FreqArray = new int[256];
for (char c : test.toCharArray()) {
FreqArray[c]++;
}
MyHTree tree = ImplementTree(FreqArray);
System.out.println("CHARACTER\tFREQUENCY\tBINARY EQUIVALEENT CODE");
PrintMyHCode(tree, new StringBuffer());
}
public static MyHTree ImplementTree(int[] FreqArray) {
PriorityQueue<MyHTree> trees = new PriorityQueue<MyHTree>();
for (int i = 0; i < FreqArray.length; i++) {
if (FreqArray[i] > 0) {
trees.offer(new MyHLeaf(FreqArray[i], (char) i));
}
}
while (trees.size() > 1) {
MyHTree FChild = trees.poll();
MyHTree SChild = trees.poll();
trees.offer(new MyHNode(FChild, SChild));
}
return trees.poll();
}
public static void PrintMyHCode(MyHTree tree, StringBuffer prefix) {
if (tree instanceof MyHLeaf) {
MyHLeaf leaf = (MyHLeaf) tree;
System.out.println(leaf.CharValue + "\t\t" + leaf.frequency + "\t\t" + prefix);
}
else if (tree instanceof MyHNode) {
MyHNode node = (MyHNode) tree;
prefix.append('0');
PrintMyHCode(node.left, prefix);
prefix.deleteCharAt(prefix.length() - 1);
prefix.append('1');
PrintMyHCode(node.right, prefix);
prefix.deleteCharAt(prefix.length() - 1);
}
}
}
abstract class MyHTree implements Comparable<MyHTree> {
public int frequency;
public MyHTree(int f) {
frequency = f;
}
public int compareTo(MyHTree tree) {
return frequency - tree.frequency;
}
}
class MyHLeaf extends MyHTree {
public char CharValue;
public MyHLeaf(int f, char v) {
super(f);
CharValue = v;
}
}
class MyHNode extends MyHTree {
public MyHTree left, right;
public MyHNode(MyHTree l, MyHTree r) {
super(l.frequency + r.frequency);
left = l;
right = r;
}
}

The PrintMyHCode() method iterates through the left & right subtrees until the leaft node is found. If there are n elements in the tree then the complexity of this method would be O(n).
The ImplementTree() method adds values in array to the tree and then it polls on their childs.
If there are n elements in the array:
1. The complexity of the for loop in this method will be O(n) as each elements is added to the tree directly
2. The complexity of while loop in this method will be O(logn) assuming that every node has atleast two children for it.
Hence, the total time complexity for ImplementTree() method in Big O notation would be O(nlogn).
Hope, this answer works for you.

Related

Generating all the elements of a power set

Power set is just set of all subsets for given set.
It includes all subsets (with empty set).
It's well-known that there are 2^N elements in this set, where N is count of elements in original set.
To build power set, following thing can be used:
Create a loop, which iterates all integers from 0 till 2^N-1
Proceed to binary representation for each integer
Each binary representation is a set of N bits (for lesser numbers, add leading zeros).
Each bit corresponds, if the certain set member is included in current subset.
import java.util.NoSuchElementException;
import java.util.BitSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class PowerSet<E> implements Iterator<Set<E>>, Iterable<Set<E>> {
private final E[] ary;
private final int subsets;
private int i;
public PowerSet(Set<E> set) {
ary = (E[])set.toArray();
subsets = (int)Math.pow(2, ary.length) - 1;
}
public Iterator<Set<E>> iterator() {
return this;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Cannot remove()!");
}
#Override
public boolean hasNext() {
return i++ < subsets;
}
#Override
public Set<E> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Set<E> subset = new TreeSet<E>();
BitSet bitSet = BitSet.valueOf(new long[] { i });
if (bitSet.cardinality() == 0) {
return subset;
}
for (int e = bitSet.nextSetBit(0); e != -1; e = bitSet.nextSetBit(e + 1)) {
subset.add(ary[e]);
}
return subset;
}
// Unit Test
public static void main(String[] args) {
Set<Integer> numbers = new TreeSet<Integer>();
for (int i = 1; i < 4; i++) {
numbers.add(i);
}
PowerSet<Integer> pSet = new PowerSet<Integer>(numbers);
for (Set<Integer> subset : pSet) {
System.out.println(subset);
}
}
}
The output I am getting is:
[2]
[3]
[2, 3]
java.util.NoSuchElementException
at PowerSet.next(PowerSet.java:47)
at PowerSet.next(PowerSet.java:20)
at PowerSet.main(PowerSet.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)
So, the problems are:
I am got getting all the elements(debugging shows me next is called only for even i's).
The exception should not have been thrown.
The problem is in your hasNext. You have i++ < subsets there. What happens is that since hasNext is called once from next() and once more during the iteration for (Set<Integer> subset : pSet) you increment i by 2 each time. You can see this since
for (Set<Integer> subset : pSet) {
}
is actually equivalent to:
Iterator<PowerSet> it = pSet.iterator();
while (it.hasNext()) {
Set<Integer> subset = it.next();
}
Also note that
if (bitSet.cardinality() == 0) {
return subset;
}
is redundant. Try instead:
#Override
public boolean hasNext() {
return i <= subsets;
}
#Override
public Set<E> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Set<E> subset = new TreeSet<E>();
BitSet bitSet = BitSet.valueOf(new long[] { i });
for (int e = bitSet.nextSetBit(0); e != -1; e = bitSet.nextSetBit(e + 1)) {
subset.add(ary[e]);
}
i++;
return subset;
}

algorithms how to deal with multiple criteria

find 2 rectangles A[i] and A[j] in an array A[n] rectangles such that A[i].width > A[j].width and A[i].length - A[j].length is the longest.
Is there a way to reduce the complexity to O(nlogn)? I can't find a way to get an O(logn) search for the second rectangle. Sorting doesn't seem to help here due to the possibilities of 2 criteria being completely opposite of each other. Maybe I'm just going at it wrong? direct me to the right path please. Thank you.
Note: Homework assignment using different object and using 2 criteria instead of 3, but the context is the same.
Since this is homework, here is a high-level answer, with the implementation left as a problem for the OP:
Sort the elements of the array ascending by width. Then scan down the array subtracting the current length from the highest length encountered so far. keep track of the greatest difference encountered so far (and the corresponding i and j). When done you will have the greatest length difference A[i].length-A[j].length where A[i].width > A[j].width
Analysis: sorting the elements takes O(n*Log(n)), all other steps take O(n).
Here is some java code to achieve the same::
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;
public class RequiredRectangle {
public static void main(String[] args) {
// test the method
int n=10;
Rectangle[] input = new Rectangle[n];
Random r = new Random();
for(int i=0;i<n;i++){
input[i] = new Rectangle(r.nextInt(100)+1,r.nextInt(100)+1);
}
System.out.println("INPUT:: "+Arrays.deepToString(input));
Rectangle[] output = getMaxLengthDiffAndGreaterBreadthPair(input);
System.out.println("OUTPUT:: "+Arrays.deepToString(output));
}
public static Rectangle[] getMaxLengthDiffAndGreaterBreadthPair(Rectangle[] input){
Rectangle[] output = new Rectangle[2];
Arrays.sort(input, new Comparator<Rectangle>() {
public int compare(Rectangle rc1,Rectangle rc2){
return rc1.getBreadth()-rc2.getBreadth();
}
});
int len=0;
Rectangle obj1,obj2;
for(int i=0;i<input.length;i++){
obj2=input[i];
for(int j=i+1;j<input.length;j++){
obj1=input[j];
int temp=obj1.getLength() - obj2.getLength();
if(temp>len && obj1.getBreadth() > obj2.getBreadth()){
len=temp;
output[0]=obj1;
output[1]=obj2;
}
}
}
return output;
}
}
class Rectangle{
private int length;
private int breadth;
public int getLength(){
return length;
}
public int getBreadth(){
return breadth;
}
public Rectangle(int length,int breadth){
this.length=length;
this.breadth=breadth;
}
#Override
public boolean equals(Object obj){
Rectangle rect = (Rectangle)obj;
if(this.length==rect.length && this.breadth==rect.breadth)
return true;
return false;
}
#Override
public String toString(){
return "["+length+","+breadth+"]";
}
}
`
Sample Output:
INPUT:: [[8,19], [68,29], [92,14], [1,27], [87,24], [57,42], [45,5], [66,27], [45,28], [29,11]]
OUTPUT:: [[87,24], [8,19]]

Subset sum with positive and negative integers

I've to implement a variation of the subset sum problem, my input will be positive and negative decimal, also I will need to know the subset, knowing that exists unfortunately it's not enough.
I've tried the algorithms found on wikipedia, but I can't make them work with negative numbers, and also I can't find the way to obtain the subset if it exists.
Could anyone point me where I could find some pseudo-code, documentation or implementation, for this algorithm.
I wrote the code in Java
it checks all the possibilities
import java.util.*;
public class StackOverFlow {
public static <T> Set<Set<T>> powerSet(Set<T> originalSet) {
Set<Set<T>> sets = new HashSet<Set<T>>();
if (originalSet.isEmpty()) {
sets.add(new HashSet<T>());
return sets;
}
List<T> list = new ArrayList<T>(originalSet);
T head = list.get(0);
Set<T> rest = new HashSet<T>(list.subList(1, list.size()));
for (Set<T> set : powerSet(rest)) {
Set<T> newSet = new HashSet<T>();
newSet.add(head);
newSet.addAll(set);
sets.add(newSet);
sets.add(set);
}
return sets;
}
public static int sumSet(Set<Integer> set){
int sum =0;
for (Integer s : set) {
sum += s;
}
return sum;
}
public static void main(String[] args) {
Set<Integer> mySet = new HashSet<Integer>();
mySet.add(-1);
mySet.add(2);
mySet.add(3);
int mySum = 4;
for (Set<Integer> s : powerSet(mySet)) {
if(mySum == sumSet(s))
System.out.println(s + " = " + sumSet(s));
}
}
}
I hope it helps

Is it possible to design a tree where nodes have infinitely many children?

How can design a tree with lots (infinite number) of branches ?
Which data structure we should use to store child nodes ?
You can't actually store infinitely many children, since that won't fit into memory. However, you can store unboundedly many children - that is, you can make trees where each node can have any number of children with no fixed upper bound.
There are a few standard ways to do this. You could have each tree node store a list of all of its children (perhaps as a dynamic array or a linked list), which is often done with tries. For example, in C++, you might have something like this:
struct Node {
/* ... Data for the node goes here ... */
std::vector<Node*> children;
};
Alternatively, you could use the left-child/right-sibling representation, which represents a multiway tree as a binary tree. This is often used in priority queues like binomial heaps. For example:
struct Node {
/* ... data for the node ... */
Node* firstChild;
Node* nextSibling;
};
Hope this helps!
Yes! You can create a structure where children are materialized on demand (i.e. "lazy children"). In this case, the number of children can easily be functionally infinite.
Haskell is great for creating "functionally infinite" data structures, but since I don't know a whit of Haskell, here's a Python example instead:
class InfiniteTreeNode:
''' abstract base class for a tree node that has effectively infinite children '''
def __init__(self, data):
self.data = data
def getChild(self, n):
raise NotImplementedError
class PrimeSumNode(InfiniteTreeNode):
def getChild(self, n):
prime = getNthPrime(n) # hypothetical function to get the nth prime number
return PrimeSumNode(self.data + prime)
prime_root = PrimeSumNode(0)
print prime_root.getChild(3).getChild(4).data # would print 18: the 4th prime is 7 and the 5th prime is 11
Now, if you were to do a search of PrimeSumNode down to a depth of 2, you could find all the numbers that are sums of two primes (and if you can prove that this contains all even integers, you can win a big mathematical prize!).
Something like this
Node {
public String name;
Node n[];
}
Add nodes like so
public Node[] add_subnode(Node n[]) {
for (int i=0; i<n.length; i++) {
n[i] = new Node();
p("\n Enter name: ");
n[i].name = sc.next();
p("\n How many children for "+n[i].name+"?");
int children = sc.nextInt();
if (children > 0) {
Node x[] = new Node[children];
n[i].n = add_subnode(x);
}
}
return n;
}
Full working code:
class People {
private Scanner sc;
public People(Scanner sc) {
this.sc = sc;
}
public void main_thing() {
Node head = new Node();
head.name = "Head";
p("\n How many nodes do you want to add to Head: ");
int nodes = sc.nextInt();
head.n = new Node[nodes];
Node[] n = add_subnode(head.n);
print_nodes(head.n);
}
public Node[] add_subnode(Node n[]) {
for (int i=0; i<n.length; i++) {
n[i] = new Node();
p("\n Enter name: ");
n[i].name = sc.next();
p("\n How many children for "+n[i].name+"?");
int children = sc.nextInt();
if (children > 0) {
Node x[] = new Node[children];
n[i].n = add_subnode(x);
}
}
return n;
}
public void print_nodes(Node n[]) {
if (n!=null && n.length > 0) {
for (int i=0; i<n.length; i++) {
p("\n "+n[i].name);
print_nodes(n[i].n);
}
}
}
public static void p(String msg) {
System.out.print(msg);
}
}
class Node {
public String name;
Node n[];
}
I recommend you to use a Node class with a left child Node and right child Node and a parent Node.
public class Node
{
Node<T> parent;
Node<T> leftChild;
Node<T> rightChild;
T value;
Node(T val)
{
value = val;
leftChild = new Node<T>();
leftChild.parent = this;
rightChild = new Node<T>();
rightChild.parent = this;
}
You can set grand father and uncle and sibling like this.
Node<T> grandParent()
{
if(this.parent.parent != null)
{
return this.parent.parent;
}
else
return null;
}
Node<T> uncle()
{
if(this.grandParent() != null)
{
if(this.parent == this.grandParent().rightChild)
{
return this.grandParent().leftChild;
}
else
{
return this.grandParent().rightChild;
}
}
else
return null;
}
Node<T> sibling()
{
if(this.parent != null)
{
if(this == this.parent.rightChild)
{
return this.parent.leftChild;
}
else
{
return this.parent.rightChild;
}
}
else
return null;
}
And is impossible to have infinite child, at least you have infinite memory.
good luck !
Hope this will help you.

How do I find all paths in a sequence of edges in a fast way?

Let E be a given directed edge set. Suppose it is known that the edges in E can form a directed tree T with all the nodes (except the root node) has only 1 in-degree. The problem is how to efficiently traverse the edge set E, in order to find all the paths in T?
For example, Given a directed edge set E={(1,2),(1,5),(5,6),(1,4),(2,3)}. We know that such a set E can generate a directed tree T with only 1 in-degree (except the root node). Is there any fast method to traverse the edge set E, in order to find all the paths as follows:
Path1 = {(1,2),(2,3)}
Path2 = {(1,4)}
Path3 = {(1,5),(5,6)}
By the way, suppose the number of edges in E is |E|, is there complexity bound to find all the paths?
I have not worked on this kind of problems earlier. So just tried out a simple solution. Check this out.
public class PathFinder
{
private static Dictionary<string, Path> pathsDictionary = new Dictionary<string, Path>();
private static List<Path> newPaths = new List<Path>();
public static Dictionary<string, Path> GetBestPaths(List<Edge> edgesInTree)
{
foreach (var e in edgesInTree)
{
SetNewPathsToAdd(e);
UpdatePaths();
}
return pathsDictionary;
}
private static void SetNewPathsToAdd(Edge currentEdge)
{
newPaths.Clear();
newPaths.Add(new Path(new List<Edge> { currentEdge }));
if (!pathsDictionary.ContainsKey(currentEdge.PathKey()))
{
var pathKeys = pathsDictionary.Keys.Where(c => c.Split(",".ToCharArray())[1] == currentEdge.StartPoint.ToString()).ToList();
pathKeys.ForEach(key => { var newPath = new Path(pathsDictionary[key].ConnectedEdges); newPath.ConnectedEdges.Add(currentEdge); newPaths.Add(newPath); });
pathKeys = pathsDictionary.Keys.Where(c => c.Split(",".ToCharArray())[0] == currentEdge.EndPoint.ToString()).ToList();
pathKeys.ForEach(key => { var newPath = new Path(pathsDictionary[key].ConnectedEdges); newPath.ConnectedEdges.Insert(0, currentEdge); newPaths.Add(newPath); });
}
}
private static void UpdatePaths()
{
Path oldPath = null;
foreach (Path newPath in newPaths)
{
if (!pathsDictionary.ContainsKey(newPath.PathKey()))
pathsDictionary.Add(newPath.PathKey(), newPath);
else
{
oldPath = pathsDictionary[newPath.PathKey()];
if (newPath.PathWeights < oldPath.PathWeights)
pathsDictionary[newPath.PathKey()] = newPath;
}
}
}
}
public static class Extensions
{
public static bool IsNullOrEmpty(this IEnumerable<object> collection) { return collection == null || collection.Count() > 0; }
public static string PathKey(this ILine line) { return string.Format("{0},{1}", line.StartPoint, line.EndPoint); }
}
public interface ILine
{
int StartPoint { get; }
int EndPoint { get; }
}
public class Edge :ILine
{
public int StartPoint { get; set; }
public int EndPoint { get; set; }
public Edge(int startPoint, int endPoint)
{
this.EndPoint = endPoint;
this.StartPoint = startPoint;
}
}
public class Path :ILine
{
private List<Edge> connectedEdges = new List<Edge>();
public Path(List<Edge> edges) { this.connectedEdges = edges; }
public int StartPoint { get { return this.IsValid ? this.connectedEdges.First().StartPoint : 0; } }
public int EndPoint { get { return this.IsValid ? this.connectedEdges.Last().EndPoint : 0; } }
public bool IsValid { get { return this.EdgeCount > 0; } }
public int EdgeCount { get { return this.connectedEdges.Count; } }
// For now as no weights logics are defined
public int PathWeights { get { return this.EdgeCount; } }
public List<Edge> ConnectedEdges { get { return this.connectedEdges; } }
}
I think DFS(Depth First Search) should suit your requirements. Have a look at it here - Depth First Search - Wikipedia. You can tailor it to print the paths in the format that you require. As regards the complexity, since every node in your tree has in-degree one , the number of edges for your tree is bounded as - |E| = O(|V|). Since DFS operates with a complexity of O(|V|+|E|), your overall complexity comes out to be O(|V|).
I did this question as a part of a my assignment. The gentleman above has correctly pointed out to use pathID. You must visit each edge atleast once hence the complexity bound is O(V+E) but for tree E=O(V) therefore the complexity is O(v). I will give you a glimpse since the details are bit involved -
you will label each path with a unique ID and the path are alloted IDs in the incremental values such as 0,1,2.... A pathID of a path is the sum of weights of the edges on the path. So using DFS allocate weights to the path. You may begin by using 0 for edges until you encounter your first path and then you keep adding 1 and so on. You will also have to argue the correctness and properly allocate the weights. DFS will do the trick.

Resources