I have quite a layman question about Java programming.
I would like to write a function to check whether a list of number is sequential or not.
Say [1, 2, 3, 4, 5], the function will return true,
but for [1, 3, 4, 9, 10], the function will return false.
Could anyone help me?
Thank so much!
Write a loop that looks at each element of the list.
For each position i in the list, test that listi + 1 equals listi + 1.
You can code it yourself as an exercise. (Don't forget to deal with the edge cases ...)
UPDATE: ... for people treating this problem as a learning exercise.
A simple direct implementation approach is probably the best idea; e.g. #Joe's final answer. However, the simple approach doesn't always work well ... or at all:
Some Java List implementations have a get method that is O(N). That would lead to an O(N^2) algorithm overall.
Sometimes a a list can only be accessed using an iterator; i.e. list.get(i) might not be an option.
In such cases, you could implement the algorithm with one pass through the list using an iterator. You need to keep "the previous element" in variable, etcetera.
Logic is simple. Just get the first number and check whether it matches with the next value. Like that check adjacent values. Break if the condition fails at any point. The list will be sequential if all the if condition is true.
As Stephen C said, it is a very simple logic
int a[] = { 1, 2, 3, 4, 5,7 };
boolean flag = true;
for (int i = 0; i < a.length - 1; i++) {
if (a[i + 1] != a[i] + 1) {
flag = false;
break;
}
}
System.out.println("Flag is " + flag);
Related
The Question:
Write a function, that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [−1, −3], the function should return 1.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [−1,000,000..1,000,000].
What I'm not understanding is how I'm failing these two cases, while also having 100% correctness
Also I'm not sure what cases I'm not covering, I managed for the case of 1 not existing in the first if statement, if there is a missing element in my for each loop, and finally, in the case of no missing element, to return the largest int + 1
Any help in clearing the confusion (and improvements for my time complexity) would be greatly appreciated
import java.lang.*;
import java.util.*;
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
//int counter = 0;
Set<Integer> set = new HashSet<Integer>();
Arrays.sort(A);
for(int n : A){
if(n > 0){
// counter++;
set.add(n);
}
}
//returns if set does not contain 1
if(!set.contains(1)){
return 1;
}
//returns missing int if it does not exist in set
for(int n: set){
if(!set.contains(n+1)){
return n+1;
}
}
//if no missing ints, returns end of array + 1
return A[A.length-1];
}
}
Answer Results:
I think you over-killed. first, using a hashset can lead to O(N) algorithm, which you have to avoid sort (O(NlogN)). But due to large memory footprint, I'd rather go with a sort and it is practically faster. Second, if you choose a sort of A, then a simple for-loop with detect any gap in the positive part of the array, which is now your result. You should avoid Hashset and the many loops in your code
I would use a BitSet.
Advantage: Fast scan for missing value. Performance: O(n)
public static int solution(int... values) {
BitSet bitSet = new BitSet();
for (int v : values)
if (v > 0)
bitSet.set(v);
return bitSet.nextClearBit(1);
}
Test
System.out.println(solution(1, 3, 6, 4, 1, 2));
System.out.println(solution(1, 2, 3));
System.out.println(solution(-1, -3));
Output
5
4
1
I really need help with a homework problem. I've been trying to figure this out for days and would really appreciate some assistance! Here's the prompt:
Merge two arrays into one. Write a method named merge which takes 3 interger array
parameters: a, b, and soln. soln is guaranteed to be the size of a.length + b.length. The arrays a and b should be "merged" into one array by alternating elements. Add a 4th parameter, which indicates which element in soln should be updated for a given recursive call of the method.
Examples:
merge({1, 2, 3}, {4, 5, 6}, soln, 0) should end with the following values in soln: {1, 4, 2, 5, 3, 6}
merge({1,2}, {3,4,5}, soln, 0) should end with the following values in soln: {1,3,2,4,5}
I can get it to work with the arrays are the same length, and even when the arrays differ in length (but only by one element). I can't get the index to line up correctly. I've tried many different variations, but here's what I have so far:
public static void merge3(int[] a, int[] b, int[] soln, int index) {
if (index > soln.length-1) {
return; //if index reaches end of soln length
}
int index2 = (int)(index/2); //allows me to pull alternately from a and b arrays. As index goes up, index2 becomes 0, 0, 1, 1, 2, 2, etc.
if (b.length >= a.length) {
if (index%2 == 0) {
if (index2 > a.length-1) {
soln[index] = b[index2];
merge3(a, b, soln, index+1);
} else {
soln[index] = a[index2];
merge3(a, b, soln, index+1);
}
} else {
soln[index] = b[index2];
merge3(a, b, soln, index+1);
}
} else if (b.length < a.length) {
if (index%2 == 0) {
soln[index] = a[index2];
merge3(a, b, soln, index+1);
} else {
if (index2 >= b.length) {
soln[index] = a[index2];
merge3(a, b, soln, index+1);
} else {
soln[index] = b[index2];
merge3(a, b, soln, index+1);
}
}
}
}
If array a is {1, 2, 3} and array b is {4, 5, 6, 7, 8, 9}, soln becomes {1, 4, 2, 5, 3, 6, 7, 7, 8} instead of what it's supposed to be, which is {1, 4, 2, 5, 3, 6, 7, 8, 9}. It's off because when I do index + 1, the recursive call catches on the same value (index2) which was used to alternate between the arrays when there's only one array left. Please help! Thank you!
Here is an intentionally pedantic approach to thinking through this kind of problem.Start by determining your state. One way to divide all the possibilities in this problem into distinct states is:
exit, where you will simply return. (always need this for every recursively called method).
before array exhaustion, where you still have at least one array element left in each of the input arrays a and b.
after array exhaustion, where all of the smaller array's elements have already been added to soln
array a empty where the first array has no elements. Normally you would handle this outside a recursive call, but we're following rules here...
Each of these states represents a different way that you need to handle your inputs.
The pseudocode for this type of structure would look like:
if (test to see if we're in "exit" state) {
logic handling "exit" state
} else {
if (test to see if we're in "before array exhaustion" state) {
logic handling "before array exhaustion" state
} else {
if (test to see if we're in "array `a` empty" state ) {
logic handling "array `a` empty" state
} else {
logic handling "after array exhaustion" state
}
}
}
recursive call to your method here
You already have the (test to see if we're in "exit" state) here:
if (index > soln.length-1) {
and you have the logic handling "exit" state here:
return; //if index reaches end of soln length
Since this state's logic returns, the syntax doesn't require that you put it in an if-else like it is in the pseudocode, but it might be clearer while you're getting a handle on Java syntax if you consistently use the if-else structure throughout.
After that you need your if (test to see if we're in "before array exhaustion" state), conditional, but instead your code assumes you're at logic handling "before array exhaustion" state and handles it accordingly. The logic is good, but the state isn't. You'll need to use the template and put that logic in its proper place, but at least you don't have to rewrite it.
Now fill out the rest of the pseudocode template, starting with the tests.
Tests:
The test to see if we're in "array 'a' empty" state just looks to see if array a is empty or not, so it's pretty trivial to write.
The test to see if we're in "before array exhaustion" state checks whether we've already copied all of the smaller array's elements into soln yet or not, based on a.length, b.length, and index.
Array population logic:
What you've got below your exit case works perfectly for logic handling "before array exhaustion" state, so you just need to write:
logic handling "array 'a' empty" state where you already know array a is empty.
logic handling "after array exhaustion" state. This is the part where we're all done with the smaller array, and we need to know which element to pull from the larger input array so that we can add it to soln.
So basically follow the template and write the 3 tests (1 already done, one trivial, and one more), and then write the logic for the different states (two already done, one trivial, and one more) and you're there.
You might also consider refactoring your existing code so that there's only one recursive call that happens at the very end. That's called tail recursion, and even with all the optimizations that Java SE 8 has, it's still better this way. It's also a lot cleaner.
Hopefully this is a useful template for thinking through a simple problem.
The problem is given an unsorted array, give subsets of array that can produce target sum:
For eg:
target = 15
data = {3,4,5,7,1,2,9};
Expected results (note the results are sorted for simplicity. not a requirement) :
[1, 2, 3, 4, 5]
[1, 2, 3, 9]
[1, 2, 5, 7]
[1, 3, 4, 7]
[1, 5, 9]
[2, 4, 9]
[3, 5, 7]
Here is my naive approach to this problem - simple and brute force.
public static void naiveSubset(int[] arr, int target){
int sum=0;
List<Integer> result = new ArrayList<>();
for (int i=0; i< arr.length;i++){
sum =arr[i];
result.add(arr[i]);
for (int j=0;j<arr.length;i++){
if (sum==target){
System.out.println(result);
result.clear();
break;
}
else if (i!=j && sum+arr[j] <= target){
sum+=arr[j];
result.add(arr[j]);
}
}
}
}
For some reasons, I am not expecting the results. I tried browsing through the code to dig out any issues. But I could not find any. please algo experts, point me in correct direction!!
The results I get (for same input as above)
[3, 3, 3, 3, 3]
[9, 3, 3]
Your solution is wrong because it's a greedy approach. It decides if you should add a number or not based on the fact that adding it does not violate the sum, at the moment.
However, this greedy approach does not work, with a simple example of the following array: [1,9,6,5] and with sum=11.
Note that for any element you choose in the outer loop, next you will add 1 to the current set. But that will deny you the possibility to get the sum of 5+6.
Once you choose 5, you start adding number, starting with '1', and adding it. Once it is added - you will never get the correct solution.
Also note: Your double loop approach can generate at most O(n^2) different subsets, but there could be exponential number of subsets - so something must be wrong.
If you want to get all possible subsets that sum to the given sum, you can use a recursive solution.
At each step "guess" if the current element is in the set or not, and recurse for both options for the smaller problem - if the data is in the set, or if it's not.
Here is a simple java code that does it:
public static void getAllSubsets(int[] elements, int sum) {
getAllSubsets(elements, 0, sum, new Stack<Integer>());
}
private static void getAllSubsets(int[] elements, int i, int sum, Stack<Integer> currentSol) {
//stop clauses:
if (sum == 0 && i == elements.length) System.out.println(currentSol);
//if elements must be positive, you can trim search here if sum became negative
if (i == elements.length) return;
//"guess" the current element in the list:
currentSol.add(elements[i]);
getAllSubsets(elements, i+1, sum-elements[i], currentSol);
//"guess" the current element is not in the list:
currentSol.pop();
getAllSubsets(elements, i+1, sum, currentSol);
}
Note that if you are looking for all subsets, there could be exponential number of those - so an inefficient and exponential time solution is expected.
If you are looking for finding if such a set exist, or finding only one such set, this can be done much more efficiently using Dynamic Programming. This thread explains the logic of how it can be done.
Note that the problem is still NP-Hard, and the "efficient" solution is actually only pseudo-polynomial.
I think the major issue in your previous approach is that simply doing loops based upon the input array will not cover all the combinations of numbers matching the target value. For example, if your major loop is in ith, and after you iterate through the jth element in your secondary loop, your future combination based on what you have collected through ith element will never include jth one anymore. Intuitively speaking, this algorithm will collect all the visible combinations through numbers near each other, but not far away from each other.
I wrote a iterative approach to cope with this subset sum problem through C++ (sorry, not have a java environment at hand:P), the idea is basically the same as the recurrsive approach, which means you would record all the existing number combinations during each iteration in your loop. I have one vector<vector> intermediate used to record all the encountered combination whose value is smaller than target, and vector<vector> final used to record all the combinations whose sum is equal to target.
The detailed explanation is recorded inline:
/* sum the vector elements */
int sum_vec(vector<int> tmp){
int sum = 0;
for(int i = 0; i < tmp.size(); i++)
sum += tmp[i];
return sum;
}
static void naiveSubset(vector<int> arr, int target){
/* sort the array from big to small, easier for us to
* discard combinations bigger than target */
sort(arr.begin(), arr.end(), greater<int>());
int sum=0;
vector<vector<int> > intermediate;
vector<vector<int> > final;
for (int i=0; i< arr.size();i++){
int curr_intermediate_size = intermediate.size();
for(int j = 0; j < curr_intermediate_size; j++){
int tmpsum = sum_vec(intermediate[j]);
/* For each selected array element, loop through all
* the combinations at hand which are smaller than target,
* dup the combination, put it into either intermediate or
* final based on the sum */
vector<int> new_comb(intermediate[j]);
if(tmpsum + arr[i] <= target){
new_comb.push_back(arr[i]);
if(tmpsum + arr[i] == target)
final.push_back(new_comb);
else
intermediate.push_back(new_comb);
}
}
/* finally make the new selected element a separate entry
* and based on its value, to insert it into either intermediate
* or final */
if(arr[i] <= target){
vector<int> tmp;
tmp.push_back(arr[i]);
if(arr[i] == target)
final.push_back(tmp);
else
intermediate.push_back(tmp);
}
}
/* we could print the final here */
}
Just wrote it so please bear with me if there is any corner case that I did not consider well. Hope this helps:)
I tried the sample demo at Codility website, and posted my solution but I've a simple mistake but couldn't determine it.
The problem is described here (The problem is only described please don't care about the analysis there as that wasn't not my solution)
http://codility.com/cert/view/certHNPV9B-7M4GAQR985B54VYF/details
my solution is here:
public static int min_router_peripherality ( int[] T ) {
// write your code here
int sum=0;
for(int i=0;i<T.length;i++) sum+= T[i];
int min = sum;
int index = 0;
int array [] = new int [T.length];
for(int i=0;i<T.length;i++) {
min = sum -T[i];
array[i] = min;
}
int x = array[0];
for (int i=0; i<array.length;i++)
{
if (array[i]<x)
{
x = array[i];
index = i;
}
}
return index;
}
What I see as mistakes are the following:
for(int i=0;i<T.length;i++)
sum+= T[i];
Here you treat T[i] like some weight. But Node-Ids are no weights. Summing up node ids is useless.
Then: The text says: "if T[P] = Q and P ≠ Q, ...". I don't see anything which takes this into account.
Then: Not understanding the algorithm I tried a simple "line" like this:
int[] T = {1, 2, 3, 4, 5, 6, 7, 8, 9, 9};
The result is 8. But in a line the result should be somewhere in the middle.
Therefore I doubt that the linked page shows the results of the code you have posted.
When looking at the results I would say that your program is correct, but too slow to successfully complete all test cases. So you need to come up with better algorithm.
EDIT: As Ivan Benko Ivan Benko noted, your solution is O(N), so i looked at your code and I came up with a following input:
{ 4, 9, 4, 9, 4, 4, 8, 9, 0, 0 }
Although it is not the example input, it does describe the same network as in the task description. So the output should be same, but your solution gives a different answer.
All I did was look at your code, and the first thing I noticed is that it doesn't look like you need that array array at all, or that third for loop. The second for loop can just keep track of the lowest min value it generates as it goes, along with the index associated with that lowest min value, rather than storing all the values and making a second run like you're doing now.
Edit:
Like everyone else, I assumed that your link was to your own results. I'm not going to post an answer, because I think you're supposed to come up with that yourself. However, it looks to me like you got confused where they said "find the sum of distances to all other nodes", and that might be why you're starting off summing up the entire array. The array they're passing into your function isn't a set of distances by any means. It's a list of existing connections. If the first element (the one at the 0 index) in the array is a 5, then that means Router 0 has a connection to Router 5. So it looks to me like you're approaching it all wrong.
Two adjacent node has a one edge and its weight is 1.
I've got a set of recursion problems that I need to do. I've completed 3 out of the 4 of them we were given, but I'm having a hard time wrapping my head around this last one. I don't necessarily want the actual answer, but maybe just point me in the right direction, because I'm not even seeing what my stop condition should be on this one. And note, it has to be recursive, no loops, etc.
Thanks in advance for any help provided!
Write recursive method arrayRange that returns the maximum integer minus the minimum integer in the filled array of ints. Use recursion; do not use a loop. The following assertions must pass (note the shortcut way to pass a reference to a new array--it saves your writing a bit of code (this passes an array built as a parameter):
assertEquals(2, rf.arrayRange(new int[] { 1, 2, 3 } ));
assertEquals(2, rf.arrayRange(new int[] { 3, 2, 1 } ));
assertEquals(0, rf.arrayRange(new int[] { 3 } ));
assertEquals(3, rf.arrayRange(new int[] { -3, -2, -5, -4 } ));
// Precondition: a.length > 0
public int arrayRange(int[] a)
The stop condition is when there are only two items left: the maximum and minimum. Then just return the difference. (Also handle the case of 1 or 0 items, consider input such as in the test cases.)
Now .. how to reduce the list each pass? :) I would consider inspecting the first three values at a time (of the three, only two should remain in the recursive step).
Happy homeworking.