Counting leaf node in a trie - java

I want to count how many leaf node in a trie structure by counting how many words there are in the trie, but my code is not updating the counting value, instead it always reset back to 0.
int num = 0;
public int countLeafNodes() {
for (char c : children.keySet()) {
Trie node = children.get(c);
System.out.println(c);
if (node.isWord) {
num++;
System.out.println(num);
}
node.countLeafNodes();
}
return num;
}

You are ignoring the value returned by the recursive call (node.countLeafNodes()).
Try :
public int countLeafNodes()
{
int num = 0;
for (char c : children.keySet()) {
Trie node = children.get(c);
System.out.println(c);
if (node.isWord) {
num++;
System.out.println(num);
}
num += node.countLeafNodes();
}
return num;
}

So it appears that the issue is that when you return from your recursion you are not taking in to account the values being returned. What I mean is that when counting the leaf nodes in the children you are not adding that total to the parents. If that is the issue you would just need to change
node.countLeafNodes();
to
num += node.countLeafNodes();

Related

Reduced time complexity of inner loop: Find count of elements greater than current element in the first loop and store that in solved array

I want to reduce the complexity of this program and find count of elements greater than current/picked element in first loop (array[])and store the count in solved array(solved[]) and loop through the end of the array[]. I have approached the problem using a general array based approach which turned out to have greater time complexity when 2nd loop is huge.
But If someone can suggest a better collection here in java that can reduce the complexity of this code that would also be highly appreciated.
for (int i = 0; i < input; i++) {
if (i < input - 1) {
count=0;
for (int j = i+1; j < input; j++) {
System.out.print((array[i])+" ");
System.out.print("> ");
System.out.print((array[j]) +""+(array[i] > array[j])+" ");
if (array[i] > array[j]) {
count++;
}
}
solved[i] = count;
}
}
for (int i = 0; i < input; i++) {
System.out.print(solved[i] + " ");
}
What I want to achieve in simpler terms
Input
Say I have 4 elements in my
array[] -->86,77,15,93
output
solved[]-->2 1 0 0
2 because after 86 there are only two elements 77,15 lesser than 86
1 because after 77 there is only 15 lesser than 77
rest 15 <93 hence 0,0
So making the code simpler and making the code faster aren't necessarily the same thing. If you want the code to be simple and readable, you could try a sort. That is, you could try something like
int[] solved = new int[array.length];
for (int i = 0; i < array.length; i++){
int[] afterward = Arrays.copyOfRange(array, i, array.length);
Arrays.sort(afterward);
solved[i] = Arrays.binarySearch(afterward, array[i]);
}
What this does it it takes a copy of the all the elements after the current index (and also including it), and then sorts that copy. Any element less than the desired element will be beforehand, and any element greater will be afterward. By finding the index of the element, you're finding the number of indices before it.
A disclaimer: There's no guarantee that this will work if duplicates are present. You have to manually check to see if there are any duplicate values, or otherwise somehow be sure you won't have any.
Edit: This algorithm runs in O(n2 log n) time, where n is the size of the original list. The sort takes O(n log n), and you do it n times. The binary search is much faster than the sort (O(log n)) so it gets absorbed into the O(n log n) from the sort. It's not perfectly optimized, but the code itself is very simple, which was the goal here.
With Java 8 streams you could reimplement it like this:
int[] array = new int[] { 86,77,15,93 };
int[] solved =
IntStream.range(0, array.length)
.mapToLong((i) -> Arrays.stream(array, i + 1, array.length)
.filter((x) -> x < array[i])
.count())
.mapToInt((l) -> (int) l)
.toArray();
There is actually a O(n*logn) solution, but you should use a self balancing binary search tree such as red-black tree.
Main idea of the algorithm:
You will iterate through your array from right to left and insert in the tree triples (value, sizeOfSubtree, countOfSmaller). Variable sizeOfSubtree will indicate the size of the subtree rooted at that element, while countOfSmaller counts the number of elements that are smaller than this element and appear at the right side of it in the original array.
Why binary search tree? An important property of BST is that all nodes in the left subtree are smaller than the current node, and all in the right subtree are greater.
Why self-balancing tree? Because this will guarantee you O(logn) time complexity while inserting a new element, so for n elements in array that will give O(n*logn) in total.
When you insert a new element you will also calculate the value of countOfSmaller by counting elements that are currently in the tree and are smaller than this element - exactly what are we looking for. Upon inserting in the tree compare the new element with the existing nodes, starting with the root. Important: if the value of the new element is greater than the value of the root, it means that is also greater than all the nodes in the left subtree of root. Therefore, set countOfSmaller to the sizeOfSubtree of root's left child + 1 (because the new element is also greater than root) and proceed recursively in the right subtree. If it is smaller than root, it goes to the left subtree of root. In both cases increment sizeOfSubtree of root and proceed recursively. While rebalancing the tree, just update the sizeOfSubtree for nodes that are included in left/right rotation and that's it.
Sample code:
public class Test
{
static class Node {
public int value, countOfSmaller, sizeOfSubtree;
public Node left, right;
public Node(int val, int count) {
value = val;
countOfSmaller = count;
sizeOfSubtree = 1; /** You always add a new node as a leaf */
System.out.println("For element " + val + " the number of smaller elements to the right is " + count);
}
}
static Node insert(Node node, int value, int countOfSmaller)
{
if (node == null)
return new Node(value, countOfSmaller);
if (value > node.value)
node.right = insert(node.right, value, countOfSmaller + size(node.left) + 1);
else
node.left = insert(node.left, value, countOfSmaller);
node.sizeOfSubtree = size(node.left) + size(node.right) + 1;
/** Here goes the rebalancing part. In case that you plan to use AVL, you will need an additional variable that will keep the height of the subtree.
In case of red-black tree, you will need an additional variable that will indicate whether the node is red or black */
return node;
}
static int size(Node n)
{
return n == null ? 0 : n.sizeOfSubtree;
}
public static void main(String[] args)
{
int[] array = {13, 8, 4, 7, 1, 11};
Node root = insert(null, array[array.length - 1], 0);
for(int i = array.length - 2; i >= 0; i--)
insert(root, array[i], 0); /** When you introduce rebalancing, this should be root = insert(root, array[i], 0); */
}
}
As Miljen Mikic pointed out, the correct approach is using RB/AVL tree. Here is the code that can read and N testcase do the job as quickly as possible. Accepting Miljen code as the best approach to the given problem statement.
class QuickReader {
static BufferedReader quickreader;
static StringTokenizer quicktoken;
/** call this method to initialize reader for InputStream */
static void init(InputStream input) {
quickreader = new BufferedReader(new InputStreamReader(input));
quicktoken = new StringTokenizer("");
}
static String next() throws IOException {
while (!quicktoken.hasMoreTokens()) {
quicktoken = new StringTokenizer(quickreader.readLine());
}
return quicktoken.nextToken();
}
static int nextInt() throws IOException {
return Integer.parseInt(next());
}
static long nextLong() throws IOException {
return Long.parseLong(next());
}
static double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
public class ExecuteClass{
static int countInstance = 0;
static int solved[];
static int size;
static class Node {
public int value, countOfSmaller, sizeOfSubtree;
public Node left, right;
public Node(int val, int count, int len, int... arraytoBeused) {
countInstance++;
value = val;
size = len;
countOfSmaller = count;
sizeOfSubtree = 1; /** You always add a new node as a leaf */
solved = arraytoBeused;
solved[size - countInstance] = count;
}
}
static Node insert(Node node, int value, int countOfSmaller, int len, int solved[]) {
if (node == null)
return new Node(value, countOfSmaller, len, solved);
if (value > node.value)
node.right = insert(node.right, value, countOfSmaller + size(node.left) + 1, len, solved);
else
node.left = insert(node.left, value, countOfSmaller, len, solved);
node.sizeOfSubtree = size(node.left) + size(node.right) + 1;
return node;
}
static int size(Node n) {
return n == null ? 0 : n.sizeOfSubtree;
}
public static void main(String[] args) throws IOException {
QuickReader.init(System.in);
int testCase = QuickReader.nextInt();
for (int i = 1; i <= testCase; i++) {
int input = QuickReader.nextInt();
int array[] = new int[input];
int solved[] = new int[input];
for (int j = 0; j < input; j++) {
array[j] = QuickReader.nextInt();
}
Node root = insert(null, array[array.length - 1], 0, array.length, solved);
for (int ii = array.length - 2; ii >= 0; ii--)
insert(root, array[ii], 0, array.length, solved);
for (int jj = 0; jj < solved.length; jj++) {
System.out.print(solved[jj] + " ");
}
System.out.println();
countInstance = 0;
solved = null;
size = 0;
root = null;
}
}
}

Complexity of two nested loops that do not always run

I need to write an answer with the least complexity degree. My questions is regarding nested-loops that do not always run. I have a for loops that iterates N times, depending on length of the string, and searches for a 'char' value. When it finds it, it iterates the loop again from this point onwards, looking for more 'char' values.
I wrote the following method:
public static int subStrMaxC(String s, char c, int k) {
char[] stringChars=new char[s.length()];
//System.out.print("the string of the characters is");
for(int i=0;i<stringChars.length;i++) {
stringChars[i]=s.charAt(i);
// System.out.print(stringChars[i]);
}
int count=0;
int bigcount=0;
int[] charArray=new int[s.length()];
for(int i=0;i<stringChars.length;i++) {
count=0;
if(stringChars[i]=='c') {
count++;
for(int j=i+1;j<stringChars.length;j++) {
if(stringChars[j]=='c') {
count++;
if((count>=2)&&(count<=k+2)) {
bigcount++;
if(count==k+2) {
count=0;
j=stringChars.length-1;
}
}
}
}
}
}
return bigcount;
}
Since the second loop do not iterate unless the first loop finds a value that meets the condition, I did not know whether the complexity is defined O(n^2)-which is my assumption, as the second loop can, in the worst case run N*(N-i) times- or just O(n), which is what I'm looking for.
Thank you!
I am quite sure this is the best you can do, but of course I may be wrong. The problem you have with your approach is your limited use of Space Complexity. With the approach below, you iterate through the string only once (i.e. no 'j' loop which leads to the n squared problem). Here you build out candidate substrings by using space/memory. Now you only have to iterate over candidate substrings which has a much lower time complexity than your first approach.
public class MaxKSubstring {
public static void main(String[] args) {
String INPUT = "testingwithtees";
char C = 't';
int K = 1;
int count = subStrMaxC(INPUT, C, K);
System.out.println(count);
}
public static int subStrMaxC(String s, char c, int k) {
char letters[] = s.toCharArray();
int valid = 0;
List<Candidate> candidates = new ArrayList<Candidate>();
for (int i=0; i< s.length(); i++) {
if (letters[i] == c)
candidates.add(new Candidate(k, c));
for (Candidate candidate : candidates) {
if (candidate.addLetter(letters[i])) {
System.out.println(candidate.value);
valid++;
}
}
}
return valid;
}
}
class Candidate {
final int K;
final char C;
public Candidate(int k, char c) {
super();
K = k;
C = c;
}
boolean endsWithC = false;
String value = "";
int kValue = 0;
public boolean addLetter(char letter) {
endsWithC = false;
value = value+letter;
if (letter == C) {
kValue++;
endsWithC = true;
}
return endsWithC && kValue <= K+2 && value.length() > 1;
}
}
O(n) best case,
O(n2) worst case
I'm not sure what you mean by the least complexity. If you are referring to the best case, that would be O(n) performance. (The parent loop iterates only and the nested loops are never iterated) since the matching case:
if(stringChars[i]=='c')
Is always false. However, the worst case time complexity which is usually what we're referring to is O(n2), owing to the fact that the condition if(stringChars[i]=='c') returns true every single time.

Inefficient java / arrays of unknown length

I am making a few methods that are used for finding the prime factors of a certain number. This is broken down into two functions which both use arrays. However, in both functions the code is very inefficient. First I have to count the length of the array, make a new array of that length and then use almost the exact same code to populate the array.
Is there a way I can make the array unknown width and push integers to the end of the array as I find them?
Here is my code:
public class JavaApplication7{
public static void main(String[] args) {
System.out.println(Arrays.toString(primeFactors(85251)));
}
public static int[] primeFactors(int num){
int[] factors = primesUpTo(num);
int originalNum = num;
int i = 0;
int count = 0;
while(num != 1){
if(num % factors[i] == 0){
num /= factors[i];
i = 0;
count++;
}else{
i++;
}
}
int[] primeFactors = new int[count];
i = 0;
count = 0;
while(originalNum != 1){
if(originalNum % factors[i] == 0){
originalNum /= factors[i];
primeFactors[count] = factors[i];
i = 0;
count++;
}else{
i++;
}
}
return primeFactors;
}
public static int[] primesUpTo(int upTo){
int count = 0;
int num = 2;
while(num <= upTo){
boolean isPrime = true;
for(int div = 2; div <= num / 2; div++){
isPrime = num % div == 0 ? false : isPrime;
}
count += isPrime ? 1 : 0;
num++;
}
int i = 0;
num = 2;
int[] primes = new int[count];
while(num <= upTo){
boolean isPrime = true;
for(int div = 2; div <= num / 2; div++){
isPrime = num % div == 0 ? false : isPrime;
}
if(isPrime){
primes[i] = num;
i++;
}
num++;
}
return primes;
}
}
You could use Arraylists that are more dynamic than Arrays.
However in both functions the code is very inefficient as first i have
to count the length of the array, make a new array of that length and
then use almost the exact same code to populate the array
However, you will find that Arraylists do seem dynamic but underneath they do a similar thing. They start with a size and make a copy of the underlying Array to a bigger one etc.
Another thing you can do if you know some upper bounds to how many numbers you will have to store is to implement you own container class. It can have a big array to hold the numbers and a length variable, for looping through the elements.
For example:
public class NumberContainer(){
private int[] elements;
private int numOfElements;
public NumberContainer(int size){
elements = new int[size];
numOfElements = 0;
}
//add a number
public void add(int x){
elements[numOfElements] = x;
numOfElements++;
}
//get length
public int length(){
return numOfElements;
}
}
....and so on.
This way you don't have to copy an Array to a new large one, allways assuming that you instantiate the NumberContainer with a large enough size.
Hope this helps
You can use a ArrayList which is created empty with no specific size and you can add (-> add(Object o) or remove (-> remove(int index)) anytime you want.
Use an ArrayList if you still need fast retrieval by Index. Otherwise consider a LinkedList, as add = O(1).
For LinkedList
get(int index) is O(n)
add(E element) is O(1)
add(int index, E element) is O(n)
remove(int index) is O(n)
Iterator.remove() is O(1) <--- main benefit of LinkedList<E>
ListIterator.add(E element) is O(1) <--- main benefit of LinkedList<E>
For ArrayList
get(int index) is O(1) <--- main benefit of ArrayList<E>
add(E element) is O(1) amortized, but O(n) worst-case since the array must be resized and copied
add(int index, E element) is O(n - index) amortized, but O(n) worst-case (as above)
remove(int index) is O(n - index) (i.e. removing last is O(1))
Iterator.remove() is O(n - index)
ListIterator.add(E element) is O(n - index)
When to use LinkedList over ArrayList?
I did
boolean isPrime = true;
for (int div = 2; div <= num / 2; div++) {
if (num % div == 0) {
isPrime = false;
break;
}
// Instead isPrime = num % div == 0 ? false : isPrime;
}
and the time needed went from 13 to 1 second.
Actually I wanted to try
public static int guessedPrimeCount(int upTo) {
if (upTo < 10) {
return 10;
}
return (int) (upTo / Math.log10(upTo - 1));
}
public int[] addToPrimes(int[] primes, int count, int p) {
if (count >= primes.length) {
primes = Arrays.copyOf(primes, count + 10);
}
primes[count] = p;
return primes;
}
primes = addToPrimes(primes, count, num);
++count;
The guessedPrimeCount is documented, x/log x, or x/log(x-1).
On adding a new prime p at [count], one in the worst case has to copy the entire array.
You can use an
ArrayList<Integer>
but this requires substantial memory overhead due to auto-boxing.
Or you can use the excellent GNU Trove3 libraries. These contain an TIntArrayList, which takes care of the resizing for you; and is essentially an int[] + a length field. The logic for appending to then is roughly:
double[] array = new double[10]; // Allocated space
int size = 0; // Used space
void add(int v) {
if (size == array.length) {
array = Arrays.copyOf(array, array.length * 2);
}
array[size++] = v;
}

Dijkstra with a heap. How to update the heap after relaxation?

I am trying to implement Dijkstra algorithm.
foreach distance d
d = INFINITY
d[source] = 0
create_heap_based_on_Distances();
while(true)
bestedge = heap[0]
remove_minimum_from_heap //it will be heap[0]
foreach adjacency of bestedge
if (weight + bestedge_distance < current_distance)
{
current_distance = weight + bestedge_distance
// Now I have to update heap, how can I do that?
}
if (heap_empty) break
So, in the relaxation, how can I update the heap, so it would have the correct order? I don't have the heap's index for that node in that step. Does that mean I have to create a new array like nodes[edge] = heapIndex, so I could get a heap's index for that node? But it seems very inefficient as I need then to update insert_to_heap, remove_minimum functions.
C or JAVA code is okay.
Does that mean I have to create a new array like nodes[edge] = heapIndex, so I could get a heap's index for that node?
Yes.
But it seems very inefficient as I need then to update insert_to_heap, remove_minimum functions.
Array updates are very cheap, both in theory and in practice, and you only have to do a few of those per heap operation, so this is not inefficient at all. Also, the memory usage of such an array is very cheap compared to the storage cost of a graph data structure.
Does that mean I have to create a new array like nodes[edge] = heapIndex,
so I could get a heap's index for that node?
I don't what the exactly mean of node[edge]. In my opinion, it should be a Map(a array indeed) f that f[node]=HeapIndex(It gives the index of that node in Heap). Storage of the node[edge] is not efficient.
Then how to implement the MapHeap? I have implemented a efficient MapHeap, but not so much note in the code:
template<class DT>
struct MapHeap
{
DT f[HEAP_SIZE+5];//store the distance
int mp1[HEAP_SIZE+5];//val -> index
// I assume the val is unique.
// In the dijk, the val is the nodeId,so it must be unique.
// mp1[nodeId] gives the index of that node in my heap
int mp2[HEAP_SIZE+5];//index -> val
int nv;// number of node in my heap now
MapHeap():nv(0)
{
memset(mp1,-1,sizeof(mp1));
memset(mp2,-1,sizeof(mp2));
}
void print(int n)
{
for(int i=1;i<=n;i++) printf("%d ",f[i]);
puts("");
for(int i=1;i<=n;i++) printf("%d ",mp1[i]);
puts("");
for(int i=1;i<=n;i++) printf("%d ",mp2[i]);
puts("");
}
void print(){print(nv);}
bool resize(int n)
{
if (nv<0||nv>HEAP_SIZE) return 0;
for(int i=n+1;i<=nv;i++)
{
mp1[mp2[i]]=-1;
mp2[i]=-1;
}
nv=n;
return 1;
}
DT top()//get the smallest element
{
if (nv<1) return DT(-1);
return f[1];
}
DT get(int idx)
{
if (idx<1||idx>nv) return DT(-1);
return f[idx];
}
// it's for unpdating the heap. It should be pravite method.
// Because I write this code for competition, so I just ignore the accsee controling
void movedown(int now,int val,const DT &x)//this node is larger than son
{
for(;now*2<=nv;)
{
int a=now*2;
int b=now*2+1;
if (b<=nv&&f[b]<f[a]) a=b;
if (f[a]>=x) break;
f[now]=f[a];
mp1[mp2[a]]=now;
mp2[now]=mp2[a];
now=a;
}
f[now]=x;
mp1[val]=now;
mp2[now]=val;
}
void moveup(int now,int val,const DT &x)//this node is smaller than father
{
for(;now>1;now>>=1)
{
int par=now>>1;
if (f[par]<=x) break;
f[now]=f[par];
mp1[mp2[par]]=now;
mp2[now]=mp2[par];
}
f[now]=x;
mp1[val]=now;
mp2[now]=val;
}
bool pop(int idx=1)//pop a element, pop the smallest element by default
{
if (idx<1||idx>nv) return 0;
DT &x=f[nv];
int v1=mp2[nv];
int v2=mp2[idx];
mp1[v1]=idx;
mp2[idx]=v1;
mp1[v2]=-1;
mp2[nv]=-1;
nv--;
if (idx!=nv+1) movedown(idx,v1,x);
x=0;
return 1;
}
bool push(const DT &x,int val)//push a node, and with the value of val(in dijk, the val is the nodeId of that node)
{
int now=++nv;
if (now>HEAP_SIZE) return 0;
moveup(now,val,x);
return 1;
}
};

linked list print every nth integer method

I need to write a method for a linked list class that:
Print the contents of every "nth" node in the list. Obtain the "n" from the user, ensure it is
greater than 0.
How would i go about doing this?
public void nthNode (int n) {
if (n <= 0) {
System.out.println("error");
} else {
//bla
}
}
public void nthNode (int n) {
if (n <= 0) {
System.out.println("error");
} else {
for (int i = 0; i < size(); i += n) {
//LinkedList#get(i);
}
}
}
Iterate over every element in the list. If the index of the current item is evenly divisible by n then print the element. You can check for even divisibility by using the modulus operator (% in Java)
You main motive is to print the data of nodes when the counter will be a multiple of n.
so instead of checking the mod on data, u need to do it on counter and have the mod check with n.
Iterating over the link list (using say curr pointer) using while loop. Check for condition curr.next!=null. initialize count to 0. While iterating count the number of nodes traversed till now. If the (count == n), then print the node data and initialize count to 0.
Assuming you have a node class of some sort:
public void nthNode( int n ){
if( n <= 0 ){
System.out.println( "error" );
} else {
Node e = new Node();
e = head;
int count = 0;
while( e != null ){
if( count == n ){
//do stuff
break;
}
e = e.next;
cout++;
}
}
Sorry kinda sloppy but that's the gist.

Categories

Resources