SumoLogic Interview Question for Software Engineer in Tests


Country: India
Interview Type: Phone Interview




Comment hidden because of low score. Click to expand.
2
of 2 vote

There are 3 basic structures that are required for these operations.
1. Hashmap : to support add, delete, contains
2. Double linked list : to support most recent entry. That is most recent added. Since we are using hashmap, to maintain last added value (most recent) we required double linked list.. (double linked list helps in the case of deletion - we can delete any element).. getMostRecent() will be in o(1)
3. One array : to keep the number of elements present upto date. This will help in randomization... getRandom() will be o(1)

structure of one node in hash will be
hash[value] = {array index, double linked list ptr}

So, the operations will be..

1. add(e) : when we add one value, hash[e] = {arr index, double linked list ptr}
2. delete(e) : when we delete one value, We are going to replace the cell that contains value in array with the last element in array. let d be the last element in the array A at index m. let i be H[value], the index in the array of the value to be removed. Set A[i]=d, H[d]=i, decrease the size of the array by one, and remove value from H. Since we are keeping a double linked list ptr.. deletion will be an easier operation to keep the most recent accordingly...
3. contains(e) : returns hash.contains(e)
4. getRandom() : return array[rand() % (array length)]
5. getMostRecent() : return last element of the double linked list

- Psycho August 06, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

nice! was asked the same question recently and gave similar solution!

- thriver April 16, 2022 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

It will required a combination of HashMap, DoublyLinkedList and a random method.
1. Use HashMap\Table to store elements in key value pairs (we can use element as a key too).
Now all of these operations will be in O(1) complexity:
1. void add(e)
2. void delete(e)
3. boolean contains(e)

2. We need a linked list to perform getMostRecent() in O(1), and i will prefer doubly linked list to remove the complexity of last element.
Each time you access an element from the map, just add it's reference at the end of list. If you delete an element than find its reference from the map and remove from list too.

3. We will need a random method for getRandom(). 
//Class variable 
int previousRandom = 0;
e getRandom(){
   //Select any two prime numbers as A and B
   previousRandom = (A * previousRandom  + B) Mod sizeOfMap;
   //use  previousRandom  as hashcode to find an element from the map.
}

- Ajeet August 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Ajeet: getMostRecent() can also be done by circular linked list?

- variksla August 06, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

How do you get some random index ensuring that it has value present in that index?

- Psycho August 06, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@variksla
Yes we can do, but it will not make any difference.

@Psycho
For missing index we will use HashMap's "linear probing" concept. Suppose if we have random index 5, but there is no element at index 5, so we will continue a linear search from 5 to end of the array, untill we will not find an element.
Just like HashMap's concept to resolve a hash collision.

- Ajeet August 07, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Ajeet FYI: Linear Probing worst case is O(N) but i agree that Average Case is O(1) since even Hashtable itself works on Average cases( Search AVG: O(1), Worst: O(N) due to collision or probing)

- deepak_gta August 07, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@deepak_gta
Yup that's true. But we dont have any other option.

- Ajeet August 07, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

When you are saying the elment to be key itself, then we are assuming that all the objects inserted will be immutable objects. I don't think that is the case.

We should use hashcode as key for storing data in hashmap.

- Dhruv August 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

template<class T>
class MyContainer {
private:
	typedef struct MyNode {
		T val;
		MyNode* next;
		MyNode* prev;
	} LNode, *PLNode;

	hash_map<T, PLNode> m_container;
	PLNode m_head, m_tail;
public:
	void add(T e) {
		PLNode tmp = new LNode();
		tmp->val = e;
		tmp->prev = nullptr;
		tmp->next = m_head;
		m_head = tmp;
		m_container.insert(pair(e, tmp);
	}
	void delete(T e) {
		PLNode tmp = m_container.find(e).second;
		tmp->prev->next = tmp->next;
		delete tmp;		
		m_container.erase(e);
	}
	bool contains(T e) { return (m_container.find(e) != m_container.end()) }
	T getRandom(){
		int size = m_container.size();
		int randomIndex = rand() % size - 1;

		return (m_container.begin() + randomIndex).first;
	}
	T getMostRecent() {
		return m_head->val;
	}
};

- sameepsheth August 06, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Are duplicate values allowed?

- Ann August 06, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

With the hash table we can achieve this.

1. Add -> 0(1)
2. Delete -> O(1)
3. Contains -> 0(1)
4. GetRandom -> Need a random number generator to arbitrarily select the some random key, store it in a class variable (say mostRecent) and return the value.
5. GetMostRecent -> Using the mostRecent variable get the hashkey and return the value.

- S August 07, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Have in mind Hash Tables collisions

- ATL October 15, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

I think HashMap can solve the problem. Add/Delete/Contains will be O(1) as it's nothing but a Entry Array operations on Array will be O(1), hashing works on bucketing system so finding random number should match to the bucket number.

- Sameer Shukla August 07, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

package com.sumologic.codingexercise;

import java.util.HashMap;
import java.util.Random;

class CustomDS2 {
    private HashMap<Integer, Integer> map;
    private int[] arr;
    private int currentSize = 0;

    public CustomDS2(int maxCapacity) {
        map = new HashMap<Integer, Integer>();
        arr = new int[maxCapacity];
    }

    public void add(int e) {
        arr[currentSize] = e;
        currentSize++;
        map.put(e, currentSize);
    }

    public void remove(int e) {
        int d = arr[currentSize];
        int i = map.get(e);
        arr[i] = d;
        map.put(d, i);
        currentSize--;
        map.remove(e);
    }

    public boolean contains(int e) {
        return map.containsKey(e);
    }

    public int getRandom() {
        Random random = new Random();
        int rand = random.nextInt(currentSize);
        return arr[rand];
    }
}

- Vaibhav Agarwal August 09, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

How about getMostRecent?

- Anonymous April 03, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

import random

class DoubleLinkedList():
  def __init__(self, data):
    self.data = data
    self.next = None
    self.prev = None

class Hash():
  def __init__(self):
    self.map = {}
    self.head = None
    self.current = None
    self.recent_element_list = []

  def contains(self, e):
    """
    This function checks if the element
    alreadys exists in the map
    @param : e element to be found
    @return : True or False
    """
    element = self.map.get(e, None)
    if element:
     return True
    else:
     return False
  
  def add(self, e):
    """
    This function is used to add any element 
    in the map
    """

    # Checking in the element already exists
    # in the map. 
    if self.contains(e):
      print "Element already exists in the Hash"
    else:
      if self.head is None or self.current is None:
        element = DoubleLinkedList(e)
        self.head = element
        self.current = element
      else:
        element = DoubleLinkedList(e)
        element.prev = self.current
        element.prev.next = element
        self.current = element
      self.map[e] = element

  def delete(self, e):
    """
    This function deletes the element from the
    map
    @param: e element to be deleted
    """

    # Checking in the element already exists
    # in the map.
    if self.contains(e):
      if self.map[e] == self.current:
        self.current = self.current.prev
        element = self.map[e]
        del(element)
      else:
        element = self.map[e]
        if element.next == self.current:
          self.current.prev = element.prev
        if self.head == element:
          self.head = element.next
          element.next.prev = element.prev
        else:
          element.prev.next = element.next.prev
          element.next.prev = element.prev.next
      self.map.pop(e, None)
      
    else:
      print "Element doesn't exists in the Hash"

  def getRandom(self):
    """
    This function returns any random element
    form the Hash
    """

    key_list = self.map.keys()
    if len(key_list) == 0:
      print "Hash is empty. Please enter the elements into Hash first"
    else:
      rand_index = random.randint(0, len(key_list)-1)
      rand_key = key_list[rand_index]
      return rand_key

  def getMostRecent(self):
    """
    This function returns the most recent element added
    in the Hash
    """
    
    # Checking if the recent element list contains
    # any element

    if self.current is not None:
      return self.current.data
    else:
      print "No element in the Hash"

- Sunil Kumar Goyal August 27, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

A cpp sollution, except getRandom() all functions are almost constant order

#include<iostream>
#include<map>
#include<list>
#include<iterator>
#include<cstdlib>
#include<ctime>

using namespace std;

template <class E>
class myContainer {
private:
    map<E, typename list<E>::iterator> emap;
    list<E> elist;
    
public:
    void add(E e);
    void deleteElement(E e);
    void toString();
    bool contains(E e);
    E getRandom();
    E getMostRecent();
};

template <class E>
void myContainer<E>::add(E e) {
    if(contains(e)) return;
    emap[e] = elist.insert(elist.end(), e);
}

template <class E>
void myContainer<E>::deleteElement(E e) {
    if(!contains(e)) return;
    elist.erase(emap[e]);
    emap.erase(e);
}

template <class E>
inline bool myContainer<E>::contains(E e) {
    if(emap.find(e) != emap.end()) return true;
    return false;
}

template <class E>
E myContainer<E>::getRandom() {
    typename list<E>::iterator it = elist.begin();
    int pos = rand()%elist.size();
    while(pos--) it++;
    return *it;
}

template <class E>
E myContainer<E>::getMostRecent() {
    return elist.back();
}

template <class E>
void myContainer<E>::toString() {
    typename map<E, typename list<E>::iterator>::iterator it;
    typename list<E>::iterator it1;
    cout << "Map contains:" << endl;
    for(it = emap.begin(); it!= emap.end(); it++) {
        cout << it->first << " ";
    }
    cout << endl;
    cout << "List contains:" << endl;
    for(it1 = elist.begin(); it1!= elist.end(); it1++) {
        cout << *it1 << "<->";
    }
    cout << endl;
}
int main() {
    srand(time(NULL));
    myContainer<int> intContainer;
    intContainer.add(1);
    intContainer.add(2);
    intContainer.add(3);
    cout << "Most recent " << intContainer.getMostRecent() << endl;
    intContainer.deleteElement(2);
    intContainer.deleteElement(2);
    intContainer.add(4);
    if(intContainer.contains(4)) {
        cout << "Contains " << 4 << endl;
    }
//    intContainer.toString();
    cout << "Random element: " <<intContainer.getRandom() << endl;
    return 0;
}

- lamda December 27, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

package com.test.coding;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Stack;

public class LookUp<T> {

	Map<T, Integer> m;

	List<T> list;

	Stack<Node<T>> s;

	int currIndex;

	public LookUp() {
		m = new LinkedHashMap<T, Integer>();
		list = new ArrayList<T>();
		s = new Stack<Node<T>>();

		currIndex = 0;
	}

	void add(T val) {
		if (list.size() > currIndex) {
			list.set(currIndex, val);
		} else {
			list.add(currIndex, val);
		}
		Node<T> node = new Node<T>(val, currIndex);
		s.push(node);
		m.put(val, currIndex);
		currIndex++;

		System.out.println("add: " + list.toString());
	}

	void delete(T val) {
		if (m.containsKey(val)) {
			int elementIndex = m.get(val);
			System.out.println("Index: " + val + " " + elementIndex);
			m.remove(val);

			list.set(elementIndex, list.get(currIndex - 1));
			currIndex--;

			Node<T> topNode = s.peek();
			if (topNode.getIndex().equals(elementIndex)) {
				s.pop();
			}
		}
		System.out.println("delete: " + list.toString() + " curr index"
				+ currIndex);
	}

	boolean contains(T val) {
		if (m.containsKey(val)) {
			return true;
		}
		return false;
	}

	T getRecent() {
		if (!s.isEmpty()) {
			return s.peek().getVal();
		}
		return null;
	}

	T getRandom() {

		Random rand = new Random();
		int randomIndex = rand.nextInt((currIndex - 0) ) + 0;

		System.out.println("random index: " + randomIndex);
		return list.get(randomIndex);

	}

}

package com.test.coding;

public class Node<T> {

	private T val;
	private Integer index;

	public Integer getIndex() {
		return index;
	}

	public T getVal() {
		return val;
	}

	public Node(T val2, int lastIndex) {
		val = val2;
		index = lastIndex;
	}
}

- dheeraj2311 August 26, 2015 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More