Related
I'm looking for a solution for this problem.
I have an array which defines the rule of the order of elements like below.
let rule = [A,B,C,D,E,F,G,H,I,J,K]
I then have another array whose element can be removed or added back.
So for example, I have a list like this:
var list = [A,D,E,I,J,K]
Now If I want to add element 'B' to 'list' the list should be
var list = [A,B,D,E,I,J,K]
because 'B' comes after 'A' and before 'D' in the rule array. So the insertion index would be 1 in this case.
The item in the array are not comparable each other (Let's say a developer can change the order of rule list at any time if that make sense). And there needs no duplicates in the array.
I'm not sure if I explained the problem clearly, but I'd like to know a good approach that finds an insertion index.
Explained the Python code in comments. Basically, find the right place to insert the new element using binary search. The order of elements is decided using rank. The below code assumes that if elements is non-empty then the rule is followed by items in the elements.
rule = ['A','B','C','D','E','F','G','H','I','J','K']
rank = dict()
for i in range(len(rule)):
rank[rule[i]] = i
elements = ['A','D','E','I','J','K'] #list in which we wish to add elements
target = 'B' #element to be inserted
#Binary search to find the right place to insert the target in elements
left, right = 0, len(elements)
while left < right:
mid = left + (right - left) // 2
if rank[elements[mid]] >= rank[target]:
right = mid
else:
left = mid + 1
elements.insert(left, target) #left is the insertion index
print(elements)
Time complexity of add: O(log(len(elements)))
Space complexity: O(1)
If the items are unique (only can occur once), and are not comparable to each other (don't know that B comes after A), then.
Iterate through the rules and find the items position in the rule array.
Check if it is the first item in rules, if so insert at the first position and skip the other steps.
Check to see if it is the last item in rules, if so insert at the end and skip the other steps.
Select the value of the item 1 before into a variable A.
Select the value of the item 1 after into a variable B.
Iterate through the list,
if you encounter the value in parameter A insert it after that value, if you encounter the value B, add the value before that.
If you come to the end without finding either value A or B, then you need to repeat but with values 2 before and 2 after the item in the rules (again checking to see if you hit the start or end of the rules list).
You will probably want to make 6 & 7 a function that calls itself recursively.
A simple approach is, we can use one iteration of Insertion sort.
So, we start from right side of array compare our input x with array elements a go from right to left side. if we arrive an index i of array that let[i]<=x then let[i+1] is correct location that x can be insert.
This approach that has time complexity O(n), follow from correctness of Insertion sort.
Note that the lower of your problem is O(n) because your data structure is array so you need after each insertion shift whole elements.
In my example, I have done to use the first (left-most) element of the given list is selected as the pivot.
qsort([],[]):- !.
qsort([Pivot|Tail],Sorted):-
split(Pivot,Tail,Less,Greater),
qsort(Less,SortedLess),
qsort(Greater,SortedGreater),
append(SortedLess,[Pivot|SortedGreater],Sorted).
split(_,[],[],[]).
split(Pivot,[X|T],[X|Less],Greater):-
X=<Pivot,split(Pivot,T,Less,Greater).
split(Pivot,[X|T],Less,[X|Greater]):-
X>Pivot,split(Pivot,T,Less,Greater).
However, I am wondering how to use the second element as pivot
I have a list like this:
[(51, 'Elijah'), (144, 'Chloe'), (485, 'Elizabeth'), (485, 'Matthew'), (207, 'Natalie'), (390, 'Jayden')]
I want to sort it in reverse order using as the key the first element of the tuple. If that is the same, I need to sort it by the second element in alphabetical order. I tried to using sorted(lista, key=function) but i get all kind of errors. Thanks, in advance.
Since the reversed option is "global", not per element of the tuple, but your first element is a number, you can reverse the numbers sorting direction by simply negating it:
>>> sorted(lista, key=lambda x: (-x[0], x[1]))
[(485, 'Elizabeth'), (485, 'Matthew'), (390, 'Jayden'), (207, 'Natalie'), (144, 'Chloe'), (51, 'Elijah')]
When lists of tuples are sorted, first the first element is compared, and if it's equal the second, and so on. So as a key function you can simply create one on the fly (using lambda) that creates a tuple from the original tuple, but inverts the first element.
Given an array A, find a shortest subarray A[i : j ] such that each distinct value present in A is also present in the subarray.
The question is not for a homework. It's a practice problem from a chapter on Hash tables. I am not looking for the code. Just looking for the algorithm or hints.
1- Maintain a hash table element->count
2- Traverse array from begin to end, incrementing the element count. Whenever an element count is changed from 0 to 1, record it's index in a variable , say index_0_1. In the end index_0_1 will have end index of a potential ans.
3- Traverse array from begin to index_0_1, decrementing the element count. Stop, whenever an element count is changed from 1 to 0, record it's index in a variable, say index_1_0. subarray A[index_1_0 : index_0_1] is a potential ans, record it.
4- Traverse from index_0_1 towards end, incrementing the element count and stop whenever you find element A[index_1_0]. Update index_0_1 with current index.
5- Traverse from index_1_0+1 to index_0_1, decrementing the element count. Stop whenever an element count is changed from 1 to 0. This is new index_1_0. If subarray A[index_1_0: index_0_1] is smaller than previous ans, update it and continue with steps 4 and step 5, until whole array have been traversed.
Use a hash table to maintain a count of each type of element in the string.
when you find a new type of element
discard all previous answers and start trimming the start of the substring,
when you can trim it no more without having zero of one type of element
remember the substring if it's the shortest yet found and then start looking for another element to replace the one you are about to loose or to find a new element not previously seen as above.
When you hit the end of the string you are done.
If your hash is any good, this should be O(n)
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.