Choose one in pair from array and find minimum total - java

You receive an array of integers and must choose one value from each pair of adjacent values. For example, given {1,0,5} you can pick 1 and 5 or just 0. The goal is to find the minimum total sum you can get from all the chosen values, print it, and print each chosen value from the array.
For example, given {1,0,5} you want to choose 0 since it's the lowest in the pairs (1,0) and (0,5), and the minimum total sum is 0.
Another example: given {10,30,90,50,30} the minimum sum is 30 + 50 = 80 and we made sure that for each pair of adjacent values at least one was chosen (10,30), (30,90), (90,50), (50,30).
I used dynamic programming to find the minimum total sum, but I'm not sure how to print each chosen value to create that sum.
public static void main(String[] args) {
// Define the input array
int[] arr = {50, 30, 40, 60, 10, 30, 10};
// Define the array to store the minimum sum for each index
int[] dp = new int[arr.length];
// Initialize the first element of the dp array
dp[0] = arr[0];
dp[1] = arr[1];
// Loop over the input array from the second index to the last index
int choice1 = 0, choice2;
for(int i = 2; i<arr.length; i++) {
// Choose the previous index and add its minimum sum to the current element
choice1 = dp[i-1] + arr[i];
// Choose the index before the previous index and add its minimum sum to the current element
choice2 = dp[i-2] + arr[i];
// Compare the two choices and choose the one with the lower sum
dp[i] = Math.min(choice1, choice2);
}
// Print the minimum sum and the chosen values
if(dp[arr.length - 1] > dp[arr.length - 2]) {
System.out.println(dp[arr.length - 2]);
}else {
System.out.println(dp[arr.length - 1]);
}
}

Related

Reduce time complexity of game program

Adam wants to watch a football game from the top of the building that is arranged in a straight line.
Adam can watch the football match from the top of ith building if
there exists a maximum of K[i] buildings in front of Adam with a
height less than or equal to the height of ith building.
If there is any building in front of Adam with a height more than
the height of ith position building then he cannot see the match
from this ith building.
Count the positions of buildings where Adam can see the match from the top of the buildings.
Example:
Both arrays have the same length.
B (Buildings) = [2,1,3] represents the height of buildings
K = [1,2,1]
Answer:
1
Explanation:
For B[0] = 2 we have K[0] = 1. The number of buildings in front of it that have a height smaller than or equal to 2 is 0. This is <= K[0] So Adam can see the match.
For B[1] = 1, we have K[1] = 2. The number of buildings in front of it that have a height smaller than or equal to 1 is 0. But B[0] = 2 so Adam cannot see the match.
For B[2] = 3, we have K[2] = 1. The number of buildings in front of it that have a height smaller than or equal to 3 is 2. But this value is >= K[2] i.e 1 so Adam cannot see the match
The total positions where Adam can see the match is 1.
Constraints:
Array size is 1 to 10^5
Each element in Arrays is 1 to 10^5
This is the code I tried with the time complexity of O(n^2):
public static int process(int[] buildings, int[] K) {
int n = buildings.length;
int answer = 0;
for(int i=0; i<n; i++) {
int count = 0;
boolean valid = true;
for(int j=i-1; j>=0; j--) {
if(buildings[j] <= buildings[i]) count++;
if (buildings[j] > buildings[i]) {
valid = false;
break;
}
}
if(valid && count <= K[i]) answer++;
}
return answer;
}
This program works for arrays of small size but fails for large arrays as the time complexity of my program is O(n^2).
What is the better approach to solve this and how can we reduce the time complexity?
you have 2 conditions which we look on one by one but we'll start from the second:
The second condition can be interpreted as if ith building is the highest building from any other building in front of it. this can be achieved by checking the max hight to the ith position and update it as you go.
if the second condition is true that's means you have i-1 buildings in front of the ith building that are equal or smaller than it (i instead of i-1 if you start to count from 0 like in array). so the first condition would be true only if k[i] is bigger than (i-1) you just need to compare between them.
here is the code in java:
import java.util.*;
class HelloWorld {
public static void main(String[] args) {
List<Integer> buildings = Arrays.asList(2, 1, 3);
List<Integer> K = Arrays.asList(1, 2, 1);
System.out.println(process(K, buildings));
}
public static Integer process(List<Integer> K, List<Integer> buildings){
Integer maxHightBuilding = buildings.get(0);
Integer sum = 0;
for(Integer i = 0; i < buildings.size(); i++){
if(buildings.get(i) >= maxHightBuilding ){
maxHightBuilding = buildings.get(i);
if(i <= K.get(i)){
sum++;
}
}
}
return sum;
}
}
I think if you retain the biggest value in front of the actual index, you can just check with the value and when your index passes the biggest value you can update it.
So find the biggest value from the end of the array.
HF!

print index of 2 max values

My question is if I input two maxvalue numbers in array, ex. 100, 10, 100. How can i get the output to print both index numbers?
The output expected would be 100 on index 1 and index 3
the index has 1 added as I want the index to start at one not zero
Add this to initialization.
HashSet<Integer> maxIndices = new HashSet<Integer>();
Make a second pass through the mileage array and add any max values to the HashSet.
The other option is to use a HashMap where the first integer is the mileage and the second value is the positive integer of how many have been found.
Because it makes only one pass, it may be faster even though you are counting every mileage, not just the one that ends up being the largest. Whether it is will be, of course, dependent upon the data, the compiler, and environmental conditions at the time of execution.
For your return value, you'll either need a custom POJO Java Bean or you can use Pair<> or Tuple<>. (See Using Pairs or 2-tuples in Java.)
Just simple Java using a series of for loops. The below method will return a 2D int array with each row consisting of two columns, the highest array value and its' respective array index number.
public int[][] getAllMaxValues(int[] allValues) {
int maxVal = 0;
int counter = 0;
// Get the Max value in array...
for (int i = 0; i < allValues.length; i++) {
if (allValues[i] > maxVal) {
maxVal = allValues[i];
}
}
// How many of the same max values are there?
for (int i = 0; i < allValues.length; i++) {
if (allValues[i] == maxVal) {
counter++;
}
}
// Place all the max values and their respective
// indexes into a 2D int array...
int[][] result = new int[counter][2];
counter = 0;
for (int i = 0; i < allValues.length; i++) {
if (allValues[i] == maxVal) {
result[counter][0] = maxVal;
result[counter][1] = i;
counter++;
}
}
// Return the 2D Array.
return result;
}
How you might use this method:
int[] allMiles = {100, 10, 100, 60, 20, 100, 34, 66, 74};
int[][] a = getAllMaxValues(allMiles);
for (int i = 0; i < a.length; i++) {
System.out.println("Array max value of " + a[i][0] +
" is located at index: " + a[i][1]);
}
Console window would display:
Array max value of 100 is located at index: 0
Array max value of 100 is located at index: 2
Array max value of 100 is located at index: 5

Getting indexes of maximum number in array

I have an array containing numbers which are ranks.
Something like this :
0 4 2 0 1 0 4 2 0 4 0 2
Here 0 corresponds to the lowest rank and max number corresponds to highest rank. There may be multiple indexes containing highest rank.
I want to find index of all those highest rank in array. I have achieved with following code:
import java.util.*;
class Index{
public static void main(String[] args){
int[] data = {0,4,2,0,1,0,4,2,0,4,0,2};
int max = Arrays.stream(data).max().getAsInt();
ArrayList<Integer> indexes = new ArrayList<Integer>();
for(int i=0;i<12;i++){
if(data[i]==max){
indexes.add(i);
}
}
for(int j=0;j<indexes.size();j++){
System.out.print(indexes.get(j)+" ");
}
System.out.println();
}
}
I have got result as : 1 6 9
Is there any better way than this ?
Because, In my case there may be an array containing millions of elements due to which I have some issue regarding performance.
So,
Any suggestion is appreciated.
One approach would be to simply make a single pass along the array and keep track of all indices of the highest number. If the current entry be less than the highest number seen so far, then no-op. If the current entry be the same as the highest number seen, then add that index. Otherwise, we have seen a new highest number and we should throw out our old list of highest numbers and start a new one.
int[] data = {0,4,2,0,1,0,4,2,0,4,0,2};
int max = Integer.MIN_VALUE;
List<Integer> vals = new ArrayList<>();
for (int i=0; i < data.length; ++i) {
if (data[i] == max) {
vals.add(i);
}
else if (data[i] > max) {
vals.clear();
vals.add(i);
max = data[i];
}
}
You are on the Stream- way... I would suggest you to stay there :)
int[] data = { 0, 4, 2, 0, -1, 0, 4, 2, 0, 4, 0, 2 };
int max = Arrays.stream(data).max().getAsInt();
int[] indices = IntStream.range(0, data.length).filter(i -> data[i] == max).toArray();
As i see your program goes through the array 2 times.You can try this:
Run through the array finding the max of this array.When you find a max just save every other element that is equal to the current max and their values.This way you only go through the array only once.
Here is an example: Let's say you have the following array {1,3,5,3,4,5} and you go through it.You will first save the 1 as max then the 3 then the 5 which is the max of this array.After saving 5 you won't save 3 or 4 but you will save 5 as it is equal to the max.Hope i helped.

Remove element from an array (code-specific)

The user enters x-amount of integers, which are stored in an array ('dataA'). The average of the data is calculated, and the element, which is furthest should be removed ('outlier'). I don't know how to remove the element and need to know.
Also, the program removes one outlier, it calculates the new average and removes the next outlier until there is one element left.
public static Scanner sc1 = new Scanner(System.in);
public static int dataN = sc1.nextInt();//number of data elements
public static double[] dataA = new double[dataN];//array storing elements
for(int index = 0; index<dataA.length; index++)//increments index
{
double lengthA = dataA.length;//length of array
double avg = sum/lengthA;//avg of elements
double outlier = dataA[0];//outlier
double index_outlier = 0;//index of outlier
double dif_in = Math.abs(avg - dataA[index]);//difference of avg & element
double dif_out = Math.abs(avg - outlier);//difference of avg & outlier
if(dif_in > dif_out)
{
outlier = dataA[index];
index_outlier = index;
}
You can try to swap the outlier with last element of Array and continue with array but consider one less element. In case you are fine with it then you can use Array like:
public static void main(String[] args) throws FileNotFoundException {
double[] dataArray = new double[] {1.5,2.5,3.5,4.5,7.5,8.5,2.5};
int arraySizeToConsider = dataArray.length;
double outlier;
int index_outlier;
double avg;
double diffInOutlierAndAvg;
while(arraySizeToConsider > 0) {
outlier = dataArray[0];
index_outlier = 0;
avg = computeSum(dataArray,arraySizeToConsider) / (arraySizeToConsider);//avg of elements
diffInOutlierAndAvg = Math.abs(avg - outlier);
// find outlier
for(int index = 0; index<arraySizeToConsider; index++)//increments index
{
if(Math.abs(avg - dataArray[index]) > diffInOutlierAndAvg) {
outlier = dataArray[index];
index_outlier = index;
}
}
double temp = dataArray[arraySizeToConsider -1];
dataArray[arraySizeToConsider -1] = outlier;
dataArray[index_outlier] = temp;
arraySizeToConsider = arraySizeToConsider -1;
System.out.println("Average: " + avg + " Outlier: " + outlier + " index " + index_outlier + " array size to consider: " +arraySizeToConsider);
}
}
private static double computeSum(double[] array, int arraySizeToConsider) {
double sum = 0;
for (int i = 0; i < arraySizeToConsider; i++) {
sum = sum + array[i];
}
return sum;
}
And here is the output:
Average: 4.357142857142857 Outlier: 8.5 index 5 array size to consider: 6
Average: 3.6666666666666665 Outlier: 7.5 index 4 array size to consider: 5
Average: 2.9 Outlier: 4.5 index 3 array size to consider: 4
Average: 2.5 Outlier: 1.5 index 0 array size to consider: 3
Average: 2.8333333333333335 Outlier: 3.5 index 2 array size to consider: 2
Average: 2.5 Outlier: 2.5 index 0 array size to consider: 1
Average: 2.5 Outlier: 2.5 index 0 array size to consider: 0
There are some more optimizations that I have left to you to figure out.
Hint: Do we need to compute sum every time we find an outlier ;)?
Best solution would be to create a new array that copies the elements from the previous one except for the one you want to delete (with a for loop and an array with 1 less space than yours) and then set your original array as the new one.
Since you need a variable size data structure use a LinkedList instead of primitive array.
Also a better solution to do this will be as follows:
1) Store all the values in a LinkedList. Sort it while add elements to the list using insertion sort or sort it after adding all elements using Collections.sort(list).
2) Find the average. This can be done while adding the elements in the list. No need to iterate over the list again.
3) Since all the values are in sorted manner, the outlier will be either the first or the last element in the LinkedList. Compare the diff_first and diff_last and remove the greater.
4) Recompute the average. For this you can use a very simple equation:
new_avg = ((avg*l)-outlier_value)/(l-1);
where l = number of values for which avg was calculated.
5) Repeat step 3 and 4 until only 1 element is left in the LinkedList.

How to find the smallest distance between two numbers next to each others in an array?

I have a sorted array. Let's say it is int [] numArr=new int[]{6, 9, 10, 27};
The smallest distance is between the 9 and the 10, and it is 1. The program should print this 1.
I am not expecting code, but I hope someone can give me an idea of how to proceed.
Declare a variable to hold the current minimum distance. It can be initialized to a really large number Integer.MAX_VALUE so that the first distance calculated becomes the initial minimum distance.
Use a for loop to loop over the values. You'll be accessing the element at the current index and the next index, so stop your for loop early to prevent an ArrayIndexOutOfBoundsException.
In the for loop, calculate the difference. If the difference is less than the current minimum, then update the current minimum to the current difference.
public static final int findSmallestDistance(final int[] pArray) {
int lMinimumDistance = Integer.MAX_VALUE;
for(int i = 1; i < pArray.length; i++) {
int lDifference = pArray[i] - pArray[i - 1];
if(lDifference < lMinimumDistance) {
lMinimumDistance = lDifference;
}
}
return lMinimumDistance;
}
Step 1: create a variable to save the actual smallest distance
Step 2: iterate through your array
Step 3: compare your actual number with the previous on your array (if this is the first element jump this step) and if it's smaller than your smallest save the result
Step 4: if the array has more elements, get the next one, else print your result
Here's some pseudocode:
Be smallest = a number surely greater than the one you're looking for
For each element i in array except the first
Be n = array[i] - array[i-1]
If n < smallest then
smallest = n
End If
End For
int numArr[] = {6, 9, 10, 27};
for(int i=0;i<numArr.length-1;i++){
if(numArr[i+1]-numArr[i]>0){
System.out.println("distance between " +numArr[i]+ " and "+numArr[i+1]+ " is: "+ (numArr[i+1]-numArr[i]));
}
}
int smallest = 100000
for (int i = 0; i < array.length; i++)
if(array[i+1]-array[i]<smallest)
{
smallest = array[i+1]-array[i];
}
System.out.println(smallest);

Categories

Resources