We have an array A of integers of size N. Given another array B which contains indices, where size of B <= N and 0<=B[i]<=N-1.
Now we have to remove all elements from array A at position B[i].
So with deletion we mean we are also shifting elements in array A.
Can someone help me in reaching to O(n) solution for this problem? And possibly O(1) space.
The first solution that comes to my mind is, traversing the array B and deleting elements in A sequentially( including shifting) but it is O(n^2).
Similar to iliaden's solution except you could do the removing of deleted elements in place.
int[] a =
int[] b =
int nullValue =
for(int i: b) a[i] = nullValue;
int j=0;
for(int i=0; i < a.length; i++) {
if(a[i] != nullValue)
a[j++] = a[i];
}
// to clear the rest of the array, if required.
for(;j<a.length;j++)
a[j] = nullValue;
note: a won't be shorter, but it avoid creating any more space. 'j' will have the number of valid entries in a
in O(n) space, you can do:
traverse array A deleting every
element at b[i] (no shifting, O(n))
create a new array C, copy all the non-empty elements
from A into C sequentially (also O(n))
return array C or copy it back
onto a cleared array A (O(n)) .
thus you get to do it in O(n) tim
and O(n) space
No marking, O(n) time, but also O(n) space, in pseudo-code:
// create a boolean array indicating which elements are to be deleted
D = new boolean[N]
fill(D, false)
for (b in B) {
D[b] = true
}
// compact `A in place
src = 0
dest = 0
while (src < N) {
if (!D[src]) {
A[dest++] = A[src]
}
src++
}
new_N = dest
if you can assume b is sorted you can shift as you iterate (you can sort the b in O(n*log(n)) if not)
int[] b;
int[] a;
int first=0,bInd=0;
for(int i = 0;i<a.length;i++){
if(bInd>=b.length || b[bInd]!=i){
a[first]=a[i];
first++;
}else{
bInd++;
}
}
Two obvious solutions: sort B in reverse order before starting, so you
always delete the highest index (and so never shift a deleted element),
or iterate through B to create a bitmap of elements to delete (and
then do those in the reverse order). The first requires an additional
O(lg n) step beforehand, and the second additional space. But I'm not
sure there are any better alternatives.
Related
I have a question that doesn't seem possible to me. I have 2+ arrays which I have to compare for common values. I am supposed to do this in O(N) comparisons but can't think of a way. Specifically (k-1)N comparisons where k is the number of arrays. I've narrowed down how I can take multiple arrays and just merge them into a single array. I've gotten that the smallest array is the limiting factor so if I sort that I can save the most comparisons. After spending half the day staring at my screen I've even come up with a way to do this linearly if I discount any duplicates, but I have to keep duplicates So, as far as I know in order to compare any arrays you need at least 2 for loops which would be O(N^2) wouldn't it? I'm also not allowed to hash anything.
For example if I had {1,3,4,3,4,5} as a master and {1,1,3,5,9,3,7} and {3,5,8,4,0,3,2} as arrays to be compared I'd need to have a final of {3,3,5} since I can't get rid of any dupiclates.
I don't want anyone to write the code, I just need to know what I should be doing in the first place.
Use an array of ints. Taking your first list, for each element, set the value at that index to 1. So if the first element is 3, put 1 in array[3]. Now, we know that 3 is present in first list. Putting 1 will help you distinguish from a 3 that is present in the earlier list versus a 3 which is repeated in current list.
Iterate through all the other k-1 lists
For every element, check the value in array for that index
If the value is 0, set it to this list number
If the value is a number less than this list number, this number is a duplicate and has already appeared in a previous list.
If this number is equal to this list index it means this number already occurred in this list but not in previous lists, so not yet a duplicate.
The numbers that you are getting as duplicates, add them to another list.
Finish all iterations
Finally print the duplicates.
Original Wrong Answer
Create a HashSet<int>
Take all values from master and add to it - O(master list count)
Now just iterate through first and second arrays and see if their elements are in that HashSet - O(each list count)
If the lists are sorted, then it's relatively straightforward if you do something like this:
List<Integer> intersection = new ArrayList<>();
int i = 0;
int j = 0;
while (i < list1.size() && j < list2.size()) {
int a = list1.get(i);
int b = list2.get(j);
if (a < b) {
i++;
} else if (b < a) {
j++;
} else { // a == b
intersection.add(a);
i++;
j++;
}
}
On each iteration of the loop, the quantity i + j increases by at least 1, and the loop is guaranteed to be done when i + j >= list1.size() + list2.size(), so the whole thing does at most O(list1.size() + list2.size()) comparisons.
This question already has answers here:
How to find the kth largest element in an unsorted array of length n in O(n)?
(32 answers)
Closed 7 years ago.
I had an interview with Facebook and they asked me this question.
Suppose you have an unordered array with N distinct values
$input = [3,6,2,8,9,4,5]
Implement a function that finds the Kth largest value.
EG: If K = 0, return 9. If K = 1, return 8.
What I did was this method.
private static int getMax(Integer[] input, int k)
{
List<Integer> list = Arrays.asList(input);
Set<Integer> set = new TreeSet<Integer>(list);
list = new ArrayList<Integer>(set);
int value = (list.size() - 1) - k;
return list.get(value);
}
I just tested and the method works fine based on the question. However, interviewee said, in order to make your life complex! lets assume that your array contains millions of numbers then your listing becomes too slow. What you do in this case?
As hint, he suggested to use min heap. Based on my knowledge each child value of heap should not be more than root value. So, in this case if we assume that 3 is root then 6 is its child and its value is grater than root's value. I'm probably wrong but what you think and what is its implementation based on min heap?
He has actually given you the whole answer. Not just a hint.
And your understanding is based on max heap. Not min heap. And it's workings are self-explanatory.
In a min heap, the root has the minimum (less than it's children) value.
So, what you need is, iterate over the array and populate K elements in min heap.
Once, it's done, the heap automatically contains the lowest at the root.
Now, for each (next) element you read from the array,
-> check if the value is greater than root of min heap.
-> If yes, remove root from min heap, and add the value to it.
After you traverse your whole array, the root of min heap will automtically contain the kth largest element.
And all other elements (k-1 elements to be precise) in the heap will be larger than k.
Here is the implementation of the Min Heap using PriorityQueue in java. Complexity: n * log k.
import java.util.PriorityQueue;
public class LargestK {
private static Integer largestK(Integer array[], int k) {
PriorityQueue<Integer> queue = new PriorityQueue<Integer>(k+1);
int i = 0;
while (i<=k) {
queue.add(array[i]);
i++;
}
for (; i<array.length; i++) {
Integer value = queue.peek();
if (array[i] > value) {
queue.poll();
queue.add(array[i]);
}
}
return queue.peek();
}
public static void main(String[] args) {
Integer array[] = new Integer[] {3,6,2,8,9,4,5};
System.out.println(largestK(array, 3));
}
}
Output: 5
The code loop over the array which is O(n). Size of the PriorityQueue (Min Heap) is k, so any operation would be log k. In the worst case scenario, in which all the number are sorted ASC, complexity is n*log k, because for each element you need to remove top of the heap and insert new element.
Edit: Check this answer for O(n) solution.
You can probably make use of PriorityQueue as well to solve this problem:
public int findKthLargest(int[] nums, int k) {
int p = 0;
int numElements = nums.length;
// create priority queue where all the elements of nums will be stored
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
// place all the elements of the array to this priority queue
for (int n : nums){
pq.add(n);
}
// extract the kth largest element
while (numElements-k+1 > 0){
p = pq.poll();
k++;
}
return p;
}
From the Java doc:
Implementation note: this implementation provides O(log(n)) time for
the enqueing and dequeing methods (offer, poll, remove() and
add); linear time for the remove(Object) and contains(Object)
methods; and constant time for the retrieval methods (peek,
element, and size).
The for loop runs n times and the complexity of the above algorithm is O(nlogn).
Heap based solution is perfect if the number of elements in array/stream is unknown. But, what if they are finite but still you want an optimized solution in linear time.
We can use Quick Select, discussed here.
Array = [3,6,2,8,9,4,5]
Let's chose the pivot as first element:
pivot = 3 (at 0th index),
Now partition the array in such a way that all elements less than or equal are on left side and numbers greater than 3 on right side. Like it's done in Quick Sort (discussed on my blog).
So after first pass - [2,3,6,8,9,4,5]
pivot index is 1 (i.e it's the second lowest element). Now apply the same process again.
chose, 6 now, the value at index after previous pivot - [2,3,4,5,6,8,9]
So now 6 is at the proper place.
Keep checking if you have found the appropriate number (kth largest or kth lowest in each iteration). If it's found you are done else continue.
One approach for constant values of k is to use a partial insertion sort.
(This assumes distinct values, but can easily be altered to work with duplicates as well)
last_min = -inf
output = []
for i in (0..k)
min = +inf
for value in input_array
if value < min and value > last_min
min = value
output[i] = min
print output[k-1]
(That's pseudo code, but should be easy enough to implement in Java).
The overall complexity is O(n*k), which means it works pretty well if and only if k is constant or known to be less that log(n).
On the plus side, it is a really simple solution. On the minus side, it is not as efficient as the heap solution
I need to write a method public int subList (CharList list)
that gets a list and returns how many times this list exist.
For example:
my list is a b c d a b g e
parameter list ita b it will return 2.
my list is b b b b
parameter list is b b it will return 3.
The method should be as efficient as possible.
Currently my problem is I don't know what do they mean when they say as efficient as possible, If I loop through the list n times, and everytime I find the same character I loop on both list and go back to where I was it will be O(n^2)? is there a better way to make is O(n) or below?
This is in effective searching string in a string, which is O(n) complexity
http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
and as you find first occurrence you can just keep looking for next occurrence in remaining list so it's still O(n) to find all occurrence
Why O(n^2)? It is O(n) because the you need to iterate only once through the list.
Lets do this with a char[] to simplify the explanation.
The simple approach is as follows:
public int countSublists (char[] list, char[] sublist)
int count = 0;
for (i = 0; i < list.length; i++) {
for (j = 0; j <= sublist.length; j++) {
if (j = sublist.length) {
count++;
} else if (i + j > list.length || list[i + j] != sublist[j]) {
break;
}
}
}
return count;
}
This has worst-case complexity of O(N*M) where N is the length of list and M is the length of sublist. And best-case complexity of O(N) ... when there are no instances of the first character of sublist in list.
There are various other algorithms that give better performance ... down to (I think) O(N/M) best-case. The general idea is that you use the value of the character at list[i + j] when there is a mismatch to allow you to skip some characters.
You can find details of various advanced search algorithms are linked from the Wikipedia page on String Searching algorithms ... which also includes a summary of the respective algorithm complexity.
But the thing to note is that the advanced search algorithms all involve some precompution steps, whose complexity is some function of M. If N is small enough, the cost of the precomputation may outweigh the saving at search time. (On the other hand, if you are repeatedly counting the same sublist in different lists, and you can reuse the precomputed tables, then you can amortize the precomputation cost ...)
I have an int[] array of length N containing the values 0, 1, 2, .... (N-1), i.e. it represents a permutation of integer indexes.
What's the most efficient way to determine if the permutation has odd or even parity?
(I'm particularly keen to avoid allocating objects for temporary working space if possible....)
I think you can do this in O(n) time and O(n) space by simply computing the cycle decomposition.
You can compute the cycle decomposition in O(n) by simply starting with the first element and following the path until you return to the start. This gives you the first cycle. Mark each node as visited as you follow the path.
Then repeat for the next unvisited node until all nodes are marked as visited.
The parity of a cycle of length k is (k-1)%2, so you can simply add up the parities of all the cycles you have discovered to find the parity of the overall permutation.
Saving space
One way of marking the nodes as visited would be to add N to each value in the array when it is visited. You would then be able to do a final tidying O(n) pass to turn all the numbers back to the original values.
I selected the answer by Peter de Rivaz as the correct answer as this was the algorithmic approach I ended up using.
However I used a couple of extra optimisations so I thought I would share them:
Examine the size of data first
If it is greater than 64, use a java.util.BitSet to store the visited elements
If it is less than or equal to 64, use a long with bitwise operations to store the visited elements. This makes it O(1) space for many applications that only use small permutations.
Actually return the swap count rather than the parity. This gives you the parity if you need it, but is potentially useful for other purposes, and is no more expensive to compute.
Code below:
public int swapCount() {
if (length()<=64) {
return swapCountSmall();
} else {
return swapCountLong();
}
}
private int swapCountLong() {
int n=length();
int swaps=0;
BitSet seen=new BitSet(n);
for (int i=0; i<n; i++) {
if (seen.get(i)) continue;
seen.set(i);
for(int j=data[i]; !seen.get(j); j=data[j]) {
seen.set(j);
swaps++;
}
}
return swaps;
}
private int swapCountSmall() {
int n=length();
int swaps=0;
long seen=0;
for (int i=0; i<n; i++) {
long mask=(1L<<i);
if ((seen&mask)!=0) continue;
seen|=mask;
for(int j=data[i]; (seen&(1L<<j))==0; j=data[j]) {
seen|=(1L<<j);
swaps++;
}
}
return swaps;
}
You want the parity of the number of inversions. You can do this in O(n * log n) time using merge sort, but either you lose the initial array, or you need extra memory on the order of O(n).
A simple algorithm that uses O(n) extra space and is O(n * log n):
inv = 0
mergesort A into a copy B
for i from 1 to length(A):
binary search for position j of A[i] in B
remove B[j] from B
inv = inv + (j - 1)
That said, I don't think it's possible to do it in sublinear memory. See also:
https://cs.stackexchange.com/questions/3200/counting-inversion-pairs
https://mathoverflow.net/questions/72669/finding-the-parity-of-a-permutation-in-little-space
Consider this approach...
From the permutation, get the inverse permutation, by swapping the rows and
sorting according to the top row order. This is O(nlogn)
Then, simulate performing the inverse permutation and count the swaps, for O(n). This should give the parity of the permutation, according to this
An even permutation can be obtained as the composition of an even
number and only an even number of exchanges (called transpositions) of
two elements, while an odd permutation be obtained by (only) an odd
number of transpositions.
from Wikipedia.
Here's some code I had lying around, which performs an inverse permutation, I just modified it a bit to count swaps, you can just remove all mention of a, p contains the inverse permutation.
size_t
permute_inverse (std::vector<int> &a, std::vector<size_t> &p) {
size_t cnt = 0
for (size_t i = 0; i < a.size(); ++i) {
while (i != p[i]) {
++cnt;
std::swap (a[i], a[p[i]]);
std::swap (p[i], p[p[i]]);
}
}
return cnt;
}
If you are provided the head of a linked list, and are asked to reverse every k sequence of nodes, how might this be done in Java? e.g., a->b->c->d->e->f->g->h with k = 3 would be c->b->a->f->e->d->h->g->f
Any general help or even pseudocode would be greatly appreciated! Thanks!
If k is expected to be reasonably small, I would just go for the simplest thing: ignore the fact that it's a linked list at all, and treat each subsequence as just an array-type thing of things to be reversed.
So, if your linked list's node class is a Node<T>, create a Node<?>[] of size k. For each segment, load k Nodes into the array list, then just reverse their elements with a simple for loop. In pseudocode:
// reverse the elements within the k nodes
for i from 0 to k/2:
nodeI = segment[i]
nodeE = segment[segment.length-i-1]
tmp = nodeI.elem
nodeI.elem = nodeE.elem
nodeE.elem = tmp
Pros: very simple, O(N) performance, takes advantage of an easily recognizable reversing algorithm.
Cons: requires a k-sized array (just once, since you can reuse it per segment)
Also note that this means that each Node doesn't move in the list, only the objects the Node holds. This means that each Node will end up holding a different item than it held before. This could be fine or not, depending on your needs.
This is pretty high-level, but I think it'll give some guidance.
I'd have a helper method like void swap3(Node first, Node last) that take three elements at an arbitrary position of the list and reverses them. This shouldn't be hard, and could could be done recursively (swap the outer elements, recurse on the inner elements until the size of the list is 0 or 1). Now that I think of it, you could generalize this into swapK() easily if you're using recursion.
Once that is done, then you can just walk along your linked list and call swapK() every k nodes. If the size of the list isn't divisble by k, you could either just not swap that last bit, or reverse the last length%k nodes using your swapping technique.
TIME O(n); SPACE O(1)
A usual requirement of list reversal is that you do it in O(n) time and O(1) space. This eliminates recursion or stack or temporary array (what if K==n?), etc.
Hence the challenge here is to modify an in-place reversal algorithm to account for the K factor. Instead of K I use dist for distance.
Here is a simple in-place reversal algorithm: Use three pointers to walk the list in place: b to point to the head of the new list; c to point to the moving head of the unprocessed list; a to facilitate swapping between b and c.
A->B->C->D->E->F->G->H->I->J->L //original
A<-B<-C<-D E->F->G->H->I->J->L //during processing
^ ^
| |
b c
`a` is the variable that allow us to move `b` and `c` without losing either of
the lists.
Node simpleReverse(Node n){//n is head
if(null == n || null == n.next)
return n;
Node a=n, b=a.next, c=b.next;
a.next=null; b.next=a;
while(null != c){
a=c;
c=c.next;
a.next=b;
b=a;
}
return b;
}
To convert the simpleReverse algorithm to a chunkReverse algorithm, do following:
1] After reversing the first chunk, set head to b; head is the permanent head of the resulting list.
2] for all the other chunks, set tail.next to b; recall that b is the head of the chunk just processed.
some other details:
3] If the list has one or fewer nodes or the dist is 1 or less, then return the list without processing.
4] use a counter cnt to track when dist consecutive nodes have been reversed.
5] use variable tail to track the tail of the chunk just processed and tmp to track the tail of the chunk being processed.
6] notice that before a chunk is processed, it's head, which is bound to become its tail, is the first node you encounter: so, set it to tmp, which is a temporary tail.
public Node reverse(Node n, int dist) {
if(dist<=1 || null == n || null == n.right)
return n;
Node tail=n, head=null, tmp=null;
while(true) {
Node a=n, b=a.right; n=b.right;
a.right=null; b.right=a;
int cnt=2;
while(null != n && cnt < dist) {
a=n; n=n.right; a.right=b; b=a;
cnt++;
}
if(null == head) head = b;
else {
tail.right=b;tail=tmp;
}
tmp=n;
if(null == n) return head;
if(null == n.right) {
tail.right=n;
return head;
}
}//true
}
E.g. by Common Lisp
(defun rev-k (k sq)
(if (<= (length sq) k)
(reverse sq)
(concatenate 'list (reverse (subseq sq 0 k)) (rev-k k (subseq sq k)))))
other way
E.g. by F# use Stack
open System.Collections.Generic
let rev_k k (list:'T list) =
seq {
let stack = new Stack<'T>()
for x in list do
stack.Push(x)
if stack.Count = k then
while stack.Count > 0 do
yield stack.Pop()
while stack.Count > 0 do
yield stack.Pop()
}
|> Seq.toList
Use a stack and recursively remove k items from the list, push them to the stack then pop them and add them in place. Not sure if it's the best solution, but stacks offer a proper way of inverting things. Notice that this also works if instead of a list you had a queue.
Simply dequeue k items, push them to the stack, pop them from the stack and enqueue them :)
This implementation uses ListIterator class:
LinkedList<T> list;
//Inside the method after the method's parameters check
ListIterator<T> it = (ListIterator<T>) list.iterator();
ListIterator<T> reverseIt = (ListIterator<T>) list.listIterator(k);
for(int i = 0; i< (int) k/2; i++ )
{
T element = it.next();
it.set(reverseIt.previous());
reverseIt.set(element);
}