Aranging integers in a specific order - algorithm

Given a set of distinct unsorted integers s1, s2, .., sn how do you arrange integers such that s1 < s2 > s3 < s4...
I know this can be solved by looking at the array from left to right and if the condition is not satisfied swapping those two elements gives the right answer. Can someone explain me why this algorithm works.

Given any three successive numbers in the array, there are four possible relationships:
a < b < c
a < b > c
a > b < c
a > b > c
In the first case we know that a < c. Since the first condition is met, we can swap b and c to meet the second condition, and the first condition is still met.
In the second case, both conditions are already met.
In the third case, we have to swap a and b to give b < a ? c. But we already know that b < c, so if a < c then swapping to meet that second condition doesn't invalidate the first condition.
In the last case we know that a > c, so swapping a and b to meet the first condition maintains the validity of the second condition.
Now, you add a fourth number to the sequence. You have:
a < b > c ? d
If c < d then there's no need to change anything. But if we have to swap c and d, the prior condition is still met. Because if b > c and c > d, then we know that b > d. So swapping c and d gives us b > d < c.
You can use similar reasoning when you add the fifth number. You have a < b > c < d ? e. If d > e, then there's no need to change anything. If d < e, then by definition c < e as well, so swapping maintains the prior condition.
Pseudo code that implements the algorithm:
for i = 0 to n-2
if i is even
if (a[i] > a[i+1])
swap(a[i], a[i+1])
end if
else
if (a[i] < a[i+1])
swap(a[i], a[i+1])
end

Here is the code to the suggested solution in java.
public static int [] alternatingList(int [] list) {
int first, second,third;
for (int i = 0;i < list.length-2;i+=2) {
first = list[i];
second = list[i+1];
third = list[i+2];
if (first > second && first > third) {
list[i+1] = first;
list[i] = second;
}
else if (third> first && third > second) {
list[i+1] = third;
list[i+2] = second;
}
}
return list;
}
In this code since all the numbers are distinct there will always be a bigger number to put into the "peaks". Swapping the numbers will not change the consistency of the last part you did because the number you swap out will always be smaller than the one you put into the new peak.
Keep in mind this code doesn't handle some edge cases like even length lists and lists smaller than three, I wrote it pretty fast :), I only wrote the code to illustrate the concept of the solution
In addition this solution is better than the one in the proposed dupe because it makes one pass. The solution in the dupe uses the hoare's selection algorithm which is n but requires multiple decreasing in size passes on the list, also it needs to make another n pass on the list after using Hoare's (or the median of medians).
More mathematical proof:
For every three consecutive numbers a,b,c there are three options
a > b && a > c
b > c && b > a
c > a && c > b
In the first case you switch a into the middle because it's the largest, second case do nothing (largest is already in the middle) and 3rd case 'c` goes to the middle.
now you have a < b > c d e where for now d and e are unknown. Now the new a,b,c are c,d,e and you do the same operation this is guaranteed not to mess up the order since c will only be changed if it is larger than d and e thus the number moved into c's spot will be smaller than b and not break the ordering, this can continue infinitely clearly with the order never breaking.

Related

Struggling to find loop invariant in power function

I am struggling to find a good loop invariant for the following function, which returns a^b where a is a real number and b is a natural number:
power <- function(a, b){
c <- 1
while(b > 0){
if(b %% 2 == 1){
c <- c * a
}
b <- floor(b / 2)
a <- a * a
}
return c
}
I've ran through the loop with a couple of examples, and I see that it has 2 kinds of cases; when b is even or odd. I also understand that on the kth iteration, a = a_0^(2^k), but I am struggling to find a proper invariant as there is no real iterating variable to use.
For the invariant to be useful, it will have to have c = a_0^b_0 as a special case after the while loop terminates, which occurs when b = 0.
For the invariant to be true, we have to get a_0^b_0 on the left hand side before the first iteration. We already know the left hand side has a c in it, and before the first iteration c = 1, so multiplication seems like a good idea.
Whatever we multiply by must end up being 1 after the loop terminates, which (as before) occurs when b = 0. Getting something to equal 1 when b is 0 suggests we want b to be an exponent, and the desired a_0^b_0 on the left hand side also suggests b should be an exponent.
Putting this all together, the invariant will either be c * a_0^b = a_0^b_0 or c * a^b = a_0^b_0. I will leave it to you to determine which one of those is correct, and to prove that it is in fact invariant.

Use of variables in recursion

I have written below code to reverse the first K nodes of linked list, It had some issue resolved in Reversing first K nodes of Linked List,Why recursion executing twice for last iteration, Now it working expected but why it leads to loop in linked list when i try to use variable "k" instead of "presentCounter" in "if" condition,what is the reason? and how to avoid it?
/*
* Condition K <= Length of linked list.
* node = null
* nextNode headNode of the linked list
*/
public void reverseNode(Node node, Node nextNode, int k) {
int presentCounter = k;
if (k > 1) {
k = k - 1;
this.reverseNode(nextNode, nextNode.next, k);
}
if (presentCounter == 1) {
this.kNode = nextNode.next; // Saving K's Next Node
this.headNode = nextNode; // Setting K node as head node
}
if (node == null) {
nextNode.next = this.kNode;
} else
nextNode.next = node;
}
Because presentCounter is also used later to check for the last element to swap with if (presenceCount == 1).
If you naively get rid of k and use presentCounter instead
if (presentCounter > 1) {
presentCounter = presentCounter - 1;
this.reverseNode(nextNode, nextNode.next, presentCounter);
}
since now presentCounter has been decremented, the check for the last element to swap triggers one item before.
For example in the list [a b c d] when requested to swap the first three elements, the check should be true for c so that this.kNode is d.
If instead is true one step before, i.e. for b, then this.kNode is c (and the head is set to b).
When linking the elements in reverse order (c b a), the old head1 is linked to this.kNode, so we end up with two different result:
Corret (this.kNode is d)
c b a d
Incorrect (this.kNode is c)
b a c b a c ...
The second one is a loop.
You can easily get rid of k though
if (presentCounter > 1)
this.reverseNode(nextNode, nextNode.next, presentCounter-1);
In order to better understand what is going on, here is a picture.
You have to understand that there are two phases: the traversing phase
(when the recursion call is made) and the building phase (when the recursion
calls have returned).
So each invocation is pictured twice.
pc stands for presentCounter
1 the first element, the one saved in nextNode when node is null, ie the first invocation of the function.
When k is 2 it enters the first condition (k > 1)
then it will decrement k and recurse
but then after the recursion finishes it will continue to the next line.
k=k-1 gives 1, so "if (k == 1)" will perform the actions inside that second conditional as well on the same pass.
By saving k into presentCounter before you subtract one from it, then checking presentCounter == 1, you avoid this extra task being done twice (once inside the recursion call because k == 1 now, and again when the recursion finishes).

How to solve this programming contest exercise

I stumbled upon this algorithm question, I couldn't get any better approach than brute force, can someone guide me please?
Given a M * N grid of characters (A,B). You are allowed to flip any
number of columns i.e. change A to B and B to A. What is the max
number of rows that can have same symbols after all possible flipping
Eg,
A B A|
B A B|
A B B|
B B A|
The answer is 2, if we flip both column 1 & 3. Please let me know if further explanation is required.
First, note that A B A and B A B are essentially the same for the purposes of this problem: whenever one gets flipped to all As, the other gets flipped to all Bs, and vice versa, so both count for the answer at the same time.
On the other hand, when A B A or B A B is flipped so that it contains the same letters, all other possible rows contain different letters.
So, the first suggested step would be to flip all rows which start with a B, since it will merge the pairs of rows which count for the answer at the same time.
Now, we have
A B A|
A B A| (flipped from B A B)
A B B|
A A B| (flipped from B B A)
What's left is to find a row that occurs most often.
This can be done by constructing a map which, well, maps rows to the number of their occurrences.
For the example, it will look like {A B A: 2, A B B: 1, A A B: 1}`.
Now, A B A obviously wins since it occurs twice, so we flip all the columns with Bs in that row. Flipping all the columns with As is another option.
I have an O(n^2) and O(M) solution but slightly better than bruteforce since the second loop starts to the i+1 of the first loop, tell me what do you think about it :
First we need to change the A, B matrix for a bit matrix where each line will be a binary your matrix becomes :
0 1 0|
1 0 1|
0 1 1|
1 1 0|
now this is based on the fact that bitwise "010 & 101 = 000" so if there is a possible column permutation that will make the rows matched.
Given N and M;
int maxSameSymbole[M] = {0};
for (int i = 0; i < M; i++) {
for (int j = i+1; j < M; j++) {
if (!(line[i].toBinary & line[j].toBinary)) //this will equal 0 if there is a possible flip that will make the 2 rows with the same symbole
maxSameSymbole[i]++;
}
}
// Simple find max in the maxSameSymbole list :
int max = maxSameSymbole[0];
for (int i = 0; i < M; i++) {
if (maxSameSymbole[i] > max)
max = maxSameSymbole[i];
}
Hope this helped to find a better solution.
Start from the first column and get the indices of the rows that would have same symbols if you flipped that column. for example: (1,4,9) rows work. Get those indices for every column and put them as the keys in a map that maps list of indices to a number it occurred. Highest value would be the answer.

Comparing pairs of objects

This is a fairly simple question but I can't remember all my coding and data structures and feel a little blank.
Lets say I have a list/array of things (e.g. structures or objects). There is a certain property (true or false) that needs to hold between all pairs of these objects. What would be the fastest method to check if the property is violated between any pair of objects?
Unless you have additional information about the property (for example, that it is transitive) your only solution is to check that property for every pair from the list, with two nested loops:
for (int i = 0 ; i != N ; i++)
for (int j = 0 ; j != N ; j++)
if (i != j) // This assumes that the property might not be reflexive
// This will check the property both ways, i.e.
// there is no implication that the property is commutative.
checkProperty(list[i], list[j]);
For commutative properties (i.e. when A ? B implies B ? A) you can do it in half the comparisons by starting the second loop at j = i+1
If property is transitive (i.e. when A ? B and B ? C imply that A ? C, where ? denotes the property check) you can build a faster check.
You'll need a double loop to compare every item. Assuming you just need to check every 2-item combination (i.e. order doesn't matter), you can just loop through the remaining items in the inner loop.
for (int i = 0 ; i < N ; i++)
for (int j = i+1 ; j < N ; j++)
checkProperty(list[i], list[j]);

Write an algorithm that finds the second smallest value among a, b, and c

How do I find the second smallest value among a,b and c in Java?
Find-2nd-Smallest (n: array)
smallest : infinity
2nd-smallest : infinity
for each i in n
if i < smallest
2nd-smallest = smallest
smallest = i
else if i < 2nd-smallest
2nd-smallest = i
return 2nd-smallest
How would I make it work for (a,b,c)? I am very confused on how to get a value with only 3 letters.
The function in this pseudo-code you gave finds the smallest and second smallest values in an array.
Run it on the array {a,b,c}.
If there's only three values, you can get away with a very simple function (pseudo-code below):
def second_smallest (a,b,c):
if a < b:
if b < c:
return b
return c
if a < c:
return a
return c
Obviously that will become massively unwieldy if there are more than three numbers but, at that point (see YAGNI), you would convert it to a more generalised solution.
That would be along the lines of:
def second_smallest (list):
if list.size < 2:
throw error "not enough numbers"
if list[0] < list[1]:
first = list[0]
second = list[1]
else:
first = list[1]
second = list[0]
for each index 2 through list.size - 1 inclusive:
if list[index] < first:
second = first
first = list[index]
next for
if list[index] < second:
second = list[index]
return second
That's basically the same sort of logic in your question but with some pre-checks to avoid having to represent infinity (that would be okay if your types were floating point but not so useful for integers).
You should be aware that the generalised solution also solves the more specific problem, assuming your three integers are actually in a list structure of some sort. If you just have the three "naked" values and you're not specifically tasked with coping with the generalised case, I'd use the first block of pseudo-code above.

Resources