Amazon Interview Question for SDE-2s


Country: United States




Comment hidden because of low score. Click to expand.
5
of 7 vote

Consider a data structure composed of a hashtable H and an array A. The hashtable keys are the elements in the data structure, and the values are their positions in the array.

1.insert(value): append the value to array and let i be it's index in A. Set H[value]=i.
2.remove(value): We are going to replace the cell that contains value in A with the last element in A. 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.

3.getRandomElement(): let r=random(current size of A). return A[r].

- blackfever November 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

This one is perfect.

- Subbu. November 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Why do people downvote without understanding?

- Subbu. November 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
-1
of 3 votes

why cannot only use Hashtable. Hashtable's add and remove is O(1)

- Anonymous November 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

@Anon: How will you do removeRandom in O(1) with just a Hashtable?

- Anonymous November 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

I dont think this is correct, I think a remove from an array is always O(n). How do you 'decrease the array by one'? Only be getting new memory and copying to it. Anything else will not free that memory so it still claimed. It maybe an acceptable solution but you going to be wasting memory.

Consider a similar solution, a hashtable and linkedList. Remove in a linked listed when given a pointer to the element is O(1). To remove a random element you can use the hashtable to lookup the pointer to that element so the remove is O(1).

- Anonymous November 22, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Anon:

It is correct. Replace array with vector (which can be made worst case O(1) and not just amortized).

As for remove, a neat trick of swapping with the last element is being used (please read the description).

Every operation is indeed O(1).

btw, this problem has appeared multiple times, with getRandom instead of remove random, there might be some other explanation which will help you better understand. I suggest you try searching for it.

- Anonymous November 22, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I understand it, I just don't think "decrease the size of the array by one" is a valid operation in any real programming language. "Replace array with vector" means a hashtable and vector is a valid answer but the terms array and vector are not interchangable.

- Anonymous November 22, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Anon.

Decrease size of array is just decrementing a variable called, err, size. You don't actually go and try to deallocate the memory for the last byte. To make it easier for you, 'reduce the count by 1'.

Replace array with vector means hashtable? What? You lost me there.

I suggest (again) you search for previous answers. Maybe those will help.

This answer is good. Your dismissal of this answer is your loss.

- Anonymous November 22, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Anon
Decreasing the size of an array isn't just decreasing a size variable
Often we want to shrink the array by half when it is below 1/4 full
Think before you talk please

- Anonymous November 23, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Anon: You really have no clue, do you?

I said use a vector, which does all that for you (shrinking/growing at the right time etc). I also said it can be made worst case O(1) rather than amortized O(1). Do you even understand that?

You are free to be a stubborn bonehead. No more explanation for you, idiot.

- Anonymous November 23, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The basic understanding of HashMap / HashTable is violated

The value as such calculated for the ELEM inserted is hashCode of the ELEMENT, and two ELEMENTS can have same hashCode. So the algo has problems firstly it does not store ELEMENTS with same hashCode and other

- Rock November 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

what if we allow duplicate?

- mike November 26, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@mike: Then you have to exactly define what removeRandom means...

- Anonymous November 26, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Mike Nope its not even case of duplicate. Two elements can have same hashcode and hence they lie in same bucket.

- Rock November 26, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

hmm i just see the exact solution posted on stackover flow 2 years ago. the issue is, you forgot to mention that, in order to keep a vector of keys (or arraylist, which is recommended), you might encounter insertion worse case O(n) (which should be fine)

- sixin210 November 30, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The remove(T) operation is hash table is not O(1) as it needs to iterate thru the sub Entries to findout the target element to remove

- Anonymous March 20, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Hashtable+vector are good choice only in synchronized context.
Vector behind the scene is dynamic resizable array , so reduce by one is same as in array.

So it seems best approach is Hashmap+ doublyLinkedList.

hashmap can be used for deleting random o(1). and adding & removing is O(1) in list

- RamJane March 25, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

This is my C++ version using two hashmaps. All operations are O(1).

#include <iostream>
#include <unordered_map>
#include <ctime>

template <typename T>
class rand_set {
public:
    rand_set() : elem2pos_map_(), pos2elem_map_(), next_slot_(0) {
        srand(time(NULL));
    }
    
	void add(T elem) {
		// Map element -> slot
		elem2pos_map_[elem] = next_slot_;
		// Map slot -> element
		pos2elem_map_[next_slot_] = elem;
		// Increase slot
        next_slot_++;
	}
	
	void remove(T elem) {
		// Find element
		auto it = elem2pos_map_.find(elem);
		if (it != elem2pos_map_.end()) {
			// Delete element
			elem2pos_map_.erase(it);
			size_t pos = it->second;
            pos2elem_map_.erase(pos);
		}
	}
	
	T removeRandom() {
        if (pos2elem_map_.empty())
            throw std::runtime_error("No elements found");

		// Find random element. Must be within 0 and next_slot_
        T elem;
        size_t pos = rand() % next_slot_;
        auto it = pos2elem_map_.find(pos);
        if (it != pos2elem_map_.end()) {
            elem = it->second;
        } else {
    		elem = pos2elem_map_.begin()->second;
    		pos = elem2pos_map_.at(elem);
        }
        
        elem2pos_map_.erase(elem);
        pos2elem_map_.erase(pos);
        return elem;
	}
	
private:
	typedef std::unordered_map<T, size_t> elem2pos_map;
	typedef std::unordered_map<size_t, T> pos2elem_map;
	
	elem2pos_map elem2pos_map_;
	pos2elem_map pos2elem_map_;
	size_t next_slot_;
};

int main() {
	rand_set<int> rset;
    for (size_t i = 0; i < 10000; i++)
        rset.add(i);

	int rand = rset.removeRandom();
    std::cout << rand << std::endl;
	return 0;
}

- Diego Giagio November 23, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I would use a Hashtable and also keep the hash keys in a separate array (upon add). That gives add and remove in 0(1)

For random remove I would pick a random key(at random index) in the keys array(O(1)) and then can remove from the hashtable in O(1)

- Thibaut Colar December 04, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-2
of 2 vote

public class CustomSet <TVal>
        where TVal : IComparable<TVal>
    {
        // Use ConcurrentDictionary?
        private readonly HashSet<TVal> m_HashSet = new HashSet<TVal>(/*Pre-set size if known*/);

        public void Add(TVal item)
        {
            m_HashSet.Add(item);
        }

        public void Remove(TVal item)
        {
            m_HashSet.Remove(item);
        }

        public void RemoveRandom(TVal item)
        {
            //...
        }
    }

- lem November 21, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-2
of 2 vote

add - O(1)
search by index - O(1)
search by element - O(1)
remove - O(1)

I dont think we can get this with any data structure unless its size is fixed to 1 :)

- siva November 21, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

LOL

- Anonymous November 23, 2013 | Flag


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