I've been searching on google, and couldn't find a a similar question or explanation.
Assume the following code:
int out, in;
for(out=nElems-1; out>1; out--)
for(in=0; in<out; in++) {
if( a[in] > a[in+1] )
swap(in, in+1);
}
Why does the outer loop stops when after the outer value reaches 1? Isn't it supposed to have 2 elements left? The 0 and 1 places? What makes us so sure that they are already sorted?
I understand how the Algorithm work, and realise there would be a better solution with a flag that stops if no iteration are done, but I'm really interested in understanding the above code.
So, i am afraid the book code doesn't work, let's prove it by example:
Array ={3,2,1};//nvm the syntax, i assume pseudocode because we don't even know what is swap()
nElems=3;
For: out=2;
For:in=0
check 0 and 1
Array={2,3,1}
in=1
check 1 and 2
Array={2,1,3}
in=2, break;
out=1, break;
You can see the flow ended with array {2,1,3} which is not sorted. So even books may have errors, or maybe if you read few pages ahead you might find out it was intentional. Correct bubble sort would have condition out>=1 or out>0
EDIT: with array consisting of 2 elements, the algorithm will do nothing, even simplier proof
Array ={2,1};
nElems=2;
For: out=1, break;//out = nElems-1, 1>1 is false
When out reaches 2, the inner loop goes from 0 to 1. It makes sure the two elements at [0] and [1] are in the correct order - this is the time to stop bubble sorting. However, the code you presented above will then compare [1] and [2] - resulting in a potential swap leading to unsorted array (as [0] and [1] should be compared again, after [1] and [2] are compared). For this code to work, the outer loop should go downto 1 inclusive, so for (out = nElems - 1; out > 0; out--).
What you need to see here is the fact, that in bubble sort the inner loop is doing the actual job of sorting (by swapping the elements). The outer loop is just setting the limit beyond which all elements are already sorted.
Related
I have this assignment where given a list of tuples where each tuple contains 2 Strings like this :
[ ("...","...") , ("...","...") , ("...","...") ... ]
I have to calculate the shortest path which will lead to an extreme-string.
An extreme-string is defined as a tuple of 2 strings where the first string is equal to the second string.
I know this might sound confusing so let me set an example.
Given :
The list [("0","100") , ("01","00") , ("110","11")]
With indices 0,1,2
The shortest path is : [2,1,2,0]
The extreme-string is equal to : "110011100"
Step by step explanation :
Starting with tuple of index 2 the initial string is : "110","11"
Appending tuple of index 1 next string is : "11001","1100"
Appending tuple of index 2 next string is : "11001110","110011"
Appending tuple of index 0 final string is : "110011100","110011100"
So say you begin with tuple ("X","Y") and then you pick tuple ("A","B") then result is ("XA","YB").
The way I approached this problem was using BFS which I already implemented and sounds right to me but there is an issue I am dealing with.
If the input is something like :
[("1","111")]
then the algorithm will never terminate as it will always be in the state "111..." - "111111111..." .
Checking for this specific input is not a good idea as there many inputs that can reproduce this result.
Having an upper bound for the iterations is also not a good idea because in some cases a finite result may actually exist after the iterations bound.
Any insight would be really useful.
Since its an assignment I can't really solve it for you, but I'll try to give tips:
BFS sounds great to me as well.
One thing that differentiates the BFS from, say, DFS is that you place the elements of level N into the queue (as opposed to stack). Since queue is FIFO, you'll process the elements of Level N before elements at the level of N + 1. So this algorithm will finish (although might occupy a lot of memory).
The interesting part is what exactly you put into the queue and how you organize the traversal algorithm. This is something that I feel you've already solved or at least you have a direction. So think about my previous paragraph and hopefully you'll come to the solution ;)
Im working on a research paper about quicksort for school and thus I have to make a precise runtime analysis on best and worst case for my algorithm but im struggling with the part of my while-statements. I understand why its log(n) since you have so many recursive calls that you have n/2^k = 1 and this equation gives you n = 2^k, k = log2(n) and so on ... well since i did understand the recursive calls this part does not really matter but what matters is my following code:
}
}
I have to specify the "cost" for each statement in dependence of my elements n.
So i added a +1 for every if statement since they are simple statements and now i dont now how to get the cost for the while loops. The outer loop runs until the pointers i and j cross so the outer loop gets execuated at least n/2+1 (+1 for the exit condition) - but i cant find out how often the inner two while loops run. I thought that they would run also n/2 times but this cant work since our teacher taught us that we have to multiply the costs whenever we have nested statements which would result in a (n/2+1)*((n/2)+1)+((n/2)+1)) which is clearly n^2 and not O(n) ...
And yes i have to add a +1 for each abort condition and if statement altough they dont really matter ...
I hope you can help me by telling me whats my mistake that i get a O(n^2) runtime although it has to be O(n)
Side note: I think for the while-loops it doesnt matter if its the best or worst case so dont mind that
Thanks in advance
ChampSilver
The reason why the worst case run time is O(n) is that if you have a careful look at the code, you realize that you visit each array index at most once:
observe that index i only increases at size, and index j only decrease, therefore you'll go at most once over each index.
For example, if you have an array a[] of size 10, then the initial index i will be 0, and j will be 9. x will be (randlomly) somewhere in between, let's say x=4.
Then, the outer while loop enters, and the first inner while loop increases index i until a[i] >= a[x].
The second inner while loop does the same to index j, for the opposite direction.
But the sum of total iterations of both inner loops is at most 10. At which point the next outer while loop check will return false and no second iteration will occur.
Lets start with this:
our teacher taught us that we have to multiply the costs whenever we have nested statements which would result in a (n/2+1)*((n/2)+1)+((n/2)+1)) which is clearly n^2 and not O(n)
This is only true if the looping variables in inner and outer loops are independent of each other.
eg.
for i in range(1..10):
for j in range(1..10):
do something
This is because, for every value of i, inner loop iterates for all values of j. So, this is O(n^2). Now, lets look the other example:
for i in range(1..10):
for i in range(1..10):
do something
In this case, the outer loop runs only once as when inner loop exits, condition for outer loop also discontinues. So, this is, O(n).
Now, lets look at your while loops.
The outer condition is while i is less than j. Inside, we are always incrementing i and decreasing j. So, in this case, the total number of times while statements (all 3) are executed will be the upper bound on i + j, which is 2n. So, complexity is O(2n) or, O(n).
EDIT:
I am making this edit to explain what "complexity" means, practically.
It is a way of approximating/calculating, number of iterations that are made in total, all loops and instructions combined, as size of input increases. So, if you really want to know that, just assign a variable, say a and add 1 to a as the 1st line of every loop. Then print a for different input sizes and you will know what O() notation means, theoretically vs practically.
public static void findNumber(int number) {
int[] soretedArray = { 1, 5, 6, 8, 9 };
for (int i = 0; i <= soretedArray.length; i++) {
for (int j = i + 1; j < soretedArray.length; j++) {
if (soretedArray[i] + soretedArray[j] == number) {
System.out.println(soretedArray[i] + "::" + soretedArray[j]);
return;
}
}
}
}
Using this code I am able to find the number and its complexity is O(N^2) but I have to find this using O(N) complexity i.e using only one for loop or hash-map or similar in Java.
I remember, I was watching the official Google video about this problem. Although it is not demonstrated in java, it is explained step-by-step in different variations of the problem. You should definitely check it:
How to: Work at Google — Example Coding/Engineering Interview
As explained in the Google video that Alexander G is linking to, use two array indexes. Initialize one to the first element (0) and the other to the last element (sortedArray.length - 1). In a loop, check the sum of the two elements at the two indexes. If the sum is the number you were looking for, you’re done. If it’s too high, you need to find a smaller number at one of the indexes; move the right index one step to the left (since the array is sorted, this is the right way). If on the other hand, the sum you got was too low, move the left index to the right to obtain a higher first addend. When the two indexes meet, if you still haven’t found the sum you were looking for, there isn’t any. At this point you have been n - 1 times through the loop, so the algorithm runs in O(n).
We ought to first check the precondition, that the array is really sorted. This too can be done in O(n), so doing it doesn’t break any requirements.
The algorithm may need refinement if you are required to find all possible pairs of numbers that yield the desired sum rather than just one pair.
Is this answer superfluous when the video link has already said it? For one thing, my explanation is shorter, so if it suffices, you’re fine. Most importantly, if the video is removed or just moved to another URL, my answer will still be here.
With fixed number, for any chosen x in the array you just have to find if number-x is in the array (Note that you can also bound x). This will not give you O(n), but O(n.log(n)).
Maybe by remarking that if you have a_i and a_j (j>i), taking the sum and comparing against number, if the result is greater next interesting tests are with a_(i-1) or a_(j-1), and if result is lower next interesting tests are with a_(i+1) or a_(j+1), will give hint to linear-time?
ArrayList<ArrayList<ArrayList<String>>> one = new ArrayList<ArrayList<ArrayList<String>>>();
one would look something like this with some example values:
[
[
["A","B","C",...],
["G","E","J",...],
...
],
[
["1","2",...],
["8","5","12","7",...],
...
],
...
]
Assuming that there will always be one base case, at least one letter arraylist (e.g. ["A","B","C"]), but there could be more (e.g. ["X,"Y","Z"]) and there may be any size of number arraylists, maybe none at all, but could be hundreds (e.g. ["1","2","3"],...,["997","998","999"]). Also, there could be more types of arraylists (e.g. ["#","#","$"]) of any size. So really the only thing that is definitive is that ALWAYS:
one.size()>=1
one.get(0).size()>=1
one.get(0).get(0).size()>=1
So the problem is: How can I best get every combination of each category without knowing how large each arraylist will be or having any repeats but assuming that one.get(0).get(0) is valid? e.g. ["A","B","C",...] ["1","2",...] ..., ["A","B","C",...] ["8","5","12","7",...] .... I'm using Java in my project currently but an any algorithm that works I can convert over myself. I apologize if this is not clear, I'm having a hard time putting it into words which is probably part of why I can't think of a solution.
I know two solutions to this, the recursive and the non recursive. Here's the non recursive (similar to the answer at How to get 2D array possible combinations )
1) Multiply the length of every array together. This is the number of possible combinations you can make. Call this totalcombinations.
2) Set up an int[] array called counters. It should be as long as the number of arrays, and all initialized to 0.
3a) For totalcombinations times, concatenate counter[0]th entry in arrays[0], the counter[1]th entry in arrays[1]... etc and add it to the list of all results.
3b) Then set j = 0 and increment counters[j]. If this causes counters[j] > arrays[j].length, then counters[j] = 0, ++j and increment the new counters[j] (e.g. repeat 3b)) until you do not get such an overflow.
If you imagine counters as being like the tumblers of a suitcase - when you overflow the first digit from 9 to 0, the next one ticks over - then you should get the strategy here.
So here I am with this simple question
Consider these two for cycles and please
explain to me if there's any difference
between the two ways of writing
method 1 :
for(i=(max-1) ; i>=0 ; i--){ do-some-stuff }
method 2 :
for(i=max ; i>0 ; i--) { do-some-stuff }
the reason I'm asking this is because today at school
while we were seeing some Java functions, there was
this palindrome method wich would use as max the
length of the word passed to it and the method used
to cycle trough the for was the first, can anyone
clarify me why the person who writed that piece of
code prefeered using that method ?
Yes, there's a big difference - in the version, the range is [0, max-1]. In the second version, it's [1, max]. If you're trying to access a 0-based array with max elements, for example, the second version will blow up and the first won't.
If the order in which the loop ran didn't matter, I'd personally use the more idiomatic ascending sequence:
for (int i = 0; i < max; i++)
... but when descending, the first form gives the same range of values as this, just in the opposite order.
Both the loops will iterate max times. But the ranges would be different:
First loop's range would be max - 1 to 0 (both inclusive)
Second second loop's range would be max to 1.
Therefore, if you are using i as an array index, or doing some work which is a function of i , dependent of i, then it will create problems for the terminal values (for example 0 is considered in the first one, where as not by the second one). But if you simply want to iterate the loop max nos of times , and do some work which is independent of the value of i, then there is no difference.