find if 3 numbers in an array add up to a sum - java

I have a method written to determine if a sum exists in an array. So the rule is there must exist 3 numbers in the array such that adding them all together equals to a given sum. So in the array {1,2,3,14,12} if i was searching for a sum of 6 then 2+3+1 would be the numbers that give me 6. From researching online this can be done with a set so i have the following function which works but im having a hard time understanding the logic:
public void existsSum(int[] numbers,int sum){
Set<Integer> set = new HashSet();
for(int i=0;i<numbers.length;i++){
int s1=sum - numbers[i];
for(int j=0;j<numbers.length;j++){
int s2=s1-numbers[j];
if(set.contains(s2)) {
System.out.format("sum of %d + %d + %d gives %d \n", numbers[i], numbers[j],s2, sum);
assert(numbers[i]+numbers[j]+s2==10);
}
}
set.add(numbers[i]);
}
}
I dont understand what is the significance of s1 and s2 ? can someone explain to me the logic. The method itself works fine and if i run it with the following it yields the correct results:
int[] integers = {1,2,3,4,5,6,7,8,9};
existsSum(integers,10);
sum of 2 + 7 + 1 gives 10
sum of 3 + 5 + 2 gives 10
sum of 3 + 6 + 1 gives 10
sum of 4 + 3 + 3 gives 10
sum of 4 + 4 + 2 gives 10
sum of 4 + 5 + 1 gives 10
sum of 5 + 1 + 4 gives 10
sum of 5 + 2 + 3 gives 10
sum of 5 + 3 + 2 gives 10
sum of 5 + 4 + 1 gives 10
sum of 6 + 1 + 3 gives 10
sum of 6 + 2 + 2 gives 10
sum of 6 + 3 + 1 gives 10
sum of 7 + 1 + 2 gives 10
sum of 7 + 2 + 1 gives 10
sum of 8 + 1 + 1 gives 10

Your code doesn't work, because i and j may point to the same number.
Also, the assert hardcodes the sum to find as 10.
Anyway, the main logic without set is 3 nested loops:
Loop 1: Loop thru all numbers.
Loop 2: Loop thru all numbers following current number from loop 1.
Loop 3: Loop thru all numbers following current number from loop 2.
If sum of the 3 current numbers is correct, print it.
for (int i = 0; i < numbers.length; i++)
for (int j = i + 1; j < numbers.length; j++)
for (int k = j + 1; k < numbers.length; k++)
if (numbers[i] + numbers[j] + numbers[k] == sum)
System.out.println("sum of %d + %d + %d gives %d\n",
numbers[i], numbers[j], numbers[k], sum);
For performance improvement, the innermost loop can be optimized, by instead calculating the 3rd number as num3 = sum - num1 - num2, then see if it is in the list of numbers.
To prevent using the same number more than once, the logic of the 3rd check is reversed to check against all numbers preceding the current number from loop 1, and to build the set of such numbers as the first list is iterated.
Pseudo-code:
set = new set()
for (int i = 0; i < numbers.length; i++)
for (int j = i + 1; j < numbers.length; j++) {
num3 = sum - numbers[i] - numbers[j]
if (num3 in set)
print("sum of %d + %d + %d gives %d\n",
num3, numbers[i], numbers[j], sum);
}
add numbers[i] to set
}

The function is simply trying to find the number s2 in the set where s2=sum-first_number-second_number. The two loops help you to iterate over all numbers in the list as first_number and last_number.
Finally searching for s2 in the set tells you that s2+first_number+last_number is equal to the sum.

Related

What is supposed to be the Time Complexity of this loop

What should be the time complexity of this code?
I am thinking (n^2 -n) as the loop will run n(n-1)/2 times.
for (int i = 0; i < n-1; i++) {
for (int j = i + 1; j < n; j++) {
System.out.println(i + "i " + j + " j");
}
}
i: outer loop runs n - 1 times
j: inner loop runs n - (i + 1) times
Analyze it with a small number, say n = 10.
The outer loop will run 9 times.
The inner loop will run as follows
i = 0: 9 times
i = 1: 8 times
i = 2: 7 times
...
i = 8: 1 time
Therefore
n * ( n - 1) = n ^ 2 - n
For very large values of n, n is insignificant when compared to n squared.
See also wikipedia asymtotic analysis.

Finding all permutations to get the given sum (Coin change problem)

I am trying to solve a classical coin-change (dynamic) problem.
To find number of all unique combinations to get a sum from infinite denominations of coins using dynamic approach, i used this method:
/*
n - number of coins
arr[] - coin denominations
x - total sum
dp[] - array to store number of combinations at index i.
*/
for (int j = 0; j < n; j++)
for (int i = 1; i <= x; i++)
if (arr[j] <= i)
dp[i] = (long) ((dp[i] + dp[i - arr[j]]) % (1e9 + 7));
This gives me all unique possible combinations count:
Eg:
Input:
n=3 x=9
Coins: 2 3 5
Output:
3
So far ,all good.
But i observed that just by interchanging the loops in above snippet, i get all the possible permutations.
for (int i = 1; i <= x; i++)
for (int j = 0; j < n; j++)
if (arr[j] <= i)
dp[i] = (long) ((dp[i] + dp[i - arr[j]]) % (1e9 + 7));
This gives me all unique possible permutations count:
Eg:
Input:
3 9
2 3 5
Output:
8
With debugging and going through each iteration, i mapped a pattern that was formed, but didn't understand the reason behind why i am getting permutations.
Can any one explain me this iteratively. Any help will be appreciated.
Thanks
Both questions can be found here:
Permutations: Coin Combinations 1
Combinations: Coin Combinations 2
The first code with outer loop by coins updates number of ways to compose values dp[] with new coin at every round of outer loop. So after k-th round we have dp[] array filled with combinations of k coins only, and the rest of coins is not used yet. If we will store combinations themselves for sorted coin array, we will see only ordered ones like 1 1 5, and 5 never will go before 1. That is why combinations.
The second code at m-th round of outer loop fills m-th cell dp[m] using all possible coins. So we count for m=7 both 1 1 5 and 1 5 1 and 5 1 1 variants. That is why all permutations are counted here.
In addition for comment: we can make 2d array, where dp[x][c] contains number of permutations with sum x, ending with coin a[c]. Note that in this case we have to join counts of permutations with sum x-a[c]. For reference - 1d and 2d Python code.
def coins1(a, n): #permutations
count = [1]+[0]*n
for x in range(1, n + 1):
for c in a:
if (x-c >= 0):
count[x] += count[x-c]
return count[n]
def coins11(a, n): #permutations 2d
m = len(a)
count = [[1] + [0]*(m-1)] + [[0]*m for i in range(n)]
for x in range(1, n + 1):
for c in range(m):
if x>=a[c]:
count[x][c] += sum(count[x-a[c]])
return sum(count[n])

What is the average digit total of a given integer?

I have to use a static method TotalAverage(int n) that would calculate the average digit total of the numbers 0 + 1 + 2 + .... + n. So that totalAverage(19) would be calculated as (0 + 1 + ... + 9 + 1 + ... + 10) / 20.0. I managed to do it for the most part using the following code:
public static double TotalAverage(int n) {
double total = 0;
int count = 0;
while (n >= 0) {
total += n % 10;
n = n - 1;
count++;
}
return total / count;
}
It works for numbers up to 9, but I get incorrect results for larger numbers. I realise that once the while statements gets to 10 % 10 it adds 0 to the total and not a 10, but I can't figure out how to do it correctly.
If you're looking to sum all digits of a number then the error in your code is
total += n % 10;
which only get the ones digit from n. Use some loop to get all digits from n without modifying it (because if you modify n your outer loop will break). Try:
int temp = n;
while(temp>0) {
total += temp % 10; //add next digit
temp /= 10;
}
You could use a separate method for digit sum. Something like this would work.
private static int digitSum(int a) {
return a < 10 ? a : a%10 + digitSum(a/10);
}
Then you can replace the line
total += n % 10
with
total += digitSum(n);

Why does the for loop output this?

I am just very confused from this homework problem. I do not understand why the values of i and sum come out this way. I just do not understand the concept of the algorithm here, can someone please explain this?
int i = 0;
int sum = 0;
for(i=0; i < 5; i++)
{
sum += i;
}
System.out.println(i + "\n" + sum);
The output is:
5
10
----jGRASP: operation complete.
5 - because there are 5 iterations
10 - because the sum is 10 :)
Sum
Iteration 1: 0 + 0 = 0
Iteration 2: 0 + 1 = 1
Iteration 3: 1 + 2 = 3
Iteration 4: 3 + 3 = 6
Iteration 5: 6 + 4 = 10
Verification code
int i = 0;
int sum = 0;
for (i = 0; i < 5; i++) {
System.out.println(String.format(
"Iteration %s: %s + %s = %s", (i + 1), sum, i, (sum + i)));
sum += i;
}
This code :
int i = 0;
int sum = 0;
for(i=0; i < 5; i++)
{
sum += i;
}
System.out.println(i + "\n" + sum);
output in sum this : 0 + 1 + 2 + 3 + 4 which is equal to 10 and i the number of iterations = 5.
You have created a variable i with value of 0 and then incrementing it 5 times in for-loop. So you got i's value as 5.
Now the value of sum is 0+1+2+3+4 which is 10
Because you iterate through your loop, which makes i == 5, then print it,
Sum goes as below, you are adding i to the previously calculated sum
0 + 1 = 1
1 + 2 = 3
3 + 3 + 6
6 + 4 = 10
Try put your print command inside the loop, they you can see better what's going on.
The only non-obvious thing is (in my opinion): i will be 5, because you used i++, which also incremented i by 1 even though the body did not execute after the last iteration. Inside the body i only can be maximum 4.
int sum = 0; int i = 0;
for (i = 0; i < 5; i++)
{
sum += i;
if (i == 5)
System.out.println("never executed");
};
Other answers tell the other things.

For loop to print the number in sequence and reverse it

How to print the following output with only one for-loop in java?
1 2 3 4 5 6 7 8 9 1 0 9 8 7 6 5 4 3 2 1
Code snippet:
class Series{
public static void main(String args[]){
for(int i=1; i<=10; i++){
System.out.println(i);
}
System.out.println(i);
for(int j=9; j>=0; j--){
System.out.println(j);
}
}
My program's in the following manner. Can anyone correct it?
public static void main(String...strings ){
int dir = 1;
for(int i=1; i>0; i+=dir){
if(i == 10)
dir = -1;
System.out.print(i+" ");
}
}
Output:
1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1
The series in the question is wrong.
It should be: 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1
The code, in one loop, is as follows:
int ctr = 1;
for(int i = 1; i > 0; i += ctr)
{
if(i == 10)
{
ctr = -1;
}
System.out.print(i + " ");
}
Every sequence follows a pattern, Let's try finding one in this.
To work with this code, analyze What loop would print with the variable that you increment and What you want in the output?
In your problem, assuming that the number you are entering is entered by user i.e. n, you want 2*n - 1 numbers in your sequence. Hence we now have the limits of our loop
For n=5, Under no Conditions the loop would simply print a sequence like this
1 2 3 4 5 6 7 8 9 provided you are starting your loop from 1.
The sequence you want is 1 2 3 4 5 4 3 2 1.
Now looking at both the sequences you can see that the sequence is same till the mid point that is till the value of n is reached. Now if you observe the pattern further if you subtract 2 from 6 you get 4 that is the number you want in your sequence. Similarly when you subtract 4 from 7 you get 3 which is the next number in the sequence you required.
Hence the pattern this sequence follows is that after the loop reaches the value provided by the user you need to subtract (2 * k) from the next number where k starts from 1 and increases with every iteration
Now you know how to achieve the pattern which would be easy to achieve using conditional statements.
PS: let's assume an added constraint of using no conditional statements then we have to write an arithmetic expression to solve our problem.
Following the pattern again the expression must display i where i is the variable incremented in the loop
so our code looks like
for (i = 1; i<=2*n - 1;i++)
{
System.out.print(i);
}
Now to get the pattern we need to subtract multiples of 2 after the user provided integer n is reached. But whatever we subtract should also not affect out first n integers.
Since we know we have to subtract multiples of 2 we know the expression we have to subtract would look like 2 * (____). As we want a sequence of multiples we can obtain that using %. As soon as the number goes over n the % operator on i would give us back sequence from 0 to n-1 hence generating multiples of 2.
Now our expression comes to 2 * (i % n). But the problem is that it would also subtract from the first 4 integers which we don't want so we have to make changes such that this expression will work only after loop reaches the value provided by the user.
As we know the division / operator provides us with the quotient. Hence it would yield us 0 till we reach the value of user defined number and 1 for the rest of the sequence as we run our loop till 2*n -1. Hence multiplying this expression to our previous expression yields 2*(i%n)*(i/n)
And there we have it our final code to generate the sequence would be
for (int i = 1;i<2*r;i++)
{
System.out.print(i - 2 * (i%r)*(i/r));
}
Observe the above code for the first n-1 integers i/r would make subtracted expression 0 and for i = n, i % r would make the expression 0. For the rest of the sequence i / r would generate value 1 and hence we will get multiples of 2 from 2 *( i % r) to provide us with the sequence
try this
int j = 10;
for (int i = 1; i <= 10; i++) {
if(i<10)
System.out.print(" " +i);
if(i==10){
i--;
System.out.print(" " +j);
if(j==1){
i++;
}
j--;
}
}
OutPut
1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1
Something like this?
for(int i=0;i<20;i++) {
if((i/10)%2 == 0)
System.out.print(i%10 + " ");
else
System.out.print((10-(i%10)) + " ");
}
Try this code, You just need a if condition in for loop.
int i = 1;
for(int j=1; j<=20; j++)
{
if(j<11)
System.out.print(j+" ");
else
{
System.out.print((j - i == 10 ?" ": (j-i + " ")));
i = i+2;
}
}
public class forLoopTest {
public static void main(String[] args) {
for (int i = 1; i < 10; i++) {
System.out.print(i + " ");
}
for (int j = 10; j >= 1; j--) {
System.out.print(j + " ");
}
}
}

Categories