boolean method with array argument - java

I am trying for too long to figure out this exersies but I am stuck here. I need to write a boolean method that will an array as argument and should return true if numbers in array are in decreasing order. Bu any time that I am trying I am having the same value or errors. Here is my code:
public class Question1c{
public static void main (String[] args){
int[] arr = {1, 9, 3, 4, 5, 6};
boolean product = isDecreasing(arr);
System.out.println(product);
}
public static boolean isDecreasing (int[] numbers){
int first = numbers[0];
for (int i : numbers){
if(first <= i){
first = i;
return true;
}
//else{
// return false;
//}
}return false;
}
}

The problem in your code is that you cannot return true until after you went through the entire array. However, you can return false as soon as you detect an "inversion" - i.e. a situation when the number that follows the one you've seen before is greater than the prior number.
You are reasonably close to a working solution - you need to remove return true, uncomment the else, and change the final return false to return true.
To make your code more readable, rename first to prior. Also consider changing the "foreach" version of the for loop to a regular for loop that skips the initial element of the array. This would let you detect decreasing order, as opposed to non-increasing, which you currently detect.

Not sure I understand, but wouldn't this solve your issue?
public class Question1c{
public static void main (String[] args){
int[] arr = {1, 9, 3, 4, 5, 6};
boolean product = isDecreasing(arr);
System.out.println(product);
}
public static boolean isDecreasing (int[] numbers){
for (int i = 0; i < numbers.Length; i++){
if (i == 0)
continue;
if (numbers[i - 1] >= numbers[i])
return false;
}
return true;
}
}
You're essentially just aiming to check that the previous item in the array isn't greater than or equal to the current item in the array, aren't you?

You initialize first with numbers[0] this causes several problems:
An empty array throws IndexOutOfBoundsException
the first check automatically passes (numbers[0] <= numbers[0])
you best check the length of numbers for 0 and use a "normal" for loop (using an index).
Your return values is also the negation of what it should be.

This might solve your issue.
public class Question{
public static void main (String[] args){
int[] arr = {1, 9, 3, 4, 5, 6};
boolean product = isDecreasing(arr);
System.out.println(product);
}
public static boolean isDecreasing (int[] numbers){
int first = numbers[0];
for (int i = 1; i < numbers.length ; i++) {
if (first <= numbers[i]) {
return false;
}
first = numbers[i];
}
return true;
}
}

Related

Combination Sum Debugging

I have written some code to try to solve this challenge, but its not working, i can't seem to figure out where it went wrong, i can find the answer online but that's not the point i'm trying to see why my code doesn't work.
question:
Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.
The same repeated number may be chosen from candidates unlimited number of times.
Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
[7],
[2,2,3]
]
this is what i have came up with:
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
helper(res,new ArrayList<Integer>(), candidates,target,0,0);
return res;
}
//current = current sum, we want it to be target
//start is index we are at and where the for loop starts
public void helper(List<List<Integer>> res, List<Integer> temp, int[] nums, int target, int current, int start){
if(start>=nums.length){
return;
}
if(current>=target){
if(current==target){
res.add(new ArrayList<>(temp));
}
temp.remove(temp.size()-1);
helper(res,temp,nums,target,current-nums[start],start+1);
return;
}
for(int i=start; i<nums.length; i++){
temp.add(nums[i]);
helper(res,temp,nums,target,current+nums[i],start);
}
}
}
explanation of my code:
so i am trying to use recursion backtracking here. i keep for looping an element in the array till the sum is >= target.if its >target i remove the last element since that made it bigger than target and try the other ones. if its = target i add it to result and i remove last element to try find more combinations.
but apparently i am getting error in this line:
temp.remove(temp.size()-1); //saying index out of bounds i am trying to remove when arraylist is empty
so it isnt running how i thought, because if the list is empty current should be 0 and it should even enter that if loop and should never be removed but it is and i am not sure why.
thanks.
The main issue if from trying to roll back the current variable value and call the helper method again from there in the if(current>=target) if statement. You can use the for loop to automatically do that for you and remove the added number after it returns. Then using the functions return to update the start value so that it will continue from where you left off will eliminate duplicates.
And because of the for loop num[i] will never go out of bounds so you dont have to worry about
if(start>=nums.length){
return;
}
This is the working version using your solution method
public static List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
helper(res,new ArrayList<Integer>(), candidates,target,0,0);
return res;
}
public static int helper(List<List<Integer>> res, List<Integer> temp, int[] nums, int target, int current, int start){
if(current>=target){
if(current==target){
res.add(new ArrayList<>(temp));
}
return start + 1;
}
for(int i=start; i<nums.length; i++){
temp.add(nums[i]);
start = helper(res,temp,nums,target,current+nums[i],start);
temp.remove(temp.size()-1);
}
return start;
}
Running the code:
public static void main(String []args){
List<List<Integer>> res = combinationSum(new int[] {2,3,6,7}, 7);
System.out.println(res);
}
Result:
[[2, 2, 3], [7]]
Try this.
static List<List<Integer>> combinationSum(int[] candidates, int target) {
int size = candidates.length;
List<List<Integer>> result = new ArrayList<>();
new Object() {
void search(int index, int sum, List<Integer> selected) {
if (index >= size) {
if (sum == target)
result.add(new ArrayList<>(selected));
} else {
int candidate = candidates[index];
List<Integer> nextSelected = new ArrayList<>(selected);
for (int nextSum = sum; nextSum <= target; nextSum += candidate, nextSelected.add(candidate))
search(index + 1, nextSum, nextSelected);
}
}
}.search(0, 0, new ArrayList<>());
return result;
}
and
int[] candidates = {2, 3, 6, 7};
int target = 7;
List<List<Integer>> result = combinationSum(candidates, target);
System.out.println(result);
result:
[[7], [2, 2, 3]]

Double natural order not working as expected

I'm trying to implement selection sort using generics. To do that I receive a comparator (Because I wanted to use the method Comparator#naturalOrder() while testing).
The problem is that when calling it with a Double array it does not work, but when calling it with an Integer array instead, it works.
Here is the selection sort implementation I made:
public static<V> void selectionSort(V[] arr, Comparator<V> cmp){
if (arr == null)
throw new IllegalArgumentException("Invalid array, can't be sorted");
int minIndex = -1;
for(int i = 0, j; i<arr.length; i++){
for (j = i; j<arr.length;j++){
if (minIndex == -1 || cmp.compare(arr[minIndex],arr[j])>0){
minIndex = j;
}
}
swap(arr, i, minIndex);
}
}
private static<V> void swap(V[] arr, int i, int j) {
V aux = arr[i];
arr[i]=arr[j];
arr[j]=aux;
}
Here is the test that's failing:
#Test
public void selectionSortDoubleTest(){
arrDouble = new Double[]{5.5,2.5,1.2,8.0};
SelectionSort.selectionSort(arrDouble, Comparator.naturalOrder());
Assert.assertArrayEquals(new Double[]{1.2,2.5,5.5,8.0}, arrDouble);
}
And here is the test that works:
#Test
public void selectionSortIntegerTest(){
arr = new Integer[]{2,5,7,1};
SelectionSort.selectionSort(arr, Comparator.naturalOrder());
Assert.assertArrayEquals(new Integer[]{1, 2, 5, 7},arr);
}
The weird part is that in the first test the arrays differ at position [1], so both start with 1.2, but then arrDouble[1] is 8.0 which doesn't make any sense.
The assertion error message I receive:
Arrays first differed at element [1];
Expected :2.5
Actual :8.0
minIndex must be reset to -1 at each iteration of the outer loop. Otherwise you swap the previously found min element with the new one. Using a debugger makes it quite easy to spot such mistakes.

Consecutive numbers in array list using boolean expressions

I'm having trouble executing this function in which it would print out "true" if there is 2 consecutive numbers in an array and "false"if not. The errors I get is that a boolean cannot be converted to an int and also in the last line of code what would I have to put inside the brackets for System.out.println()?
public class A1Q2 {
private static int hasTwoLengthRun(int[] array) {
for(int i=0; i < array.length; i++){
if(array[i+1] == array[i]){
return true;
}
else{
return false;
}
}
}
public static void main(String[] args) {
int[] array = new int[]{5, 16, 7, 35, -2, -9, 75};
System.out.println();
}
}
1)hasTwoLengthRun() should return a boolean and not an int as you return boolean values.
2) it has a broken logic as it returns false as soon as two elements of the array are not equals between.
You should return false only when you have iterated over all elements.
3) For the compiler the method doesn't return a value since you return a value only in the for. If you have a array with no element, you don't enter in the for and you return nothing. It is not legal.
4) you will get an ArrayIndexOutOfBoundsException with the for condition as the last iteration use a index out of the array.
Here is a code that should work :
private static boolean hasTwoLengthRun(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
if (array[i + 1] == array[i]) {
return true;
}
}
return false;
}
I see at least 3 problems here:
Return type of hasTwoLengthRun function should be boolean
You've incorrectly arranged return false statement - it should be invocated in the end of the method
You've incorrectly used array boundaries - you'll get exception trying to reach element out of array.
Here is the corrected code:
public class Test {
private static boolean hasTwoLengthRun(int[] array) {
for(int i=0; i < array.length - 1; i++){
if(array[i+1] == array[i]){
return true;
}
}
return false;
}
public static void main(String[] args) {
int[] array = new int[]{5, 16, 7, 35, -2, -9, 75};
System.out.println(hasTwoLengthRun(array));
}
}
You get an error, because you've written that your hasTwoLengthRun function returns int, while in your return statements you return true or false - a boolean-typed values.
Here:
private static int hasTwoLengthRun(...
says the method shall return an int. A number.
Then you return true/false. In java, those two types can not be interchanged.
So, change to:
private static boolean hasTwoLengthRun(...
Besides; your logic is wrong:
for(int i=0; i < array.length-1; i++){
if(array[i+1] == array[i]) {
return true;
}
}
return false;
is what you need instead; to A) avoid running over the length of your array and B) not returning with false when the first two elements are not matching your condition!

Sorting an array through my method error Java

I am new to programming and I need some help. I am supposed to make my own method checking if one array has a subsequence to another one. Meaning if the first array is {1, 2, 3, 4, 5} and the second one is {1, 2, 3} the second one is a subsequence of the first. However if the first is {1, 2, 3, 4, 5} and the second is {1, 4, 5} it is not a subsequence, so the second has to be in order as well.
I have tried to do it this way through strings:
private static boolean subs(int[] array, int[] subsequence) {
String a = Arrays.toString(array);
String b = Arrays.toString(subsequence);
boolean c = false;
if (a.equals(b)) {
return true;
}
for (int i = 0; i < a.length(); i++) {
if (!(b.equals(a.substring(i, b.length() + i)))) {
c = false;
} else {
c = true;
break;
}
}
if (c == true) {
return true;
} else {
return false;
}
}
However I get 3 errors, here is the printscreen :
And here is how I am testing the method:
int[] fArray = { 1, 2, 3, 4, 5 };
int[] tempArray = { 2, 3, 4 };
System.out.println(subs(fArray, tempArray));
I know I probably made a lot of mistakes, so hit me with it.
Here:
for (int i = 0; i < a.length(); i++) {
if (!(b.equals(a.substring(i, b.length() + i)))) {
Your outer loop condition makes sure that i stays smaller than a.length().
But then you try to take a substring within a that goes for b.length()+i!
In other words: for any b.length() > 0 ... that code will always try to fetch characters beyond the end of a.
And there is also a bug in your result handling - it seems very much possible that you assign
c = true;
at some point; to later overwrite that with
c = false;
In other words: your code forgets that he found a match! The much easier solution: when hitting the true case, just return true there! And if you don't return within the loop; you just return false in the end.
Finally: although it seems like a cool idea to turn your arrays into strings ... that doesn't really buy you anything. You are still doing the work of going through the first array and checking if the second is in there. Writing code that does that directly on the provided arrays ... would not be much different from what you got there with your "string detour".
Edit: when using multiple returns in a method, you simply have to make sure that any possible path has a return statement. In your case:
boolean subs(... {
if equal strings
return true
for i as index in a
if a.substring equals b
return true
return false
The issue is that fArray as String has more chars than tempArray as string, so when you start to compare char by char from a to b, is a given point where the index is going beyond the size of b and then you get the exception
Your problem line is: if (!(b.equals(a.substring(i, b.length() + i))))
Why?
Lets assume your a.length() is equals 6 and b.length() is equals 2 now your looping for (int i = 0; i < a.length(); i++) with i going from 0 to 5.
Now lets say your loop executed 3 times and i is equals 4now.
Now when you call a.substring(4, b.length() + 4) with b.length() == 2 => a.substring(4, 6) but your string only goes from 0 to 5
The simplest way to do this would be to use Collections.indexOfSubList:
private static boolean subs(int[] array, int[] subsequence) {
return Collections.indexOfSubList(toList(array), toList(subsequence)) >= 0;
}
private static List<Integer> toList(int[] array) {
List<Integer> list = new ArrayList<>(array.length);
for (int num : array) {
list.add(num);
}
return list;
}
//*******************************************************************
// NOTE: please read the 'More Info' tab to the right for shortcuts.
//*******************************************************************
import java.lang.Math; // headers MUST be above the first class
import java.util.Arrays;
// one class needs to have a main() method
public class HelloWorld
{
// arguments are passed using the text field below this editor
public static void main(String[] args)
{
int[] fArray = { 1,2,3,4,5 };
int[] tempArray = { 2,3,4 };
System.out.println(subs(fArray, tempArray));
}
private static boolean subs(int[] array, int[] subsequence) {
String a = Arrays.toString(array);
String b = Arrays.toString(subsequence);
boolean c = false;
if (a.equals(b)) {
return true;
}
String ss = b.substring(1,b.length()-1);
for (int i = 0; i < 8; i++) {
String substr =a.substring(i, ss.length()+i);
if (!(ss.equals( substr ))) {
System.out.println("heelllo");
c = false;
} else {
c = true;
break;
}
}
if (c == true) {
return true;
} else {
return false;
}
}
}

Java Algorithm Question

Problem Statement :: In Java ,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, with this additional constraint: if there are numbers in the array that are adjacent and the identical value, they must either all be chosen, or none of them chosen. For example, with the array {1, 2, 2, 2, 5, 2}, either all three 2's in the middle must be chosen or not, all as a group. (one loop can be used to find the extent of the identical values).
groupSumClump(0, {2, 4, 8}, 10) → true
groupSumClump(0, {1, 2, 4, 8, 1}, 14) → true
groupSumClump(0, {2, 4, 4, 8}, 14) → false --> Failing Test Case
groupSumClump(0, {8, 2, 2, 1}, 9) → true --> Failing Test Case
groupSumClump(0, {8, 2, 2, 1}, 11) → false --> NegativeArraySizeException
I have done some initial Analysis and the partial code is as below.
public boolean groupSumClump(int start, int[] nums, int target) {
start = 0;
boolean flag = false;
// get the highest int from the list of array we have
int highestInteger = getTheBiggest(nums);
if (highestInteger > target) {
flag = false;
} else {
int variable = 0;
for (int i = 0; i < nums.length; i++) {
variable += nums[i];
}
if (variable == target) {
flag = true;
} else {
if (variable < target) {
flag = false;
} else {
// here goes ur grouping logic here
flag = summate(highestInteger, target, nums);
}
}
}
return flag;
}
private boolean summate(int highestInteger, int target, int[] nums) {
boolean val = false;
if (highestInteger == target) {
val = true;
} else {
int[] temp = new int[nums.length - 1];
int var = 0;
if ((target - highestInteger) > 0) {
for (int j = 0; j < nums.length-1; j++) {
if (nums[j] != highestInteger) {
temp[var] = nums[j];
if (temp[var] == (target - highestInteger)) {
val = true;
return val;
}
var++;
}
}
val = summate(getTheBiggest(temp), target - highestInteger,
temp);
}
}
return val;
}
private int getTheBiggest(int[] nums) {
int biggestInteger = 0;
for (int i = 0; i < nums.length; i++) {
if (biggestInteger < nums[i]) {
biggestInteger = nums[i];
}
}
return biggestInteger;
}
Please Note: I dont know how to handle the logic for below problem statement :
There is an Additional Constraint to the problem such that if there are numbers in the array that are adjacent and the identical value, they must either all be chosen, or none of them chosen. For example, with the array {1, 2, 2, 2, 5, 2}, either all three 2's in the middle must be chosen or not, all as a group. (one loop can be used to find the extent of the identical values).
how should i handle this part of logic in above problem.
I have been struggling to get this right with no idea.
Suggestions provided will be appreciated.
Culd you let me know what is the problem with the code/how to handle the additional constraint in this problem, :-((
Additional constraint says either u select as a group and not select as a group.so i dont know how to proceed.if u can PLEASE help me.it will be appreciated.
EDIT FOR USER->MISSINGNO: I have added the below code construct to above main code and it prints me wrong values.where have i gone wrong.
groupSumClump(0, {2, 4, 4, 8}, 14) → false is failing again
2
8
4
The flag is -->true which is wrong.
for(int number=0;number<nums.length-1;number++){
if(nums[number]==nums[number+1]){
nums[number]=nums[number]+nums[number+1];
}
}
I would convert the array to a simpler array that can be solved with your previous method, by clumping the adjacent values:
{1, 2, 2, 2, 5, 2} --> {1, 6, 5, 2}
You might want to keep some extra bookkeeping info though to be able to find the original solution from a solution to the altered problem.
This problem is similar to finding group of integers in an array which sum up to a given target.
Hint for this problem is:
The base case is when start>=nums.length. In that case, return true if target==0. Otherwise, consider the element at nums[start]. The key idea is that there are only 2 possibilities -- nums[start] is chosen or it is not. Make one recursive call to see if a solution is possible if nums[start] is chosen (subtract nums[start] from target in that call). Make another recursive call to see if a solution is possible if nums[start] is not chosen. Return true if either of the two recursive calls returns true.
You can use the same hint but with a loop in it to find sum of repeated numbers in array. Make a call to see if a solution is possible if the sum is chosen and make another call if the sum is not chosen.Return true if either of the two recursive calls returns true.
I think this would help.
public boolean groupSumClump(int start, int[] nums, int target)
{
if(start >= nums.length) return target == 0;
int count = 1;
while(start+count < nums.length && nums[start] == nums[start+count])
count++;
if(groupSumClump(start+count, nums, target-count*nums[start])) return true;
if(groupSumClump(start+count, nums, target)) return true;
return false;
}
You Have taken quite a lengthy approach to solving this question. Try thinking more recursively.
For the Base Case, we'll check if the start is greater than or equal to the length of the provided array(nums). If it is true, we'll check if we've reached the target sum, i.e. target is equal to 0 or not. If it is, then we'll return true as we have an answer, else return false because we have traversed the whole array, and still not reached our target.
Base Case -
if(start>=nums.length)
return target==0;`
Now, we'll take a counter variable int c=1;. We'll use it to count the number of repeating characters present(if any). How we'll do it is, we will use a while loop and iterate till nums[start] to nums[start+c] and keep on increasing the counter by 1. When this loop will end, if the value of c is 1, then we didn't find any repeating characters. Else, we have found c repeating characters of nums[start]. Make Sure you don't go out of bounds in this while loop.
int c=1;
while(start+c<nums.length&&nums[start]==nums[start+c])
c++;
Now, you know if you have repeating characters or not. You either have to include all of them or none of them. We already have c, so now we just have to call the function in which it includes c*nums[start] or it doesn't include c*nums[start]
Now, if we have repetitions, the function will skip or take all of the same values. But if we don't have repetitions, just because the value of c is 1, the function call will work in this case too. Try to dry run the code to get a better idea.
In the end, if all the function calls return false, then we know that we don't have an answer, so we too will return false.
public boolean groupSumClump(int start, int[] nums, int target) {
if(start>=nums.length)
return target==0;
int c=1;
while(start+c<nums.length&&nums[start]==nums[start+c])
c++;
if(groupSumClump(start+c,nums,target-
c*nums[start])||groupSumClump(start+c,nums,target))
return true;
return false;
}
Once you've done missingno's preprocessing step (in linear time) what you have is essentially the subset sum problem. It's a rather hard problem, but approximate algorithms exist- might as well turn out to be practical depending on how long your sequence is.
the problem statement is ambigious and not clear:
with this additional constraint: if there are numbers in the array
that are adjacent and the identical value, they must either all be
chosen, or none of them chosen. For example, with the array {1, 2, 2,
2, 5, 2}, either all three 2's in the middle must be chosen or not,
all as a group
how about choosing single digits if the 'streaks' did not work out?
same example: {1,2,2,2,5,2}
in one recursive call we choose the streak of 2 2 2 (from answer above)
*if(groupSumClump(start+count, nums, target-count*nums[start])) return true*
in the next rec. call why can't we subtract the first single digit at nums[start]:
if(groupSumClump(start+count, nums, target)) return true;
can i do this:
if(groupSumClump(start+1, nums, target - nums[start])) return true;
DOES IT MEAN WE CAN NEVER CHOOSE SINGLE DIGITS?
Your public method parameter list for the method groupSumClump should not expose the start parameter, especially if you have an internal variable that overrides it.
Have a look at this implementation. The time complexity for the solve method is O(2^N), since in the worst case you are obliged to check all possible subsets of nums. Well unless someone proves that NP = P.
I Hope it helps.
import java.util.*;
public class SubsetSumSolver {
public boolean solve(int[] nums, int target) {
return solve(0, 0, target, mergeSameNumbers(nums));
}
private boolean solve(int start, int tempSum, int sum, ArrayList<Integer> nums) {
if (start == nums.size())
return sum == tempSum;
return solve(start + 1, tempSum + nums.get(start),sum, nums) || solve(start + 1, tempSum, sum, nums);
}
private ArrayList<Integer> mergeSameNumbers(int[] nums) {
if (nums.length == 0)
return toArrayList(nums);
LinkedList<Integer> merged = new LinkedList<>();
int tempSum = nums[0];
for (int i = 1; i < nums.length; i++) {
if (nums[i - 1] == nums[i])
tempSum += nums[i];
else {
merged.add(tempSum);
tempSum = nums[i];
}
}
merged.add(tempSum);
return new ArrayList(merged);
}
private ArrayList<Integer> toArrayList(int[] nums) {
ArrayList<Integer> result = new ArrayList();
for (int index = 0; index < nums.length; index++)
result.add(nums[index]);
return result;
}
}
My solution with a HasMap.
public boolean groupSumClump(int start, int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Arrays.sort(nums);
for (int i : nums) {
if (!map.containsKey(i)) {
map.put(i, 1);
}
else {
map.put(i, map.get(i) + 1);
}
}
return groupSumClumpHelper(start, nums, target, map);
}
private boolean groupSumClumpHelper(int start, int[] nums, int target, Map map) {
if (start >= nums.length) {
return target == 0;
}
if (!map.get(nums[start]).equals(1)) {
return groupSumClumpHelper(start + Integer.parseInt(map.get(nums[start]).toString()), nums, target - Integer.parseInt(map.get(nums[start]).toString()) * nums[start], map) ||
groupSumClumpHelper(start + Integer.parseInt(map.get(nums[start]).toString()), nums, target, map);
}
return groupSumClumpHelper(start + 1, nums, target - nums[start], map) || groupSumClumpHelper(start + 1, nums, target, map);
}

Categories

Resources