I am learning Java and wanted to find the contiguous sub-array with maximum sum. I am able to find it, but when I am going outside the for loop, the value of the sub-array saved in an ArrayList changes.
public class FindingSumOfContiguousSubArray {
//code for computing sum of an array list
public int getSum (ArrayList <Integer> arraylist ) {
int sum = 0;
for (int i=0; i<arraylist.size(); i++) {
sum += arraylist.get(i);
}
return sum;
}
private ArrayList<Integer> contigiousSubArray(int [] array){
ArrayList <Integer> finalList = new ArrayList<Integer>();
int n = array.length;
int minVal = -1000;
for(int i = 0; i<n; i++) {
ArrayList<Integer> aList = new ArrayList<Integer>(); //taking local object of ArrayList
for(int j = i; j<n; j++) {
aList.add(array[j]); //{-2, 1}
int sum = getSum(aList);
//System.out.println(minVal);
if (sum > minVal) {
minVal = sum;
//finalList.clear();
finalList = aList;
System.out.println(sum);
System.out.println(finalList);
}
else continue;
}
}
System.out.println(finalList);
return finalList;
}
public static void main(String[] args) {
FindingSumOfContiguousSubArray cSA = new FindingSumOfContiguousSubArray(); //creating class object
int [] inpArray = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
ArrayList <Integer> contFinalList = cSA.contigiousSubArray(inpArray);
//System.out.println(contFinalList);
//System.out.println(cSA.getSum(contFinalList));
}
}
This code gives output:
[1, -3, 4, -1, 2, 1]
5
[4, -1, 2]
6
[4, -1, 2, 1]
[4, -1, 2, 1, -5, 4]
I am not sure why my arraylist is showing [4, -1, 2, 1, -5, 4] outside the for loop.
I'm not exactly sure what you're looking for here, but maybe try this (you don't need your summing method this way):
private static List<Integer> contigiousSubArray(int [] array){
List<Integer> finalList = new ArrayList<>();
int minVal = Integer.MIN_VALUE;
for(int i = 0; i < array.length; i++) {
List<Integer> aList = new ArrayList<Integer>(); //taking local object of ArrayList
for(int j = i; j < array.length; j++) {
aList.add(array[j]); //{-2, 1}
int sum = aList.stream()
.collect(Collectors.summingInt(Integer::intValue));
//System.out.println(minVal);
if (sum > minVal) {
minVal = sum;
finalList.clear();
finalList.addAll(aList);
}
}
}
return finalList;
}
try this :
public int contigiousSubArray(int[] arr) {
int[] result = new int[arr.length];
result[0]=arr[0];
for (int i = 1; i < arr.length; i++) {
result[i]=Math.max(result[i-1]+arr[i], arr[i]);
}
int maxSumArray = result[0];
for (int j = 1; j if(maxSumArray<result[j])
maxSumArray = result[j];
}
return maxSumArray;
}```
Related
I have the following input
int combinationCount = 3;
int arr[] = {1, 1, 2, 2, 3};
combinationCount is {1,2,3}, combinationCount defines the number of sequence of number. For Eg: combinationCount = 3 means {1,2,3} and combinationCount = 2 means {1,2}
Array is always sorted, I want to print the output as the number of combinations as follow
[1,2,3], [1,2,3], [1,2,3], [1,2,3] //I have to iterate the whole array as it is just logic for a problem
Output Explanation (I want to print values, not index):
This is just an explanation of output which shows the index position of the value printed.
Index position of each value
[0, 2, 4], [0, 3, 4], [1, 2, 4], [1, 3, 4]
Example 2
int combinationCount = 2; // means combination is {1,2}
int arr[] = {1, 2, 2};
Print: [1,2], [1,2]
Example 3
int combinationCount = 3; // means combination is {1,2,3}
int arr[] = {1, 1, 3};
Print nothing
The program which I written is as follow:
int combinationCount = 3;
int arr[] = {1, 1, 2, 2, 3};
List<Integer> list = new ArrayList<>();
int prev = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 1) {
prev = 1;
list = new ArrayList<>();
list.add(1);
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] == prev + 1) {
prev = arr[j];
list.add(arr[j]);
} else if (arr[j] > (prev + 1)) {
break;
}
}
if (list.size() == combinationCount) {
System.out.print(list + ",");
}
} else {
break;
}
}
Output coming as
[1,2,3],[1,2,3]
which is not correct
Somewhere I am missing loop and how optimized code we can write? Any suggestions pls. Kindly let me know for any concern.
You can use Cartesian Product. I have used this answer as reference.
public class Test {
public static List<List<Integer>> product(List<List<Integer>> lists) {
List<List<Integer>> result = new ArrayList<>();
int solutions = lists.stream().mapToInt(List::size).reduce(1, (a, b) -> a * b);
for (int i = 0; i < solutions; i++) {
int j = 1;
List<Integer> tempList = new ArrayList<>();
for (List list : lists) {
tempList.add((Integer) list.get((i / j) % list.size()));
j *= list.size();
}
result.add(tempList);
}
return result;
}
public static void main(String[] args) {
int combinationCount = 2, count = 0;
int arr[] = {1, 1, 3};
Map<Integer, List<Integer>> map = new HashMap<>();
List<List<Integer>> combinations = new ArrayList<>();
for (Integer idx = 0; idx < arr.length; idx++) {
map.computeIfAbsent(arr[idx], k -> new ArrayList<>()).add(idx);
}
for (int i = 1; i <= combinationCount; i++) {
if (map.getOrDefault(i, null) != null)
count += 1;
}
if (count == combinationCount) {
List result = product(new ArrayList(map.values()));
System.out.println(result);
} else {
System.out.println("No combination found");
}
}
}
Output:
No combination found
I have this input of array: int[] input = {1,3,2,2,33,1}; I need to make score for it like this output: {1,3,2,2,4,1} so the smallest number gets 1 and if there is smaller it gets 2 an so on.
another example: for input {1,10,3,44,5,2,5} -outputs-> {1,5,3,6,4,2,4}
This is my try but it does not work as expected.
public static int[] getRanksArray(int[] array) {
int[] result = new int[array.length];
for (int i = 0; i < array.length; i++) {
int count = 0;
for (int j = 0; j < array.length; j++) {
if (array[j] != array[i]) {
count++;
}
}
result[i] = count + 1;
}
return result;
}
Edit: Updated to handle double rather than int input array.
First sort an array representing indices of the input array. Then walk through this array incrementing a rank counter whenever you encounter successive elements that are not equal (ideone)
public static int[] rank(double[] nums)
{
Integer[] idx = new Integer[nums.length];
for(int i=0; i<idx.length; i++) idx[i] = i;
Arrays.sort(idx, (a, b) -> (Double.compare(nums[a], nums[b])));
// Or use this for descending rank
// Arrays.sort(idx, (a, b) -> (Double.compare(nums[b], nums[a])));
int[] rank = new int[nums.length];
for(int i=0, j=1; i<idx.length; i++)
{
rank[idx[i]] = j;
if(i < idx.length - 1 && nums[idx[i]] != nums[idx[i+1]]) j++;
}
return rank;
}
Test:
System.out.println(Arrays.toString(rank(new double[] {1,3,2,2,33,1})));
System.out.println(Arrays.toString(rank(new double[] {1,10,3,44,5,2,5})));
Output:
[1, 3, 2, 2, 4, 1]
[1, 5, 3, 6, 4, 2, 4]
This can be solved using a sorted map storing lists/sets of indexes mapped by the values of the input array.
Then you can iterate over this map and fill the rank array with incrementing indexes.
Implementation:
public static int[] rank(int[] arr) {
TreeMap<Integer, List<Integer>> map = new TreeMap<>();
for (int i = 0; i < arr.length; i++) {
List<Integer> indexes = map.compute(arr[i], (k, v) -> v == null ? new ArrayList<>() : v);
indexes.add(i);
map.putIfAbsent(arr[i], indexes);
}
int[] rank = new int[arr.length];
int id = 1;
for (Map.Entry<Integer, List<Integer>> entry : map.entrySet()) {
for(Integer i : entry.getValue()) {
rank[i] = id;
}
id++;
}
return rank;
}
Test:
int[][] d = {
{1,3,2,2,33,1},
{1,10,3,44,5,2,5}
};
for (int[] input : d) {
System.out.println(Arrays.toString(rank(input)));
}
output:
[1, 3, 2, 2, 4, 1]
[1, 5, 3, 6, 4, 2, 4]
This post - "Java + Count duplicates from int array without using any Collection or another intermediate Array", was also a sample exercise in my book at school, but what I want to do is get the elements that has duplicates without sorting it.
What I did is I removed the duplicates of arrays first, to get only the unique elements and then I compare it to the original array and count how many times the element has been found. But the problem is it doesn't print the correct elements which has duplicates.
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
the correct output should be: 7, 1, 4
but instead it outputs: 7, 6, 1
This is my codes:
//method for removing duplicates
public static int[] removeDuplicates(int[] n) {
int limit = n.length;
for(int i = 0; i < limit; i++) {
for(int j = i + 1; j < limit; j++) {
if(n[i] == n[j]) {
for(int k = j; k < limit - 1; k++) {
n[k] = n[k + 1];
}
limit--;
j--;
}
}
}
int[] uniqueValues = new int[limit];
for(int i = 0; i < uniqueValues.length; i++) {
uniqueValues[i] = n[i];
}
return uniqueValues;
}
//method for getting elements that has duplicates
public static int[] getDuplicatedElements(int[] n) {
int[] nCopy = n.clone();
int[] u = removeDuplicates(nCopy);
int count = 0;
int limit = u.length;
for(int i = 0; i < u.length; i++) {
for(int j = 0; j < n.length; j++) {
if(u[i] == n[j]) {
count++;
}
}
if(count == 1) {
for(int k = i; k < limit - 1; k++) {
u[k] = u[k + 1];
}
limit--;
}
count = 0;
}
int[] duplicated = new int[limit];
for(int i = 0; i < duplicated.length; i++) {
duplicated[i] = u[i];
}
return duplicated;
}
//main
public static void main(String[] args) {
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
//printing original values
System.out.print(Arrays.toString(num));
System.out.println();
int[] a = getDuplicatedElements(num);
System.out.print("Elements with Duplicates: " + Arrays.toString(a));
}
What's the error in my codes here? Please help thanks...
You have two issues:
public static int[] getDuplicatedElements(int[] n) {
int[] nCopy = n.clone();
int[] u = removeDuplicates(nCopy);
System.out.println ("unique " + Arrays.toString (u));
int count = 0;
int limit = u.length;
for(int i = 0; i < limit; i++) { // you must use limit instead of u.length
// in order for the loop to terminate
for(int j = 0; j < n.length; j++) {
if(u[i] == n[j]) {
count++;
}
}
if(count == 1) {
for(int k = i; k < limit - 1; k++) {
u[k] = u[k + 1];
}
limit--;
i--; // you must decrement i after you find a unique element in u
// otherwise you'll be skipping elements in the u array
}
count = 0;
}
int[] duplicated = new int[limit];
for(int i = 0; i < duplicated.length; i++) {
duplicated[i] = u[i];
}
return duplicated;
}
With those fixes, you'll get the expected output:
Elements with Duplicates: [7, 1, 4]
It's fairly simple when using a stream
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
List<Integer> list = Arrays.stream(num).boxed().collect(Collectors.toList());
list.stream().filter(i -> Collections.frequency(list, i) > 1)
.collect(Collectors.toSet()).forEach(System.out::println);
Array with duplicates [4,4,1]. Find pairs with sum 5 in O(n).
Expected output (4,1) and (4,1) and count is 2.
Approach#1:
Using HashSet:
public static int twoSum(int[] numbers, int target) {
HashSet<Integer> set = new HashSet<Integer>();
int c = 0;
for(int i:numbers){
if(set.contains(target-i)){
System.out.println(i+"-"+(target-i));
c++;
}
set.add(i);
}
return c;
}
Output is 1.
Approach #2 as stated in this link:
private static final int MAX = 100000;
static int printpairs(int arr[],int sum)
{
int count = 0;
boolean[] binmap = new boolean[MAX];
for (int i=0; i<arr.length; ++i)
{
int temp = sum-arr[i];
if (temp>=0 && binmap[temp])
{
count ++;
}
binmap[arr[i]] = true;
}
return count;
}
Output 1.
However the O(nlog n) solution is using sorting the array:
public static int findPairs(int [] a, int sum){
Arrays.sort(a);
int l = 0;
int r = a.length -1;
int count = 0;
while(l<r){
if((a[l] + a[r]) == sum){
count ++;
System.out.println(a[l] + " "+ a[r]);
r--;
}
else if((a[l] + a[r])>sum ){
r--;
}else{
l++;
}
}
return count;
}
Can we get the solution in O(n)?
You can use your second approach - just change boolean to int:
public static void main(String[] args) {
System.out.println(printPairs(new int[]{3, 3, 3, 3}, 6)); // 6
System.out.println(printPairs(new int[]{4, 4, 1}, 5)); // 2
System.out.println(printPairs(new int[]{1, 2, 3, 4, 5, 6}, 7)); // 3
System.out.println(printPairs(new int[]{3, 3, 3, 3, 1, 1, 5, 5}, 6)); // 10
}
public static int printPairs(int arr[], int sum) {
int count = 0;
int[] quantity = new int[sum];
for (int i = 0; i < arr.length; ++i) {
int supplement = sum - arr[i];
if (supplement >= 0) {
count += quantity[supplement];
}
quantity[arr[i]]++; // You may need to check that arr[i] is in bounds
}
return count;
}
you can try this also
Map<Integer, List> map = new HashMap<>();
int count = 0;
for (int i = 0; i < arr.length; i++) {
if (map.containsKey(k - arr[i])) {
count += map.get(k - arr[i]).size();
}
List<Integer> test = map.getOrDefault(arr[i], new ArrayList<>());
test.add(i);
map.put(arr[i], test);
}
return count;
Here is an O(N) Time & Space approach using HashMap.
class Solution
{
static int getPairsCount(int[] arr, int n, int target)
{
HashMap<Integer,Integer> map = new HashMap<>();
int pairs=0;
for (int i=0; i<n; i++)
{
if (map.containsKey(target - arr[i]))
{
pairs += map.get(target - arr[i]);
for (int j=1; j<=map.get(target - arr[i]); j++)
System.out.print("(" +(target-arr[i])+ "," +arr[i]+ ") ");
}
map.put(arr[i] , map.getOrDefault(arr[i],0)+1);
}
return pairs;
}
public static void main (String [] args)
{
int target = 5;
int [] input = {4, 4, 1};
System.out.println(getPairsCount(input , input.length , target));
target = 10;
input = new int [] {1, 6, 3, 2, 5, 5, 7, 8, 4, 8, 2, 5, 9, 9, 1};
System.out.println(getPairsCount(input , input.length , target));
}
}
Output:
2 (Pairs)
(4,1) (4,1)
13 (Pairs)
(5,5) (3,7) (2,8) (6,4) (2,8) (8,2) (8,2) (5,5) (5,5) (1,9) (1,9) (9,1) (9,1)
How would one go about filling in an array so that, for example, if you had the following array.
int[] arr = new int[5];
arr[0] = 1;
arr[1] = 3;
arr[2] = 7;
arr[3] = 2;
arr[4] = -4;
so it would look like
arr = {1, 3, 7, 2, -4};
and you would pass it into your method to get a result of
arr = {1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4};
so that you essentially are filling in the numeric gaps. I'd like to make this under the assumption that I don't know how long the array passed in is going to be to make it a more universal method.
my current method looks like such right now...
public static void fillArray(int[] numbers){
int length = numbers.length;
for(int i = 0; i < numbers.length - 1; i ++){
if(numbers[i] <= numbers[i + 1]){
length += numbers[i + 1] - numbers[i];
}else if(numbers[i + 1] < numbers[i]){
length += numbers[i + 1] - numbers[i];
}
}
}
I have length to determine the size of my new array. I think it should work but I'm always down for some input and advice.
Looks like homework, providing algorithm only:
Navigate through the elements of the current array.
Get the distance (absolute difference) between the elements in the array.
Summarize the distances.
Create a new array whose length would be the sum of the distances.
Fill the new array using the elements of the first array and filling the gaps.
Return the array.
Like Luiggi Mendoza said, looks like HW, so here's another algorithm:
insert the first element into a list of integers.
loop on the rest of the elements.
for each two array elements X[i-1], X[i], insert the missing integers to the list
after the loop - use guava to turn the List to array.
This works. just check for array size < 2 for safety.
public static void main(String[] args) {
int[] arr = {1, 3, 7, 2, -4};
Integer[] result = fillArray(arr);
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
}
private static Integer[] fillArray(int[] arr) {
List<Integer> list = new ArrayList<Integer>();
list.add(arr[0]);
for (int i = 1; i < arr.length; i++) {
int prevItem = arr[i-1];
int gap = arr[i] - prevItem;
if(gap > 0){
fillGap(list, prevItem, gap, 1);
} else if(gap < 0){
fillGap(list, prevItem, gap, -1);
}
}
return list.toArray(new Integer[0]);
}
private static void fillGap(List<Integer> list, int start, int gap, int delta) {
int next = start+delta;
for (int j = 0; j < Math.abs(gap); j++) {
list.add(next);
next = next+delta;
}
}
Try
import java.util.ArrayList;
import java.util.List;
public class ArrayGap {
public static void main(String[] args) {
int[] arr = {1, 3, 7, 2, -4};
int high, low;
List<Integer> out = new ArrayList<Integer>();
for(int i=0; i<arr.length - 1; i++){
high = arr[i];
if(arr[i] < arr[i+1]){
for(int j=arr[i]; j<arr[i+1]; j++){
out.add(j);
}
} else {
for(int j=arr[i]; j>=arr[i+1]; j--){
out.add(j);
}
}
}
System.out.println(out);
}
}