Delete duplicate integer from an integer array - psuedo code - algorithm

I need some help in getting this right,
problem
Write a function which takes 2 arrays- One array is the source array and the other array is the array of indices and delete all those elements present at the indices of the source array taking the indices from the second array.
This is what I have come up with....
public static int[] DeleteArrayUsingIndices(int[] source, int[] indices)
{
for (int i = 0; i < indices.Length; i++)
{
if (indices[i] < source.Length)
{
source[indices[i]] = int.MinValue; // delete
}
}
return source;
}
I am not very sure with this solution, as this does not remove the value. Can anyone help me out with this.

You cannot really delete elements from an array, so you need to ask what is meant by this wording. If replacing the elements with an exceptional element (like int.MinValue in your code) is acceptable, your solution is fine.
Another interpretation could be to rearrange the array so the "not deleted" indexes are at the begining of the array in the same order they were in the original -- in this case you would want to return the new "length" of the array (the number of elements that were not "deleted") -- this means that a "delete" operation will compact the array of not-yet deleted elements to the begining of the array (shifting the contents of the array toward the beginning from the deleted index to the end of the array (or to the end of the non-deleted elements). Care must be taken not to "delete" the same element twice.
To achieve the latter, you will have to either keep track of which position was moved by how many elements. Alternatively, update the index array to decrement indices larger than the current one (to accomodate the now compacted array) -- in this case you coul start by sorting the index array (possibly removing duplicates at the same time) and just keep track of how many positions have been shifted so far

try this
public static void main(String[] args) {
Integer[] a = {1,2,3,4,5,6,7,8,9};
Integer[] b = {2,3};
System.out.println(Arrays.asList(deleteArrayUsingIndices(a, b)));
}
^ for testing
public static Integer[] deleteArrayUsingIndices(Integer[] source, Integer[] indices)
{
ArrayList<Integer> sourceArr = new ArrayList<Integer>(Arrays.asList(source));
ArrayList<Integer> toDelete = new ArrayList<Integer>();
for (int i:indices)
{
try {
toDelete.add(sourceArr.get(i));
} catch (Exception e) {}
}
sourceArr.removeAll(toDelete);
return sourceArr.toArray(new Integer[sourceArr.size()]);
}

Related

Remove duplicates in O(n) by hand

I need to remove all duplicates in a list, but only if the item in list a is the same in list b aswell. This is my current code, but at 100k items it's taking literal days, is there a fast way to do this?
Any help appreciated.
List<int> ind = new List<int>();
List<int> used = new List<int>();
for (int i = 0; i < a.Count; i++)
{
for (int j = 0; j < a.Count; j++)
{
if (i != j&&!used.Contains(i))
{
if (a[j] == a[i] && b[i] == b[j])
{
ind.Add(j);
used.Add(j);
}
}
}
}
List<string> s2 = new List<string>();
List<string> a2 = new List<string>();
for (int i = 0; i < a.Count; i++)
{
if (!ind.Contains(i))
{
s2.Add(a[i]);
a2.Add(b[i]);
}
}
The key to many such problems is the correct data structure. To avoid duplicates, you need to use Sets, as they remove duplicates automatically.
Here is the code in Java, I hope it is similar in C#:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
class Duplicates
{
static List<Integer> list1 = new ArrayList<>();
static List<Integer> list2 = new ArrayList<>();
static final int SIZE = 100_000;
static final int MAX_VALUE = 1000_000;
public static void main(String[] args)
{
// populate the lists with random values for testing
Random r = new Random();
for(int i=0; i<SIZE; i++)
{
list1.add(r.nextInt(MAX_VALUE));
list2.add(r.nextInt(MAX_VALUE));
}
Set<Integer> set1 = new HashSet<>(list1);
Set<Integer> set2 = new HashSet<>(list2);
// items that are in both lists
Set<Integer> intersection = new HashSet<>(set1);
intersection.retainAll(set2);
Set<Integer> notSeenYet = new HashSet<>(intersection);
List<Integer> list1Unique = new ArrayList<Integer>();
for(int n: list1)
{
if(intersection.contains(n)) // we may have to skip this one
{
if(notSeenYet.contains(n)) // no, don't skip, it's the first occurrence
{
notSeenYet.remove(n);
}
else
{
continue;
}
}
list1Unique.add(n);
}
System.out.println("list 1 contains "+list1Unique.size()+" values after removing all duplicates that are also in list 2");
}
}
It takes less than a second for 100k values.
Output
list 1 contains 99591 values after removing all duplicates that are
also in list 2
Create a HashSet.
First, iterate through the list b and add all elements into the HashSet.
Then, iterate through each element of the list a. When you visit an element, ask the HashSet if it already contains that element. If if doesn't, it's a new element, so just keep it. If it does, it is a duplicate and you can remove it from a.
HashSets can perform the Do you have this element? question in O(1), so for the whole list, you have O(n).
For more information, check the documentation.
Here is a general algorithm to consider. We can start by sorting both lists in ascending order. Using a good sorting algorithm such as merge sort, this would take O(NlgN) time, where N is the length of the list. Once we have paid this penalty, we need only maintain two pointers in each of the lists. The general algorithm would basically involve walking up both lists, searching for duplicates in the first a list, should the value in question match the pointer into the b list. If there be a match, then duplicates would be removed from the a list, otherwise we keep walking until reaching the end of the a list. This process would be only O(N), making the biggest penalty the initial sort, which is O(NlgN).
To "remove duplicates" I understand to mean "from n identical items, leave the first and remove the remaining n - 1". If so then this is the algorithm:
Convert list b to set B. Also introduce set A_dup. Run through list a and for each item:
if item is found in A_dup then remove it from a,
else if item is found in set B then add it to A_dup.
Repeat.
Checking for existence in sets (both A_dup and B) is O(1) operation, also to add new item in the set. So, you're left with iterating through list a, which in total gives us O(n).
I think what you are trying to do is find distinct pairs, right?
If so, you can do that in one line using Zip and Distinct and a C# Tuple (or use an anonymous type).
var result = a.Zip(b, (x,y) => (x, y)).Distinct();
import java.util.*;
import java.util.stream.Collectors;
public class Test {
public static void main(String args[]) {
List<String> dupliKhaneList = new ArrayList<>();
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Khan");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Khan");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Zidan");
// Solution 1 if want to remove in list
List<String> uniqueList = dupliKhaneList.stream().distinct().collect(Collectors.toList());
System.out.println("DupliKhane => " + dupliKhaneList);
System.out.println("Unique 1 => " + uniqueList);
// Solution 2 if want to remove using 2 list
List<String> list1 = new ArrayList<>();
list1.add("Vaquar");
list1.add("Khan");
list1.add("Vaquar");
list1.add("Vaquar");
list1.add("Khan");
list1.add("Vaquar");
list1.add("Zidan");
List<String> list2 = new ArrayList<>();
list2.add("Zidan");
System.out.println("list1 => " + list1);
System.out.println("list2 => " + list2);
list1.removeAll(list2);
System.out.println("removeAll duplicate => " + list1);
}
}
Results :
DupliKhane => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar, Zidan]
Unique 1 => [Vaquar, Khan, Zidan]
list1 => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar, Zidan]
list2 => [Zidan]
removeAll duplicate => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar]

Find the minimum length snippet from the paragraph that contains all the words belonging to a given query in O(n) time

Given a review paragraph and keywords, find minimum length snippet from paragraph which contains all keywords in any order.If there are millions of review, what preprocessing step would you do.
The first part is simple, just the minimum window problem. Now, for preprocessing, I use inverted index. So, for each review I build a table storing the list of occurance of each word. Now, when a query comes, I retrieve the list of indices for each word. Now, is there some way to find out the min window length from this set of list in O(n) time? I tried building min and max heap to store the current index of each list and then keeping a track of the min window length(using the root of both the heaps). Then I perform extractMin operation and remove the same element from the max heap as well. To keep address of the location of each element in the max heap(for removal), I maintain a hash table. Now from the list, to which the extracted element belonged, I insert the next element into both the heaps and change the window length, if needed. This takes O(nlog n) time. Is it possible to do this in O(n) time?
Assuming this combination is sorted here is how I would do it:
Create a list of objects that describe the word and its index, Something like Obj(String name,Int index).
Init a set containing all keywords of the query.
Init the lower bound of the window as the index of the first element in the list.
Go through the list updating the upper bound of the window as the current object's index, updating the lower bound of the window as the index of the first occurrence of any of the words in your query (i.e. once min_window is set to the index of an actual word occurrence it is no longer updated) and by removing the corresponding word from the set of keywords.
When the set is empty, save the resulting lower and upper bound along with the length of the snippet.
Repeat the steps 2 to 5 but this time the list you're going to use is the list that starts at the element that comes right after the one defined by the previous min_window and by only keeping the min_window and max_window if the length of the snippet is shorter than the previous one (this should be repeated until you can no longer find all occurrences in the given sublist).
#include<bits/stdc++.h>
using namespace std;
map<string,int>word;
void functionlower(string& str){
transform(str.begin(),str.end(),str.begin(),::tolower);
}
string compareWord(string& str){
string temp;
temp.resize(str.size());
transform(str.begin(),str.end(),temp.begin(),::tolower);
return temp;
}
int main(){
int total_word;
cin>>total_word;
for(int i=0;i<total_word;i++){
string str;
cin>>str;
functionlower(str);
word.insert({str,0});
}
cin.ignore();
string str;
vector<string>para;
getline(cin,str);
int index=0;
for(int i=0;i<=str.size();i++){
if(i==str.size()||str[i]==' '){para.push_back(str.substr(index,i-index)); index=i+1;}
}
int currlen=0;
int currpos=0;
int lenprint=0;
int olen=-1;
int opos=-1;
for(int i=0;i<para.size();i++){
string search=compareWord(para[i]);
if(word.find(search)!=word.end()){
if(word[search]==0)currlen++;
word[search]++;
}
while(currlen>=word.size()){
search=compareWord(para[currpos]);
if((i-currpos)<olen||olen==-1){
olen=i-currpos;
opos=currpos;
}
if(word.find(search)!=word.end()){
if(word[search]==1)break;
word[search]--;
currpos++;
lenprint=i;
}else currpos++;
}
}
for(int i=0;i<=olen;i++){
cout<<para[opos+i]<<" ";
}
cout<<endl;
return 0;
}
O(nlogk) where k is number of words need to search
Assuming a constant wordLength, this solution can be achieved in O(n) time complexity, where n is number of words in para; here is the code for implementation in java:
package Basic.MinSnippetWithAllKeywords;
import java.util.*;
/**
* Given a review paragraph and keywords,
* find minimum length snippet from paragraph which contains all keywords in any order.
*/
public class Solution {
public String minSnippet(String para, Set<String> keywords) {
LinkedList<Integer> deque = new LinkedList<>();
String[] words = para.split("\\s");
for (int i = 0; i < words.length; ++i) {
if(keywords.contains(words[i]))
deque.offer(i);
}
while(deque.size() > 1) {
int first = deque.pollFirst();
int second = deque.peekFirst();
if (words[first] != words[second]) {
deque.offerFirst(first);
break;
}
}
while(deque.size() > 1) {
int first = deque.pollLast();
int second = deque.peekLast();
if(words[first] != words[second]) {
deque.offerLast(first);
break;
}
}
if (deque.isEmpty())
return "";
return String.join(" ",
Arrays.copyOfRange(words, deque.peekFirst(), deque.peekLast() + 1));
}
/*
Example:
my name is shubham mishra
is name
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String para = sc.nextLine();
String keyLine = sc.nextLine();
Set<String> keywords = new HashSet<>();
keywords.addAll(Arrays.asList(keyLine.split("\\s")));
System.out.println(new Solution().minSnippet(para, keywords));
}
}

Ordered insertion working sporadically with primitive types & strings

For an assignment, we've been asked to implement both ordered and unordered versions of LinkedLists as Bags in Java. The ordered versions will simply extend the unordered implmentations while overriding the insertion methods.
The ordering on insertion function works... somewhat. Given a test array of
String[] testArray= {"z","g","x","v","y","t","s","r","w","q"};
the output is
q w r s t y v x g z
when it should be
g q r s t v w x y z
However, the ordering works fine when the elements aren't mixed up in value. For example, I originally used the testArray[] above with the alphabe reversed, and the ordering was exactly as it should be.
My add function is
#Override
public void add(E e){
Iter iter= new Iter(head.prev);
int compValue;
E currentItem= null;
//empty list, add at first position
if (size < 1)
iter.add(e);
else {
while (iter.hasNext()){
currentItem= iter.next(); //gets next item
//saves on multiple compareTo calls
compValue= e.compareTo(currentItem);
//adds at given location
if (compValue <= 0)
iter.add(e, iter.index);
else //moves on
currentItem= iter.next();
}
}
}
The iterator functionality is implemented as
//decided to use iterator to simplify method functionality
protected class Iter implements Iterator<E>, ListIterator<E>{
protected int index= 0;
protected Node current= null;
//Sets a new iterator to the index point provided
public Iter(int index){
current= head.next;
this.index=0;
while (index > nextIndex()) //moves on to the index point
next();
}
public void add(E e, int index){
size++;
Iter iterator= new Iter(index);
Node node= new Node();
Node current= iterator.current.prev;
node.next= current.next;
node.prev= current;
node.next.prev= node;
node.prev.next= node;
node.item= e;
}
As it is right now, the only things being used are primitive types. I know for objects, a specific comparable class will have to be written, but in this case, String contains a compareTo() method that should give correct ordering.
By chance, a classmate of mine has a similar implementation and is returning the same results.
Using natural ordering, how can I resolve this problem?
Three things about your add() function jump out at me:
It should exit the loop as soon as it inserts the new value; this might not actually be a problem, but it is inefficient to keep looking
You call next_item at the top of the loop, but call it AGAIN if the value isn't added
If your list has just 1 value in it, and you try to add a value larger than the one currently in the list, won't the new value fail to be added?

Data structure: insert, remove, contains, get random element, all at O(1)

I was given this problem in an interview. How would you have answered?
Design a data structure that offers the following operations in O(1) time:
insert
remove
contains
get random element
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.
insert(value): append the value to array and let i be its index in A. Set H[value]=i.
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.
contains(value): return H.contains(value)
getRandomElement(): let r=random(current size of A). return A[r].
since the array needs to auto-increase in size, it's going to be amortize O(1) to add an element, but I guess that's OK.
O(1) lookup hints at a hashed data structure.
By comparison:
O(1) insert/delete with O(N) lookup implies a linked list.
O(1) insert, O(N) delete, and O(N) lookup implies an array-backed list
O(logN) insert/delete/lookup implies a tree or heap.
For this Question i will use two Data Structure
HashMap
ArrayList / Array / Double LinkedList.
Steps :-
Insertion :- Check if X is already present in HashMap --Time complexity O(1) . if not Present Then Add in end of ArrayList -- Time complexity O(1).
add it in HashMap also x as key and last Index as a value -- Time complexity O(1).
Remove :- Check if X is present in HashMap --Time complexity O(1). If present then find the its index and remove it from HashMap --Time complexity O(1). swap this element with last element in ArrayList and remove the last element --Time complexity O(1). Update the index of last Element in HashMap --Time complexity O(1).
GetRandom :- Generate Random number from 0 to last index of ArrayList . return the ArrayList element at random index generated --Time complexity O(1).
Search :- See in HashMap for x as a key. --Time complexity O(1).
Code :-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class JavaApplication1 {
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
ArrayList<Integer> al =new ArrayList<Integer>();
HashMap<Integer,Integer> mp = new HashMap<Integer,Integer>();
while(true){
System.out.println("**menu**");
System.out.println("1.insert");
System.out.println("2.remove");
System.out.println("3.search");
System.out.println("4.rendom");
int ch = sc.nextInt();
switch(ch){
case 1 : System.out.println("Enter the Element ");
int a = sc.nextInt();
if(mp.containsKey(a)){
System.out.println("Element is already present ");
}
else{
al.add(a);
mp.put(a, al.size()-1);
}
break;
case 2 : System.out.println("Enter the Element Which u want to remove");
a = sc.nextInt();
if(mp.containsKey(a)){
int size = al.size();
int index = mp.get(a);
int last = al.get(size-1);
Collections.swap(al, index, size-1);
al.remove(size-1);
mp.put(last, index);
System.out.println("Data Deleted");
}
else{
System.out.println("Data Not found");
}
break;
case 3 : System.out.println("Enter the Element to Search");
a = sc.nextInt();
if(mp.containsKey(a)){
System.out.println(mp.get(a));
}
else{
System.out.println("Data Not Found");
}
break;
case 4 : Random rm = new Random();
int index = rm.nextInt(al.size());
System.out.println(al.get(index));
break;
}
}
}
}
-- Time complexity O(1).
-- Space complexity O(N).
You might not like this, because they're probably looking for a clever solution, but sometimes it pays to stick to your guns... A hash table already satisfies the requirements - probably better overall than anything else will (albeit obviously in amortised constant time, and with different compromises to other solutions).
The requirement that's tricky is the "random element" selection: in a hash table, you would need to scan or probe for such an element.
For closed hashing / open addressing, the chance of any given bucket being occupied is size() / capacity(), but crucially this is typically kept in a constant multiplicative range by a hash-table implementation (e.g. the table may be kept larger than its current contents by say 1.2x to ~10x depending on performance/memory tuning). This means on average we can expect to search 1.2 to 10 buckets - totally independent of the total size of the container; amortised O(1).
I can imagine two simple approaches (and a great many more fiddly ones):
search linearly from a random bucket
consider empty/value-holding buckets ala "--AC-----B--D": you can say that the first "random" selection is fair even though it favours B, because B had no more probability of being favoured than the other elements, but if you're doing repeated "random" selections using the same values then clearly having B repeatedly favoured may be undesirable (nothing in the question demands even probabilities though)
try random buckets repeatedly until you find a populated one
"only" capacity() / size() average buckets visited (as above) - but in practical terms more expensive because random number generation is relatively expensive, and infinitely bad if infinitely improbable worst-case behaviour...
a faster compromise would be to use a list of pre-generated random offsets from the initial randomly selected bucket, %-ing them into the bucket count
Not a great solution, but may still be a better overall compromise than the memory and performance overheads of maintaining a second index array at all times.
The best solution is probably the hash table + array, it's real fast and deterministic.
But the lowest rated answer (just use a hash table!) is actually great too!
hash table with re-hashing, or new bucket selection (i.e. one element per bucket, no linked lists)
getRandom() repeatedly tries to pick a random bucket until it's empty.
as a fail-safe, maybe getRandom(), after N (number of elements) unsuccessful tries, picks a random index i in [0, N-1] and then goes through the hash table linearly and picks the #i-th element.
People might not like this because of "possible infinite loops", and I've seen very smart people have this reaction too, but it's wrong! Infinitely unlikely events just don't happen.
Assuming the good behavior of your pseudo-random source -- which is not hard to establish for this particular behavior -- and that hash tables are always at least 20% full, it's easy to see that:
It will never happen that getRandom() has to try more than 1000 times. Just never. Indeed, the probability of such an event is 0.8^1000, which is 10^-97 -- so we'd have to repeat it 10^88 times to have one chance in a billion of it ever happening once. Even if this program was running full-time on all computers of humankind until the Sun dies, this will never happen.
Here is a C# solution to that problem I came up with a little while back when asked the same question. It implements Add, Remove, Contains, and Random along with other standard .NET interfaces. Not that you would ever need to implement it in such detail during an interview but it's nice to have a concrete solution to look at...
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
/// <summary>
/// This class represents an unordered bag of items with the
/// the capability to get a random item. All operations are O(1).
/// </summary>
/// <typeparam name="T">The type of the item.</typeparam>
public class Bag<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
{
private Dictionary<T, int> index;
private List<T> items;
private Random rand;
private object syncRoot;
/// <summary>
/// Initializes a new instance of the <see cref="Bag<T>"/> class.
/// </summary>
public Bag()
: this(0)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Bag<T>"/> class.
/// </summary>
/// <param name="capacity">The capacity.</param>
public Bag(int capacity)
{
this.index = new Dictionary<T, int>(capacity);
this.items = new List<T>(capacity);
}
/// <summary>
/// Initializes a new instance of the <see cref="Bag<T>"/> class.
/// </summary>
/// <param name="collection">The collection.</param>
public Bag(IEnumerable<T> collection)
{
this.items = new List<T>(collection);
this.index = this.items
.Select((value, index) => new { value, index })
.ToDictionary(pair => pair.value, pair => pair.index);
}
/// <summary>
/// Get random item from bag.
/// </summary>
/// <returns>Random item from bag.</returns>
/// <exception cref="System.InvalidOperationException">
/// The bag is empty.
/// </exception>
public T Random()
{
if (this.items.Count == 0)
{
throw new InvalidOperationException();
}
if (this.rand == null)
{
this.rand = new Random();
}
int randomIndex = this.rand.Next(0, this.items.Count);
return this.items[randomIndex];
}
/// <summary>
/// Adds the specified item.
/// </summary>
/// <param name="item">The item.</param>
public void Add(T item)
{
this.index.Add(item, this.items.Count);
this.items.Add(item);
}
/// <summary>
/// Removes the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns></returns>
public bool Remove(T item)
{
// Replace index of value to remove with last item in values list
int keyIndex = this.index[item];
T lastItem = this.items[this.items.Count - 1];
this.items[keyIndex] = lastItem;
// Update index in dictionary for last item that was just moved
this.index[lastItem] = keyIndex;
// Remove old value
this.index.Remove(item);
this.items.RemoveAt(this.items.Count - 1);
return true;
}
/// <inheritdoc />
public bool Contains(T item)
{
return this.index.ContainsKey(item);
}
/// <inheritdoc />
public void Clear()
{
this.index.Clear();
this.items.Clear();
}
/// <inheritdoc />
public int Count
{
get { return this.items.Count; }
}
/// <inheritdoc />
public void CopyTo(T[] array, int arrayIndex)
{
this.items.CopyTo(array, arrayIndex);
}
/// <inheritdoc />
public bool IsReadOnly
{
get { return false; }
}
/// <inheritdoc />
public IEnumerator<T> GetEnumerator()
{
foreach (var value in this.items)
{
yield return value;
}
}
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
/// <inheritdoc />
public void CopyTo(Array array, int index)
{
this.CopyTo(array as T[], index);
}
/// <inheritdoc />
public bool IsSynchronized
{
get { return false; }
}
/// <inheritdoc />
public object SyncRoot
{
get
{
if (this.syncRoot == null)
{
Interlocked.CompareExchange<object>(
ref this.syncRoot,
new object(),
null);
}
return this.syncRoot;
}
}
}
We can use hashing to support operations in Θ(1) time.
insert(x)
1) Check if x is already present by doing a hash map lookup.
2) If not present, then insert it at the end of the array.
3) Add in hash table also, x is added as key and last array index as index.
remove(x)
1) Check if x is present by doing a hash map lookup.
2) If present, then find its index and remove it from hash map.
3) Swap the last element with this element in array and remove the last element.
Swapping is done because the last element can be removed in O(1) time.
4) Update index of last element in hash map.
getRandom()
1) Generate a random number from 0 to last index.
2) Return the array element at the randomly generated index.
search(x)
Do a lookup for x in hash map.
Though this is way old, but since there's no answer in C++, here's my two cents.
#include <vector>
#include <unordered_map>
#include <stdlib.h>
template <typename T> class bucket{
int size;
std::vector<T> v;
std::unordered_map<T, int> m;
public:
bucket(){
size = 0;
std::vector<T>* v = new std::vector<T>();
std::unordered_map<T, int>* m = new std::unordered_map<T, int>();
}
void insert(const T& item){
//prevent insertion of duplicates
if(m.find(item) != m.end()){
exit(-1);
}
v.push_back(item);
m.emplace(item, size);
size++;
}
void remove(const T& item){
//exits if the item is not present in the list
if(m[item] == -1){
exit(-1);
}else if(m.find(item) == m.end()){
exit(-1);
}
int idx = m[item];
m[v.back()] = idx;
T itm = v[idx];
v.insert(v.begin()+idx, v.back());
v.erase(v.begin()+idx+1);
v.insert(v.begin()+size, itm);
v.erase(v.begin()+size);
m[item] = -1;
v.pop_back();
size--;
}
T& getRandom(){
int idx = rand()%size;
return v[idx];
}
bool lookup(const T& item){
if(m.find(item) == m.end()) return false;
return true;
}
//method to check that remove has worked
void print(){
for(auto it = v.begin(); it != v.end(); it++){
std::cout<<*it<<" ";
}
}
};
Here's a piece of client code to test the solution.
int main() {
bucket<char>* b = new bucket<char>();
b->insert('d');
b->insert('k');
b->insert('l');
b->insert('h');
b->insert('j');
b->insert('z');
b->insert('p');
std::cout<<b->random()<<std::endl;
b->print();
std::cout<<std::endl;
b->remove('h');
b->print();
return 0;
}
In C# 3.0 + .NET Framework 4, a generic Dictionary<TKey,TValue> is even better than a Hashtable because you can use the System.Linq extension method ElementAt() to index into the underlying dynamic array where the KeyValuePair<TKey,TValue> elements are stored :
using System.Linq;
Random _generator = new Random((int)DateTime.Now.Ticks);
Dictionary<string,object> _elements = new Dictionary<string,object>();
....
Public object GetRandom()
{
return _elements.ElementAt(_generator.Next(_elements.Count)).Value;
}
However, as far as I know, a Hashtable (or its Dictionary progeny) is not a real solution to this problem because Put() can only be amortized O(1) , not true O(1) , because it is O(N) at the dynamic resize boundary.
Is there a real solution to this problem ? All I can think of is if you specify a Dictionary/Hashtable initial capacity an order of magnitude beyond what you anticipate ever needing, then you get O(1) operations because you never need to resize.
I agree with Anon. Except for the last requirement where getting a random element with equal fairness is required all other requirements can be addressed only using a single Hash based DS. I will choose HashSet for this in Java. The modulo of hash code of an element will give me the index no of the underlying array in O(1) time. I can use that for add, remove and contains operations.
Cant we do this using HashSet of Java? It provides insert, del, search all in O(1) by default.
For getRandom we can make use of iterator of Set which anyways gives random behavior. We can just iterate first element from set without worrying about rest of the elements
public void getRandom(){
Iterator<integer> sitr = s.iterator();
Integer x = sitr.next();
return x;
}
/* Java program to design a data structure that support folloiwng operations
in Theta(n) time
a) Insert
b) Delete
c) Search
d) getRandom */
import java.util.*;
// class to represent the required data structure
class MyDS
{
ArrayList<Integer> arr; // A resizable array
// A hash where keys are array elements and vlaues are
// indexes in arr[]
HashMap<Integer, Integer> hash;
// Constructor (creates arr[] and hash)
public MyDS()
{
arr = new ArrayList<Integer>();
hash = new HashMap<Integer, Integer>();
}
// A Theta(1) function to add an element to MyDS
// data structure
void add(int x)
{
// If ekement is already present, then noting to do
if (hash.get(x) != null)
return;
// Else put element at the end of arr[]
int s = arr.size();
arr.add(x);
// And put in hash also
hash.put(x, s);
}
// A Theta(1) function to remove an element from MyDS
// data structure
void remove(int x)
{
// Check if element is present
Integer index = hash.get(x);
if (index == null)
return;
// If present, then remove element from hash
hash.remove(x);
// Swap element with last element so that remove from
// arr[] can be done in O(1) time
int size = arr.size();
Integer last = arr.get(size-1);
Collections.swap(arr, index, size-1);
// Remove last element (This is O(1))
arr.remove(size-1);
// Update hash table for new index of last element
hash.put(last, index);
}
// Returns a random element from MyDS
int getRandom()
{
// Find a random index from 0 to size - 1
Random rand = new Random(); // Choose a different seed
int index = rand.nextInt(arr.size());
// Return element at randomly picked index
return arr.get(index);
}
// Returns index of element if element is present, otherwise null
Integer search(int x)
{
return hash.get(x);
}
}
// Driver class
class Main
{
public static void main (String[] args)
{
MyDS ds = new MyDS();
ds.add(10);
ds.add(20);
ds.add(30);
ds.add(40);
System.out.println(ds.search(30));
ds.remove(20);
ds.add(50);
System.out.println(ds.search(50));
System.out.println(ds.getRandom());`enter code here`
}
}
This solution properly handles duplicate values. You can:
Insert the same element multiple times
Remove a single instances of an element
To make this possible, we just need to keep a hash-set of indexes for each element.
class RandomCollection:
def __init__(self):
self.map = {}
self.list = []
def get_random_element(self):
return random.choice(self.list)
def insert(self, element):
index = len(self.list)
self.list.append(element)
if element not in self.map:
self.map[element] = set()
self.map[element].add(index)
def remove(self, element):
if element not in self.map:
raise Exception("Element not found", element)
# pop any index in constant time
index = self.map[element].pop()
# find last element
last_index = len(self.list) - 1
last_element = self.list[last_index]
# keep map updated, this also works when removing
# the last element because add() does nothing
self.map[last_element].add(index)
self.map[last_element].remove(last_index)
if len(self.map[element]) == 0:
del self.map[element]
# copy last element to index and delete last element
self.list[index] = self.list[last_index]
del self.list[last_index]
# Example usage:
c = RandomCollection()
times = 1_000_000
for i in range(times):
c.insert("a")
c.insert("b")
for i in range(times - 1):
c.remove("a")
for i in range(times):
c.remove("b")
print(c.list) # prints ['a']
Why don't we use epoch%arraysize to find random element. Finding array size is O(n) but amortized complexity will be O(1).
I think we can use doubly link list with hash table. key will be element and its associated value will be node in doubly linklist.
insert(H,E) : insert node in doubly linklist and make entry as H[E]=node; O(1)
delete(H,E) : get node address by H(E), goto previous of this node and delete and make H(E) as NULL, so O(1)
contains(H,E) and getRandom(H) are obviuosly O(1)

Does the singularly LinkedList give output In LIFO?

I was working on a singularly-linked list. While creating my own linked list I got confused on printing the collection of nodes in my custom linked list.
I want to know, does a singularly-linked list display its collection in a LIFO manner like a stack?
below is my Own LinkedList AND node is A Class can anyone tell me Does Singular LinkedList Prints The Collection In Lifo Manner.
class MYlinklist
{
Node header;
public void Add(int a)
{
Node n = new Node();
n.element = a;
n.Next = header;
header = n;
}
public void Print()
{
Node n = new Node();
n = header;
while (n != null)
{
Console.WriteLine(n.element.ToString());
n = n.Next;
}
}
}
If you are referring to LinkedList<T>, the answer depends on how you add new members.
If you want to make the linked list iterate in LIFO, you can do so by always using AddFirst to add, and RemoveFirst to remove. This will cause it behave very much like a stack.
The nice thing about LinkedList<T>, however, is that you can add anywhere inside of the list as an O(1) operation.
Edit:
If you want this to be FIFO instead, you'll need to change how to add your nodes, and add them at the end of the list, not the start:
class MyLinkedList
{
Node header;
Node last;
public void Add(int a)
{
Node n = new Node();
n.element = a;
n.Next = null; // We'll put this at the end...
if (last == null)
{
header = n;
last = n;
}
else
{
last.Next = n;
last = n;
}
}
public void Print()
{
Node n = new Node();
n = header;
while (n != null)
{
Console.WriteLine(n.element.ToString());
n = n.Next;
}
}
}
You're adding nodes at the head of the list (note how you are always setting node.Next to the head of the list).
Then you're iterating through from the head (which is the last element inserted) to the tail.
If you want to iterate in FIFO order, you should do the following:
Maintain a reference to the tail of the list (as well as the head, which you've put in header).
When you add a node, set tail.Next to the new node, and then set tail to point to the new node.
Your iteration function can be unchanged.
Your other option is, instead of maintaining a reference to the tail, just do an iteration through the list each time. But this comes with the tradeoff of needing to go through n-1 elements to add the nth element every time, which means adding many elements is an O(n^2) operation. I would not recommend doing this, but it might be fine for a beginning if you're learning the basics and you're not sure about the tail reference manipulation. In production code, though, you should always have a head and a tail reference for linked lists.

Resources