How do I label a list of lists sequentially? - algorithm

Suppose I have a sequence and a list of lists:
["A" "B" "C" "D" "E"]
[[:1 :2][:3 :4 :5]]
And I'd like to use the sequence to label each element of the list of lists:
[["A" :1 "B" :2] ["C" :3 "D" :4 "E" :5]]
What should my algorithm be?
Edit: So the best answer Stack Overflow can give is to make a copy and then mutate it, and that only works if the data is a specific shape?
I've accepted that answer since it's correct and the only answer given, but surely we can do better than that?

Should be fairly simple. Iterate through your sublist elements while moving an index through the sequence. If the lists are longer than the sequence, you can use a modulo to set the moving index to the beginning of the sequence when it reaches the end.
int index = 0
for(sublist in list) {
for(element in sublist) {
element.label = sequence[index++]
index = index modulo length_of(sequence)
}
}
If your sublists can also have sublists, then you would probably have to make a recursive method.

Related

Merge Sort Algorithm last step

// Sorts the sequence (A[p],...,A[r-1])
template<class T>
void merge_sort(array<T>& A,int p,int r)
{
if (p<r-1)
{
int q=?; // see discussion in the text
merge_sort(A,p,q);
merge_sort(A,q,r);
merge(A,p,q,r);
}
}
Let's say array is [4, 9, 13, 1, 5]. I understand the recursion, the first merge_sort method splits the array up until the point of [4], so the first and second merge sort method gets skipped.How does it know where the rest of the array is to merge it? Array A is now only [4], so if we call merge (A,p,q,r) it only gets the 4 and no other part of it to merge it with?
Array A is now only [4] ... it only gets the 4 and no other part of it to merge it with.
That's were the confusion is. The array doesn't get shorter! At all times the array is the complete array with all its original values.
The notion of a subarray is only reflected by the additional parameters, p and r. These mark the range of interest in that full array (where p is the first index that is in the range, and r is the first index after the range).
Look for instance, at this recursive call:
merge_sort(A,p,q);
The p and q indices mark where in the array A is the partition that we want to sort. That call will only work with that part of the array.
At a certain moment, we will have p==0, q==1 and r==2 and the above call will then look at one element only, A[0].
The next recursive call is:
merge_sort(A,q,r);
This call will also look at one element: A[1].
These two calls will just return (as obviously nothing had to be done as a subarray with just one value is always "sorted"), and then the merge can be done with this call:
merge(A,p,q,r);
Note that this merge call gets to work with two values: A[0] and A[1]. When this call returns we know that the values at indices 0 and 1 are now guaranteed to be in sorted order.

Trying to improve efficiency of this search in an array

Suppose I have an input array where all objects are non-equivalent - e.g. [13,2,36]. I want the output array to be [1,0,2], since 13 is greater than 2 so "1", 2 is greater than no element so "0", 36 is greater than both 13 and 2 so "2". How do I get the output array with efficiency better than O(n2)?
Edit 1 : I also want to print the output in same ordering. Give a c/c++ code if possible.
Seems like a dynamic programming.
May be this can help
Here is an O(n) algorithm
1.Declare an array of say max size say 1000001;
2.Traverse through all the elements and make arr[input[n]]=1 where input[n] is the element
3.Traverse through the arr and add with the previous index(To keep record of arr[i] is greater than how many elements) like this
arr[i]+=arr[i-1]
Example: if input[]={12,3,36}
After step 2
arr[12]=1,arr[3]=1,arr[36]=1;
After step 3
arr[3]=1,arr[4]=arr[3]+arr[4]=1(arr[4]=0,arr[3]=1),
arr[11]=arr[10]=arr[9]=arr[8]=arr[7]arr[6]=arr[5]=arr[4]=1
arr[12]=arr[11]+arr[12]=2(arr[11]=1,arr[12]=1)
arr[36]=arr[35]+arr[36]=3(because arr[13],arr[14],...arr[35]=2 and arr[36]=1)
4.Traverse through the input array an print arr[input[i]]-1 where i is the index.
So arr[3]=1,arr[12]=2,arr[36]=3;
If you print arr[input[i]] then output will be {2,1,3} so we need to subtract 1 from each element then the output becomes {1,0,2} which is your desired output.
//pseude code
int arr[1000001];
int input[size];//size is the size of the input array
for(i=0;i<size;i++)
input[i]=take input;//take input
arr[input[i]]=1;//setting the index of input[i]=1;
for(i=1;i<1000001;i++)
arr[i]+=arr[i-1];
for(i=0;i<size;i++)
print arr[input[i]]-1;//since arr[i] was initialized with 1 but you want the input as 0 for first element(so subtracting 1 from each element)
To understand the algorithm better,take paper and pen and do the dry run.It will help to understand better.
Hope it helps
Happy Coding!!
Clone original array (and keep original indexes of elements somewhere) and quicksort it. Value of the element in quicksorted array should be quicksorted.length - i, where i is index of element in the new quicksorted array.
[13, 2, 36] - original
[36(2), 13(1), 2(0)] - sorted
[1, 0, 2] - substituted
def sort(array):
temp = sorted(array)
indexDict = {temp[i]: i for i in xrange(len(temp))}
return [indexDict[i] for i in array]
I realize it's in python, but nevertheless should still help you
Schwartzian transform: decorate, sort, undecorate.
Create a structure holding an object as well as an index. Create a new list of these structures from your list. Sort by the objects as planned. Create a list of the indices from the sorted list.

Given 2 arrays, returns elements that are not included in both arrays

I had an interview, and did one of the questions described below:
Given two arrays, please calculate the result: get the union and then remove the intersection from the union. e.g.
int a[] = {1, 3, 4, 5, 7};
int b[] = {5, 3, 8, 10}; // didn't mention if has the same value.
result = {1,4,7,8,10}
This is my idea:
Sort a, b.
Check each item of b using 'dichotomy search' in a. If not found, pass. Otherwise, remove this item from both a, b
result = elements left in a + elements left in b
I know it is a lousy algorithm, but nonetheless it's better than nothing. Is there a better approach than this one?
There are many approaches to this problem. one approach is:
1. construct hash-map using distinct array elements of array a with elements as keys and 1 is a value.
2. for every element,e in array b
if e in hash-map
set value of that key to 0
else
add e to result array.
3.add all keys from hash-map whose values 1 to result array.
another approach may be:
join both lists
sort the joined list
walk through the joined list and completely remove any elements that occurs multiple times
this have one drawback: it does not work if input lists already have doublets. But since we are talking about sets and set theory i would also expect the inputs to be sets in the mathematical sense.
Another (in my opinion the best) approach:
you do not need a search through your both lists. you can just sequentially iterate through them:
sort a and b
declare an empty result set
take iterators to both lists and repeat the following steps:
if the iterators values are unequal: add the smaller number to the result set and increment the belonging iterator
if the iterators values are equal: increment both iterators without adding something to the result set
if one iterator reaches end: add all remaining elements of the other set to the result

What is the most efficient way to sort a number list into alternating low-high-low sequences?

Suppose you are given an unsorted list of positive integers, and you wish to order them in a manner such that the elements alternate as: (less than preceding element), (greater than preceding element), (less than preceding element), etc... The very first element in the output list may ignore the rule. So for example, suppose your list was: 1,4,9,2,7,5,3,8,6.
One correct output would be...
1,9,2,8,3,7,4,6,5
Another would be...
3,4,2,7,5,6,1,9,8
Assume that the list contains no duplicates, is arbitrarily large, and is not already sorted.
What is the most processing efficient algorithm to achieve this?
Now, the standard approach would be to simply sort the list in ascending order first, and then peel elements from the ends of the list in alternation. However, I'd like to know: Is there a more time-efficient way to do this without first sorting the list?
My reason for asking: (read this only if you care)
Apparently this is a question my sister's boyfriend poses to people at job interviews out in San Francisco. My sister asked me the question, and I immediately came up with the standard response. That's what everyone answers. However, apparently one girl came up with a completely different solution that does not require sorting the list, and it appears to work. My sister couldn't explain to me this solution, but the idea has been confounding me since last night. I'd appreciate any help! Thanks!
You can do this in O(n) by placing each element in turn at the end, or at the penultimate position based on a comparison with the current last element.
For example,
1,4,9,2,7,5,3,8,6
Place 1 at end, current list [1]
4>1 true so place 4 at end, current list [1,4]
9<4 false so place 9 at penultimate position [1,9,4]
2>4 false so place 2 at penultimate [1,9,2,4]
7<4 false so place 7 at penultimate [1,9,2,7,4]
5>4 true so place 5 at end [1,9,2,7,4,5]
3<5 true so place 3 at end [1,9,2,7,4,5,3]
8>3 true so place 8 at end [1,9,2,7,4,5,3,8]
6<8 true so place 6 at end [1,9,2,7,4,5,3,8,6]
Note that the equality tests alternate, and that we place at the end if the equality is true, or at the penultimate position if it is not true.
Example Python Code
A=[1,4,9,2,7,5,3,8,6]
B=[]
for i,a in enumerate(A):
if i==0 or (i&1 and a>B[-1]) or (i&1==0 and a<B[-1]):
B.insert(i,a)
else:
B.insert(i-1,a)
print B
One solution is this. Given in Pseudocode.
Assuming, nums has at least two elements and all elements in nums are distinct.
nums = [list of numbers]
if nums[0] < nums[1]: last_state = INCREASING else: last_state = DECREASING
for i = 2 to len(nums - 1):
if last_state = INCREASING:
if nums[i] > nums[i-1]:
swap (nums[i], nums[i-1])
last_state = DECREASING
else
if nums[i] < nums[i-1]:
swap (nums[i], nums[i-1])
last_state = INCREASING
Proof of correctness:
After each loop iteration, elements upto index i in nums remain alternating and last_state is represent the order of i th and i-1 th elements.
Note that a swapping happens only if last 3 items considered are in order. (Increasing or Decreasing) Therefore, if we swapped ith element with i-1 th element, the order of i-2 th element and i-1th element will not change.

Trying to understand how array.sort works with custom comparer block

I am new to ruby and doing a RubyMonk tutorial. One of the problems is the following. Can someone please enlighten me because I am not understanding the suggested solution?
Problem Statement
Create a method named 'sort_string' which accepts a String and rearranges all the words in ascending order, by length. Let's not treat the punctuation marks any different than other characters and assume that we will always have single space to separate the words.
Example: Given a string "Sort words in a sentence", it should return "a in Sort words sentence".
Suggested Solution:
def sort_string(string)
string.split(' ').sort{|x, y| x.length <=> y.length}.join(' ')
end
My questions are;
1) Why are there two block variables being passed through? Should there only be one, because you are going through every element of the sentence one at a time?
2) I looked up the <=> operator and it states,"Combined comparison operator. Returns 0 if first operand equals second, 1 if first operand is greater than the second and -1 if first operand is less than the second." So aren't we essentially sorting by -1, 0, and 1 then, not the words?
Thank you very much in advance for your help!
1) Why are there two block variables being passed through? Should there only be one, because you are going through every element of the sentence one at a time?
Because that's how the sort method works. It compares two elements at a time, and the block tells it how to compare the two elements. There is a single-element method called sort_by which will only require one which could be used in this case:
def sort_string(string)
string.split(' ').sort_by{|x| x.length}.join(' ')
end
Or even shorter:
def sort_string(string)
string.split(' ').sort_by(&:length).join(' ')
end
2) I looked up the <=> operator and it states,"Combined comparison operator. Returns 0 if first operand equals second, 1 if first operand is greater than the second and -1 if first operand is less than the second." So aren't we essentially sorting by -1, 0, and 1 then, not the words?
Again, this is how sorting works. Sort looks at the result and, depending upon the value -1, 0, or 1 will order the original data accordingly. It's not ordering the results of <=> directly. If you've done any C programming and used strcmp, think about how you would use that function. It's based upon the same concept.
For the first question, if you look at the documentation for the sort method its block form takes two variables
http://www.ruby-doc.org/core-2.0.0/Array.html#method-i-sort
For the second question, the spaceship operator does a comparison between the two operands and then returns -1, 0, or 1, and then you're sorting on the results. Yes, you're sorting on -1, 0, and 1, but those values are obtained from the comparison.
There are two block variables because to sort you need two items - you can't compare one item against nothing or itself.
You are sorting by -1, 0 and 1 - through the words.
Both of these questions are related to the sort method - here's an example which might make it clearer:
(1..10).sort { |a, b| b <=> a } #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
for each number 1 -10, sort looks at 'a' and 'b' - the block arguments. then in the block, the code says to order b higher than a - and this is what it does
The sort function by default sorts the items in some order.
However, if it is passed a block, it uses that block to compare the elements of the array, so that you can define a different, custom order of the elements.
That is, the block has to compare the elements. A minimalistic working version of such comparison is to compare two elements, just to know which one is "greater-or-equal".
This is why the custom block takes two parameters: those are the elements to compare. You don't actually know which one. The sort will perform some sorting algorithm and depending on the internals, it will pick some pairs of elements, compare them using your block, and then, well, it will use that knowledge to reorder the elements in order.
As you provide a block that 'compares', it'd be not very efficient to just return BOOL that says "greater or not". A better and often a bit faster way is to determine if the elements are equal, less, or greater. At once.
arr.sort {|item1, item2}
if item1 < item2 return :lesser
if item1 == item2 return :equal
if item1 < item2 return :greater
}
This is just pseudocode.
With numbers, it is very easy: just subtract them. If you get less-than-zero, you know that the first was lesser. If you get more-than-zero, the first was bigger. If you got zero, they were equal. So, over the time it was 'standarized' way of describing the three-way comparison result to some sorting algorithms.
arr.sort {|item1, item2}
if item1 < item2 return -1
if item1 == item2 return 0
if item1 > item2 return 1
}
or just
arr.sort {|item1, item2}
return item1 - item2
}
Not all types can be subtracted though. Ruby went somewhat further and defined "comparison operator". Instead of just separate </>/==/<=/>=, it provides you with <=> that returns numeric values. -1 meaning that left was lesser and so on.
arr.sort {|item1, item2}
return item1 <=> item2
}
Now, if you provide <=> operator to MyClass, you will be able to sort them easily, even if plain item1-item2 cannot work on non-numeric 'MyClass'..

Resources