Please help me solve my Java homework about arrays - java

Problem Statement:
Given an array of ints, compute if the array contains somewhere a value followed in the array by that value times 10. We'll use the convention of considering only the part of the array that begins at the given index.The initial call will pass in index as 0.
Examples:
public boolean array220(int[] nums, int index)
array220({1, 2, 20}, 0) → true
array220({3, 30}, 0) → true
array220({3}, 0) → false**
I'm stuck with the problem with no approach to solve it.

for (int i = index; i < nums.length - 1; i++)
if (nums[i] * 10 == nums[i + 1]) return true;
return false;

I'll give you some psuedo code to work with.
Let `nums` be my array
Let `i` be the starting index
Let `index` be `i + 1`
for all indices < array's length, iterate
Let currNum be `array[index - 1]`
if currNum times 10 equals `array[index]`
return true
increment index
return false because we found no numbers that we true

I'm not going to give you the answer as a Java program, since a number of folks have already done that.
When in doubt, try writing out the program in English (or any other native tongue). If you can't write it out in complete detail, write out what you can, and then refine in pieces.
Given an array of ints, compute if the array contains somewhere a value followed in the array by that value times 10. We'll use the convention of considering only the part of the array that begins at the given index.The initial call will pass in index as 0.
What do we know here? We have an array and a starting index. So, what do you want to do? Maybe that's a bit complicated, so if we were doing it by hand, how would you start?
Look at the first element of the array (where "first" is the starting index)
Look at the next element of the array and divide it by 10
Look at the results from steps #1 and #2. Are they the same?
If they are, return true
If they are not, start back again at step #1, but look at the following elements instead
Then refine that further:
Set the current index to be the starting index
For each element of the array, from the current index through the end:
Get the following element and divide by 10
Are the two numbers equal? If so, we're done, return true
If not, increment the current index and repeat
You may notice that there is a small issue with step #2: You don't want to loop all the way to the end. Because if you do that, there won't be any "next" element to compare it to. So really you want to loop to the second-to-last element.
Continue refining. At some point you can translate directly to Java or whatever programming language you want. (If you can't do this last step, you need to add an additional step 0: Learn the programming language first)

Recursive answer just for the hell of it... also I wouldn't post this is there weren't already valid answers. Make an attempt and post what you tried.
public boolean array220(int[] nums, int index){
if(index >= nums.length - 1)
return false;
if(nums[index] * 10 == nums[index + 1]){
return true;
} else {
return array220(nums, ++index);
}
}

Related

Correct runtime analysis on a Bubblesort-algorithm

Hey I did a runtime analysis on Bubblesort and I wanted to ask you if there were any mistakes since I was not sure at a certain point
heres an extract of the algorithm:
boolean sorted = false;
while(!sorted)
{
int a = 0;
int b = 1;
sorted = true;
while(a < sortArray.length && b < sortArray.length)
{
if(sortArray[a].getWertigkeit() < sortArray[b].getWertigkeit())
{
Karte tmp1 = sortArray[a];
Karte tmp2 = sortArray[b];
sortArray[a] = tmp2;
sortArray[b] = tmp1;
sorted = false;
}
a++;
b++;
}
}
So the problem I got is in the first while-loop, I solved it as following:
Best Case: In the best Case the sorted never gets set back to the false (through the if(..){..}) so it only goes once through the loop;
So the runtime is, if I am not wrong, 2*2n*1 = 4n => O(n) for the best Case;
Worst Case:In the worst Case the variable sorted gets set on false everytime the loop starts, as far as I know, so it needs another "n" comparisons so the runtime should be: n*2n*1 = 2n^2 => O(n^2)
I am really not sure if my thoughts about the while(!sorted) are correct or if the runtime makes any sense (since the big o notation seems fine, but im not sure about the precise runtime)
I really hope that my problem is relatable and I look forward to hear from you.
Thx already
Your analysis of the best-case runtime of O(n) is correct. Nice job!
For the worst-case, you need to be a little bit more precise. You're right that every time the flag gets reset you have to make another pass over the array to get it more sorted than before, so you know it's going to be O(n) times the number of times the loop runs. What you haven't yet done in your analysis is talk about how many times that loop can run before everything is going to end up sorted.
One observation you can make about bubble sort is that after the first pass over the array, the largest element is guaranteed to be in the last position - can you explain why? After the second pass, the second-largest element is guaranteed to be in the second-to-last position - again, can you explain why? Based on this pattern, can you argue why the number of times the outer loop runs is at most O(n)?

Double Recursion in one method Java

I am pretty sure that I thoroughly understand how the methods with only one recursion work.
Ex) calculating factorial
public int factorial(int n){ //factorial recursion
if(n==0){
return 1;
}
else{
return n*factorial(n-1);
}
}
For these methods, I can even picture what's going on in the stacks and what values are being returned at each stack level.
But Whenever, I encounter methods with Double Recursions, the nightmare begins.
Below is a recursion problem with double recursions from coding bat.
Ex) Given an array of ints, is it possible to choose a group of some of the ints, such that the group sums to the given target? If yes, true. If no, false.
You use 3 parameters; starting index start, An int Array nums, target int value target.
Below is the solution for this problem.
public boolean groupSum(int start, int[] nums, int target) {
if (start >= nums.length) return (target == 0);
if (groupSum(start + 1, nums, target - nums[start])) return true;
if (groupSum(start + 1, nums, target)) return true;
return false;
}
My take to understand this solution is this. Say I was given an array {2,4,8} with starting index = 0, and target value 10. So (0,{2,4,8},10) goes in through the method, the function gets re-called at
if (groupSum(start + 1, nums, target - nums[start])) return true;
so it becomes (1,{2,4,8},8) and it does over and over until start index hits
3. when it hits 3. The stack at the last level(?) goes to the second recursive call. And this is where I start losing track of what's happening.
Can anybody break this down for me? And when people use double recursion,(I know it's very inefficient and in practice, almost no one uses it for its inefficiency. But just in an attempt to understand it.)can they actually visualize what's going to happen? or do they just use it hoping that the base case and recursion would work properly? I think this applies generally to all the ppl who wrote merge sort, tower of hanoi alogrithm etc..
Any help is greatly appreciated..
The idea of a double recursion is to break the problem into two smaller problems. Once you solve the smaller problems, you can either join their solutions (as is done in merge sort) or choose one of them - which is done in your example, which only requires the second smaller problem to be solved if solving the first smaller problem didn't solve the full problem.
Your example tries to determine if there is a subset of the input nums array whose sum is the target sum. start determines which part of the array is considered by the current recursive call (when it's 0, the entire array is considered).
The problem is broken to two, since if such a subset exists, it either contains the first element of the array (in which case the problem is reduced to finding if there's a sub-set of the last n-1 elements of the array whose sum is target minus the value of the first element) or doesn't contain it (in which case the problem is reduced to finding if there's a sub-set of the last n-1 elements of the array whose sum is target).
The first recursion handles the case where the subset contains the first element, which is why it makes a recursive call that would look for the target sum minus the first element in the remaining n-1 elements of the array. If the first recursion returns true, it means that the required subset exists, so the second recursion is never called.
The second recursion handles the case where the subset doesn't contain the first element, which is why it makes a recursive call that would look for the target sum in the remaining n-1 elements of the array (this time the first element is not subtracted from the target sum, since the first element is not included in the sum). Again, if the second recursive call returns true, if means that the required subset exists.
Well if you want to visualize it, usually it's kind of like a tree. You first follow one path through the tree until the end, then step one back and pick a different path (if possible). If there is none or you are happy with your result you just take another step back and so on.
I don't know if this helps you but when I learned recursion, it helped to just think of my method as already working.
So I thought: Great, so basically my method is already working, but I can't call it with the same parameters and have to make sure I return the right value for these exact parameters by using different ones.
If we take that example:
At first we know that if we have no numbers to look at left, then the answer depends on if the target is 0. (first line)
Now what do we do with the rest? Well... we'd need to think about it for a moment.
Just think about the very first number. Under what circumstances is it part of the solution? Well that would be if you could create target-firstnumber with the rest of the numbers. Because then when you add firstnumber, you reach target.
So you try to see if that's possible. If so, it's solvable. (second line)
But if not, it's still possible that the first number just isn't important for the solution. So you have to try again to build the target without that number. (third line)
And that's basically all there is to this.
Of course to think like this you need two things:
1. You need to believe that your method already works for other parameters
2. You need to make sure your recursion terminates. That's the first line in this example but you should always think about if there is any combination of parameters that will just create an endless recursion.
Try to understand it like this: Recursion can be rewritten as a while-loop. where the condition of the while is the negation of the stop-condition of the recursion.
As already said, there is nothing called double recursion.

Sorted Array Distinct Values Sum to Target

I am currently working on this coding problem for class.
Given a sorted array of n distinct values as well as a target value T, determine in O(n) time whether or not there exist two distinct values in the array that sum to T. (For example, if the array contained 3, 5, 6, 7, and 9 and T = 14, then the method you are to write should return true, since 5+9 = 14. It should return false if for the same array of values T = 17.)
So, initially, I just wrote the problem with a nested linear search approach which obviously results in a O(n^2) runtime to establish a baseline to simplify from, however, I have only been able to, so far, simplify it to O(n log(n)). I did this by creating a new array made up of the differences of the Target - array[i] and then comparing the new array to the original array using a binary search nested within a loop that linearly goes up the new array.
I am not asking for an answer but rather a hint at where to look to simplify my code. I feel like the fact that the array is sorted is important in getting it down to O(n) but not sure how to go about doing it.
Thanks for your time!
Imagine you have two pointers (s, e) wich set on start and end of you array.
If you will move them in opposite direction (with specific algorithm) and look at the summ of elements you will see that moving one pointer increase summ and moving other decrease.
Onli thing you need is find balance.
If it doesnt help. Ask for next tip.
Some tips/steps:
1 - Start the iteration by the array[i], which is the nearest lower value from T
2 - Move another pointer to the array[0]
3 - Sum both values and compare with T
4 - If bigger or if lower, do appropriate moving in the pointers and repeat the step 3
A Hint:
Something like Binary Search, start with middle (compare with middle)
we have startindex = 0, endindex = N-1
while(some condition){
middleindex = endindex - startindex / 2, middle = array[middleindex]
if T - array[middleindex] > middle, startindex = middleindex
if T - array[middleindex] < middle, endindex = middleindex
}
It will do the task in O(log(n)) :D

algorithm for finding longest sequence of the same element in 1D array-looking for better solution

I need to find algorithm which will find the longest seqeunce of element in one
dimension array.
For example:
int[] myArr={1,1,1,3,4,5,5,5,5,5,3,3,4,3,3}
solution will be 5 because sequnece of 5 is the longest.
This is my solution of the problem:
static int findSequence(int [] arr, int arrLength){
int frequency=1;
int bestNumber=arr[0];
int bestFrequency=0;
for(int n=1;n<arrLength;n++){
if(arr[n]!=arr[n-1]){
if(frequency>bestFrequency){
bestNumber=arr[n-1];
bestFrequency=frequency;
}
frequency=1;
}else {
frequency++;
}
}
if( frequency>bestFrequency){
bestNumber=arr[arrLength-1];
bestFrequency=frequency;
}
return bestNumber;
}
but I'm not satisfied.May be some one know more effective solution?
You can skip the some number in the array in the following pattern:
Maintain a integer jump_count to maintain the number of elements to skip (which will be bestFrequency/2). The divisor 2 can be changed according to the data set. Update the jump_count every time you update the bestFrequency.
Now, after every jump
If previous element is not equal to current element and frequency <= jump_count, then scan backwards from current element to find number of duplicates and update the frequency.
e.g. 2 2 2 2 3 3 and frequency = 0 (bold are previous and current elements), then scan backwards to find number of 3's and update the frequency = 2
If previous element is not equal to current element and frequency > jump_count, scan for scan for every element to update the frequency and update the bestFrequency if needed.
e.g. 2 2 2 2 2 3 3 and frequency = 1 (bold are previous and current elements), scan for number of 2's in this jump and update the frequency = 1 + 4. Now, frequency < bestFrequency, scan backwards to find number of 3's and update the frequency = 2.
If previous element = current element, scan the jump to make sure it is continuous sequence. If yes, update the frequency to frequency + jump_count, else consider this as the same case as step 2.
Here, we will consider two examples:
a) 2 2 2 2 2 2 (bold are previous and current elements), check if the jump contains all 2's. Yes in this case, so add the jump_count to frequency.
b) 2 2 2 2 3 2 (bold are previous and current elements), check if the jump contains all the 2's. No in this case, so considering this as in step 2. So, scan for number of 2's in this jump and update the frequency = 1 + 4. Now, frequency < bestFrequency, scan backwards to find number of 2's(from the current element) and update the frequency = 1.
Optimization: You can save some loops in many cases.
P.S. Since this is my first answer, I hope I am able to convey myself.
Try this:
public static void longestSequence(int[] a) {
int count = 1, max = 1;
for (int i = 1; i < a.length; i++) {
if (a[i] == a[i - 1]) {
count++;
} else {
if (count > max) {
max = count;
}
count = 1;
}
}
if (count> max)
System.out.println(count);
else
System.out.println(max);
}
Your algorithm is pretty good.
It touches each array element (except the last) only once. This puts it at O(n) runtime which for this problem seems like the best worst case runtime you can get and is a pretty good worst case runtime as far as algorithms go.
One possible suggestion is when you find a new bestFrequency and n+bestFrequency > arrayLength you can break out of the loops. This is because you know a longer sequence cannot be found.
The only optimization that seems possible is:
for(int n=1;n<arrLength && frequency + (arrLength - n) >= bestFrequency;n++){
because you don't need to search any further one you can't possible exceed the best frequency with the number of elements remaining (probably possible to simplify that even further given a little more thought).
But as others point out, you're doing a O(n) search on n elements for a sequence - there's really no more efficient algorithm available.
I was thinking this must be an O(n) problem, but now I'm wondering if it doesn't have to be, that you could potentially make it O(log n) using a binary search (I don't think what #BlackJack posted actually works quite right, but it was inspiring):
Was thinking something like keep track of first, last element (in a block, probably a recursive algorithm). Do a binary split (so middle element to start). If it matches either first or last, you possibly have a run of at least that length. Check if the total length could exceed the current known max run. If so, continue, if not break.
Then repeat the process - do a binary split of one of those halves to see if the middle item matches. Repeat this process, recursing up and down to get the maximum length of a single run within a branch. Stop searching a branch when it can't possibly exceed the maximum run length.
I think this still comes out to be an O(n) algorithm because the worth-case is still searching every single element (consider a max length of 1 or 2). But you limit to checking each item once, and you search into the most-likely longest branches first (based on start/middle/end matches), it could potentially skip some fairly long runs. A breadth-first rather than depth-first search would also help.

Questions about recursion, trying to schedule the max number of events

I'm working with recursion trying to become better at with it. My current activity is trying to program a recursive method that generates the maximum number of events one could schedule. Heres my method so far:
public int maxEvents(int n, int[] Start) {
if(n<=0) return 0;
if(n==1) return 1;
else return maxEvents(n-1, Start) + maxEvents(Start[n]-1, Start);
}
Basically my main method passes maxEvents an int n, which is the last Event. So say I have 4 events (1-4) then n would be 4. The next part is an array who's value at the index is the time the event starts, and the index itself is when the event ends.
The preconditions are:
n >= 0
days and conventions go from 1 to n
Event n ends at (and includes) day n and begins at Start[n]
Begin[0] is unused
For all i from 1 to n, Begin[i] <= i ( Convention i can't have a later beginning day than ending day, of course.)
At the end my method is supposed to return:
The maximum number of conventions you can host if you must select only from conventions 1 through n. (This set is empty if n = 0)
Some example input / outputs:
n = 3 Begin[1]=1 Begin[2]=1 Begin[3]=3
maxEvents=2
Or:
n = 5 Begin[1]=1 Begin[2]=1 Begin[3]=2 Begin[4]=3 Begin[5]=4
maxEvents=3
My two recursive calls should count the maximum number without inviting n, you can then chose from 1 to n-1. And count the maximum number inviting n, noting that Begin[n]-1 is the last convention that does not conflict with the beginning of convention n. Then I could take the max of the two, and return that.
I've tried using different if statements, saying something like:
if("recursion call 1">"recursion call 2"){
return "recursion call 1";
}
And using something like "maxEvents(Start[n]-1, Start)" as one of my recursive calls (like used in my above code) however its not returning the correct values, like the ones I listed above. All in all I'm having trouble with the concept of recursion, and I know something is wrong with my recursive calls, so if someone could point me in the right direction that'd be great. Thanks!
Does this work?
return Math.max(maxEvents(n-1, Start), 1 + maxEvents(Start[n]-1, Start))
The idea is that you are splitting into two mutually exclusive cases: one where the nth event is not included and another where nth event is included. Out of the two, you have to select the bigger. So adding the two is not correct - taking the max is the right way. But you have to also add a 1 to the second option to account for including the nth event.

Categories