Finding the Largest through Reduce and Conquer - java

I have a problem I need help solving, basically, the problem asks me to use a Reduce and Conquer Algorithm to find the largest element.
Problem Description: Return the largest element in a non-empty array of integers. We'll use the convention of considering only part of the array that begins at a given index and ends at another. In this way, a recursive call can work through any part of the array. The initial call will pass in index 0 and the index to the last element.
Some of the things I thought of was to approach this problem using recursion but I been struggling with recursion as it is a concept I don't have a full grasp of. Can any one point me into the right direction? Any ideas or suggestions are welcomed. Thank you.
Here is what I thought of so far:EDIT: Updated code
public int max(int[] nums, int begin, int end) {
int maxVal = begin;
if (begin == end) return nums[0];
else if(begin < end){
maxVal = max(nums, begin+1, end);
if (maxVal > nums[end-begin]) return maxVal;
else return nums[end-begin];
}
return maxVal;
}
This would be the outputs:
max([2, 1, -2, 3, 8], 0, 4) → 8
max([6, 2, -4], 0, 2) → 6
max([3], 0, 0) → 3

Do it as follows:
public class Main {
public static void main(String[] args) {
// Tests
System.out.println(max(new int[] { 2, 1, -2, 3, 8 }, 0, 4));
System.out.println(max(new int[] { 2, 1, -2, 8, 3 }, 0, 4));
System.out.println(max(new int[] { 2, 1, 8, -2, 3 }, 0, 4));
System.out.println(max(new int[] { 2, 8, 1, -2, 3 }, 0, 4));
System.out.println(max(new int[] { 8, 2, 1, -2, 3 }, 0, 4));
}
static int max(int[] nums, int begin, int end) {
if (begin >= end) {
return nums[end];
}
if (nums[begin] > nums[end]) {
return max(nums, begin, end - 1);
} else {
return max(nums, begin + 1, end);
}
}
}
Output:
8
8
8
8
8

Related

How to write a recursive boolean function to find if an array is splitable from i to length - 1 into a two segment sum so that it is equal to diff

public static boolean isSplitable(int[] arr, int diff, int i)
no loops or helper methods i need to check if arr[i...arr.length - 1] has a two section sum that is equal to diff
for example i have: diff = 1, i = 2, arr = {3, 4, 1, 1, 2, 0, 1, 1, 3} it returns true because sum of {1, 1, 2, 0}(4) minus the sum of {1, 1, 3}(5) equals diff(1).
i have tried to think of ways to even sum arr without a loop only thing i came up with is adding it to diff but then i lose my original diff plus i dont know the amount of elements so i can add "or" in my return statement so now im out of ideas.
I'm assuming your restrictions are no loops and no library usage. You probably need some kind of additional functions. Moreover, I assume the difference check shall use absolute values, i.e. it does not matter if the first or second sum is smaller, as long as the difference matches (-1 or 1 in your example). That being said, a first approach could look like this:
import org.junit.jupiter.api.Test;
import static java.util.Arrays.copyOfRange;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class RecursiveSplitTest {
#Test
public void testIsSplitable() {
{
int[] array = {3, 4, 1, 1, 2, 0, 1, 1, 3};
assertTrue(isSplitable(array, 1, 2));
}
{
int[] array = {3, 4, 1, 1, 1, 0, 4, 1, 3};
assertTrue(isSplitable(array, 1, 4));
}
{
int[] array = {3, 4, 1, 1, 1, 0, 4, 1, 3};
assertFalse(isSplitable(array, 1, 7));
}
{
int[] array = {3};
assertFalse(isSplitable(array, 1, 1));
}
}
public static boolean isSplitable(int[] array, int diff, int start) {
if (start < 0 || start > array.length - 2) {
System.out.println("Not possible due to initial parameters");
return false;
}
return doSplitableRecursive(copyOfRange(array, start, array.length), diff, 0);
}
private static boolean doSplitableRecursive(int[] array, int diff, int start) {
if (start + 1 >= array.length) {
System.out.println("Could not find it");
return false;
}
int[] left = copyOfRange(array, 0, start + 1);
int[] right = copyOfRange(array, start + 1, array.length);
int leftSum = sum(left, 0);
int rightSum = sum(right, 0);
System.out.println("leftSum: " + leftSum);
System.out.println("rightSum: " + rightSum);
if (leftSum + diff == rightSum || leftSum - diff == rightSum) {
System.out.println("Found match for cut at start + " + (start + 1));
return true;
}
return doSplitableRecursive(array, diff, start + 1);
}
private static int sum(int[] array, int current) {
if (array.length == 0) {
return current;
}
return sum(copyOfRange(array, 1, array.length), current + array[0]);
}
}
The key is to systematically divide the array in two pieces, beginning at start and checking the sum of each piece against the difference. Then cutting one index further and repeating the process if it did not match. Finally, you have to exit with false if there are no more elements left.
It is a little rough around the edges. Feel free to improve it and fix possibly remaining bugs. The print statements are for debugging purposes. Of course, one could argue JUnit and java.util.Arrays are library functions. These can be replaced with a little bit of extra effort if needed.

Google Foobar challenge Minion Work Assignment Java test cases not passing

I have tried solving this problem using Java and for some reason only 2 out of 9 test cases pass but locally all my test cases pass. I am 99% positive that there is some issue with Google Foobar Java test cases for this challenge. Did someone encounter this and if yes, what did you do to solve it?
Question was...
Write a function called solution(data, n) that takes in a list of
less than 100 integers and a number n, and returns that same list
but with all of the numbers that occur more than n times removed
entirely.
The returned list should retain the same ordering as the original
list - you don't want to mix up those carefully-planned shift
rotations! For instance, if data was [5, 10, 15, 10, 7] and n was 1,
solution(data, n) would return the list [5, 15, 7] because 10 occurs
twice, and thus was removed from the list entirely.
-- Java cases --
Input:
Solution.solution({1, 2, 3}, 0)
Output:
Input:
Solution.solution({1, 2, 2, 3, 3, 3, 4, 5, 5}, 1)
Output:
1,4
There are 6 more test cases that are hidden.
Below is the solution I created.
public class MinionShift {
public static int[] solution(int[] data, int n) {
if(n<1)
return new int[0];
if(data.length < 1)
return data;
Map<Integer, Integer> map = new HashMap<>();
for(int d: data) {
map.put(d, map.getOrDefault(d, 0) + 1);
}
return Arrays.stream(data).filter(c->map.containsKey(c) && !(map.get(c)>n)).toArray();
}
}
Test cases that I have tried...
[{1, 2, 3}, 0]
[{1, 2, 2, 3, 3, 3, 4, 5, 5}, 1]
[{1, 2, 2, 3, 3, 3, 4, 5, 5}, 10]
[{1, 2, 2, 3, 3, 3, 4, 5, 5}, -1]
[{}, 5]
[{1, 1, 1, 1, 1}, 5]
[{101, 102, 103, 104, 105}, 5]
Edit...
I tried a Java stream based solution as follows but unfortunately the challenge went away as I submitted a Python solution. But I am posting it here anyways.
public class MinionShift {
public static int[] solution(int[] data, int n) {
if(n<1)
return new int[0];
if(data.length < 1)
return data;
return Arrays.stream(data).filter(d->Arrays.stream(data).filter(i->i==d).count()<=n).toArray();
}
}
This is how I got it to work, you have to work backwards with the array. You need to create another array to check for duplicates to remember them.
public static int[] solution(int[] data, int n){
if(n < 1){
return new int[0];
}
if(data.length < 1){
return data;
}
List<Integer> a = Arrays.stream(data).boxed().collect(Collectors.toList());
for(int i = a.size()-1; i > -1; i--){
ArrayList<Integer> t = new ArrayList<>();
for(int j = 0; j < a.size(); j++){
if(a.get(j) == a.get(i)){
t.add(j);
}
}
if(t.size() > n){
for(int j = t.size()-1; j > -1; j--){
a.remove((int) t.get(j));
}
i -= t.size()-1;
}
}
data = new int[a.size()];
int c = 0;
for(int d : a){
data[c] = d;
c++;
}
return data;
}

Moving array elements to the left

Writing a code that shifts array elements left by an int n (keyboard input) and replaces space with zeros.
Ex. int[] data = { -1, 1, 3, 7, 5} and I want to see { 3, 7, 5, 0, 0}.
Suppose I have:
public static void shiftLeft( int[] data, int n )
{
System.arraycopy( data, 1, data, 0, data.length - 1 );
data[data.length - 1] = 0;
}
Any quick help would be great.
You were close, but your srcPos argument should be n and the length argument should be data.length - n. You can then use the overloaded Arrays#fill method that accepts a start/end index to fill the rest of the array with 0:
public static void shiftLeft(int[] data, int n) {
System.arraycopy(data, n, data, 0, data.length - n);
Arrays.fill(data, data.length - n, data.length, 0);
}
Testing this with your example input yields the following:
int[] data = { -1, 1, 3, 7, 5};
shiftLeft(data, 2);
System.out.println(Arrays.toString(data));
Output:
[3, 7, 5, 0, 0]

Quicksort with pivot as middle instead of 1st index sorts incorrectly

Just a quick one. I'm struggling to make this code work when the pivot is the middle value. I know it works when the pivot is the leftmost value. Any help please?
public class Quicksort {
public static void main(String[] args) {
int[] numbers = { 1, 3, 6, 2, 2, 2, 4, 8, 4 };
System.out.println(Arrays.toString(numbers));
sort(numbers);
System.out.println(Arrays.toString(numbers));
}
public static void sort(int[] number) {
quicksort(number, 0, number.length - 1);
}
public static void quicksort(int[] array, int left, int right) {
int lowest = left, highest = right;
if (right - left >= 1) {
int pivot = array[(left + right) / 2];
// works when pivot = array[left];
while (lowest < highest) {
while (array[lowest] <= pivot && lowest <= right && highest > lowest) {
lowest++;
}
while (array[highest] > pivot && highest >= left && highest >= lowest) {
highest--;
}
if (highest > lowest) {
swap(array, lowest, highest);
}
}
swap(array, left, highest); // problem area?
quicksort(array, left, highest - 1);
quicksort(array, highest + 1, right);
} else {
return;
}
}
public static void swap(int[] array, int index, int index1) {
int temp = array[index];
array[index] = array[index1];
array[index1] = temp;
}
}
the output for this is
[1, 3, 6, 2, 2, 2, 4, 8, 4] //unsorted
[2, 2, 2, 1, 3, 4, 4, 6, 8] //wrongly "sorted"
Following the suggestion by Peter Lawrey, I first observed that your program sorts two numbers correctly. Then tried with three:
int[] numbers = { 1, 3, 6 };
After your while loop you have
left = 0
lowest = 2
highest = 1
In this case your comment problem area? seems correct sonce you are swapping the numbers 1 and 3, thus bringing them out of order.
In general, after your loop you know that array[left..lowest - 1] are <= pivot and array[highest + 1..right] are > pivot, but if lowest == highest I don’t think you can be sure whether array[highest] belongs in one part or the other, so you don’t know whether to swap it into the left part.
By the way, you have the same problem with int pivot = array[left];. Try int[] numbers = { 3, 1, 6 };, the result is [3, 1, 6].

Find the smallest missing number with Duplicates [duplicate]

This question already has answers here:
Find the Smallest Integer Not in a List
(28 answers)
Closed 8 years ago.
This is an interview question, but I couldn't solve it in time, so posting it here:
Given a sorted array of n integers where each integer is in the range from 0 to m-1 and m > n. Find the smallest number that is missing from the array.
Examples
Input: {0, 1, 2, 6, 9}, n = 5,m = 10
Output: 3
Input: {4, 5, 10, 11}, n = 4, m = 12
Output: 0
The code for this is as follows:
int findFirstMissing(int array[], int start, int end) {
if(start > end)
return end + 1;
if (start != array[start])
return start;
int mid = (start + end) / 2;
if (array[mid] > mid)
return findFirstMissing(array, start, mid);
else
return findFirstMissing(array, mid + 1, end);
}
Now, the question is that input array can have duplicates also:
input = [0, 1, 1, 2, 3, 3, 4, 5, 5, 7]
output = 6
How do I solve it efficiently? What kind of optimizations can be applied?
It can be easily proved that you have to this in O(n) time, as you can't distinguish without checking every single value two tables:
1,2,_3_,4,5,7
and
1,2,_2_,4,5,7
This solution works in O(N) time and uses O(1) additional memory:
public class Test {
public static void main(String[] args) {
int m = 5;
int[] data = new int[] {0, 1, 1, 2, 3, 3, 4, 5};
int current = 0;
for (int i = 0; i < data.length; ++i) {
if (current == data[i]) {
current++;
}
}
if (current >= m) {
System.out.println("All is here");
} else {
System.out.println(current);
}
}
}
Note: n is actually ignored, I used data.length instead.
Solution
public static void main(String[] args) {
Collection<Integer> input = new LinkedList<Integer>(Arrays.asList(10, 9, 7, 6, 5, 4, 3, 2, 1));
NavigableSet<Integer> sortedOriginal = new TreeSet<Integer>(input);
NavigableSet<Integer> numbers = new TreeSet<Integer>();
for(int i=sortedOriginal.first();i<=sortedOriginal.last();i++){
numbers.add(i);
}
for(Integer x : numbers){
if(!sortedOriginal.contains(x)){
System.out.println(x);
break;
}
}
}

Categories