How to remove duplicated list from a list of list? - java

Is there some elegant ways to remove duplicated list (list with same values) from a list of list?
I tried with Set<List<Integer>> but it's not working, it still shows the duplicated lists. It seems that Set only checks the object reference.
the example code:
int[] nums = {-1, 0, 1, 2, -1, -4};
Set<List<Integer>> set = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
set.add(Arrays.asList(nums[i], nums[j], nums[k]));
}
}
}
}
then the set will contain 3 elements but two of them have the same values.

A repair:
record Triple(int x, int y, int z) {};
int[] nums = {-1, 0, 1, 2, -1, -4};
Set<Triple> set = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
set.add(new Triple(nums[i], nums[j], nums[k]));
}
}
}
}
However the algorithm is suboptimal O(n³).
record Triple(int x, int y, int z) {};
int[] nums = {-1, 0, 1, 2, -1, -4};
Arrays.sort(nums);
Set<Triple> set = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
int numI = num[i];
for (int j = i + 1; j < nums.length; j++) {
int numJ = num[j];
int numK = -(numI + numK);
int k = Arrays.binarySearch(nums, j + 1, nums.length, numK);
if (k >= 0) { // Found
set.add(new Triple(numI, numJ, numK));
}
}
}
binarySearch delivers a non-negative index when it finds the search key. When negative, it delivers the 1s complement of the "insert" position.
This has complexity O(n².log n). You determine the found resp. insert position in the for-i loop and in the for-j loop decrement k a couple of times to find the sum. That would not be difficult but less readable.
Mind the resulting numbers are ordered.

Related

Find the most common value from a 2D integer array

I am looking for the most common value from the 2D array and how many times it occurs. I tried this solution but it's not working. I tried searching but not able to find a proper example. Please help me solve this problem.
Here is my code:
private void commonElevation(int[][] data) {
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (i + 1 < data.length) {
if (data[i][j] == data[i + 1][j]) {
System.out.println(data[i][j] + " = " + data[i + 1][j]);
}
}
}
}
}
You could use the Stream API:
int[][] data = {{1, 2, 3}, {2, 2, 2}, {4, 5, 6}};
Map<Integer, Long> counts = Arrays.stream(data).flatMapToInt(Arrays::stream).boxed()
.collect(groupingBy(Function.identity(), counting()));
Optional<Map.Entry<Integer, Long>> max = counts.entrySet().stream().max(Comparator.comparing(Map.Entry::getValue));
max.ifPresent(System.out::println);
Output
2=4
Given the new constraints a brute-force approach will work:
// find the maximum
int value = 0, max = Integer.MIN_VALUE;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
// search for counts
int currentCount = 0;
for (int k = 0; k < data.length; k++) {
for (int l = 0; l < data[k].length; l++) {
if(data[k][l] == data[i][j]) {
currentCount++;
}
}
}
if (currentCount > max) {
value = data[i][j];
max = currentCount;
}
}
}
System.out.println(value + "=" + max);
Output
2=4
Basically iter over all values and count the appearances of each of those values. This approach (brute-force) is very inefficient.
One possibility would be to use a hash map to keep track of the values along with the number of times each occurs:
private void commonElevation(int[][] data) {
Map<Integer, Integer> counts = new HashMap<>();
for (int i=0; i < data.length; i++) {
for (int j=0; j < data[i].length; j++) {
int count = counts.get(data[i][j]) == null ? 0 : counts.get(data[i][j]);
counts.put(data[i][j], ++count);
}
}
int frequent = Integer.MIN_VALUE;
for (Integer value : counts.values()) {
if (value > frequent) frequent = value;
}
System.out.println("most frequent value is: " + frequent);
}

Calculate total number of combinations of size k in array using recursion in Java?

I am attempting to write a recursive method that COUNTS the number of combinations of k size in an integer array.
I can easily do this for a known value k (e.g. 3) as so:
int[] arr = {1,2,3,4};
int count = 0;
for(int i = 0; i < arr.length; i++) {
for(int j = i+1; j < arr.length; j++) {
for(int k = j+1; k < arr.length; k++) {
count++;
}
}
}
However, I would like to be able to do this without a known k. I have found methods online that print the combinations using recursion, such as this one:
https://www.techiedelight.com/find-distinct-combinations-of-given-length/, but none that count them.
Simple case of modifying the method linked.
public static int recur(int[] A, int i, int k)
{
int count = 0;
if (k == 0) {
count++;
}
for (int j = i; j < A.length; j++) {
count = count + recur(A, j + 1, k - 1);
}
return count;
}

HackerRank closest number

Given a list of unsorted integers, find the pair of elements that have the smallest absolute difference between them. If there are multiple pairs, find them all.
My reasoning was to compare each: arr[j] - arr[i] with lowest and if it is smaller or equal to that, add that value to the array lowest, but it's not working.
Code:
static int[] closestNumbers(int[] arr) {
int lowest = arr[1] - arr[0];
int lowestArray[] = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (Math.abs(arr[j] - arr[i]) < lowest) {
lowest = Math.abs(arr[j] - arr[i]);
}
}
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] == lowest) {
lowestArray[i] = arr[i];
}
}
return lowestArray;
}
Below is the required code:-
import java.util.*;
class GFG
{
// Returns minimum difference between
// any two pair in arr[0..n-1]
static void printMinDiffPairs(int arr[], int n)
{
if (n <= 1)
return;
// Sort array elements
Arrays.sort(arr);
// Compare differences of adjacent
// pairs to find the minimum difference.
int minDiff = arr[1] - arr[0];
for (int i = 2; i < n; i++)
minDiff = Math.min(minDiff, arr[i] - arr[i-1]);
// Traverse array again and print all pairs
// with difference as minDiff.
for ( int i = 1; i < n; i++)
{
if ((arr[i] - arr[i-1]) == minDiff)
{
System.out.print("(" + arr[i-1] + ", "
+ arr[i] + ")," );
}
}
}
// Driver code
public static void main (String[] args)
{
int arr[] = {5, 3, 2, 4, 1};
int n = arr.length;
printMinDiffPairs(arr, n);
}
}
Does above program handle duplicates?
The cases like {x, x, x} are not handled by above program. For this case, the expected output (x, x), (x, x), (x, x), but above program prints (x, x), (x, x)
The problem is that when you initialize your lowest array like this,
int[] lowest = new int[arr.length];
you are actually initializing it with zeros. Also, whenever you are taking arr[j]-arr[i], it will always be greater than or equal to zero (since your array is sorted in an ascending fashion), leading to incorrect results because the following if statement,
if(Math.abs(arr[j] - arr[i]) <= lowest[l]) {
lowest[l] = Math.abs(arr[j] - arr[i]);
}
will never execute for differences greater than 0.
Initialize the lowest array like so,
for(int i=0;i<lowest.length;i++){
lowest[i] = Integer.MAX_VALUE;
}
Also, your outer loop for the i variable starts with i=1, but it should start with i=0
static int[] closestNumbers(int[] arr) {
int minAbs = Integer.MAX_VALUE;
Arrays.sort(arr);
int[] out = new int[(arr.length) + 3];
int j = 0;
for (int i = 1; i < arr.length; i++) {
minAbs = Math.min(minAbs, Math.abs(arr[i] - arr[i - 1]));
}
for (int i = 1; i < arr.length; i++) {
if(minAbs ==Math.abs(arr[i] - arr[i - 1])) {
out[j++]=arr[i - 1];
out[j++]=arr[i];
}
}
int[] tem= new int[j];
for(int i=0; i<j;i++) {
tem[i]=out[i];
}
return tem;
}

matrix max sum finding by removing the almost one row or almost one column

Given a matrix with m-rows and n-columns, finding the maximum sum of
elements in the matrix by removing almost one row or one column
Example:
m=2, n=3
matrix :
**[[1,2,-3]
[4,5,-6 ]
]**
output: 12 , by removing the third column then sum of elements in
[[1,2][4,5]]
How to solve this problem in java8 using dynamic programming
Based on the kadane algorithm, below code works fine
public static void main(String[] args) {
int[][] m = {
{1, 2, -3},
{4, 5, -5},
};
int N = m.length;
for (int i = 0; i < N; ++i)
m[0][i] = m[0][i];
for (int j = 1; j < N; ++j)
for (int i = 0; i < N; ++i)
m[j][i] = m[j][i] + m[j - 1][i];
int totalMaxSum = 0, sum;
for (int i = 0; i < N; ++i) {
for (int k = i; k < N; ++k) {
sum = 0;
for (int j = 0; j < N; j++) {
sum += i == 0 ? m[k][j] : m[k][j] - m[i - 1][j];
totalMaxSum = Math.max(sum, totalMaxSum);
}
}
}
System.out.println(totalMaxSum);
}

Java: Generating a custom sets of elements

I need a simple java program that can generate me the custom sets for a set,say for {'1','2','3','4'}. The result should be:
{'1','2'},{'2','3'},{'3','4'},{'1','2','3'},{'2','3','4'}.
I have tried codes for powerset,but the output isn't desirable. It would be appreciable if the code could be something like:
for(j=2;j<set.size()-1;j++)
{
for(i=0;i<set.size()-1;i++)
{
//a[i],a[i+1] when j=2
//a[i],a[i+1],a[i+2] when j=3
}
}
I know .size() is for ArrayList and a[i] is for simple array and i've written both as any approach will do!! Thanks In Advance!! :)
This code should print the values you want:
final int[] values = {1, 2, 3, 4};
for (int size = 2; size < values.length; size++) {
for (int i = 0; i + size <= values.length; i++) {
for (int j = 0; j <= size - 1; j++) {
System.out.print(values[i + j]);
}
System.out.println();
}
}
From the example, we see that you want to print sets of values whose length is greater than 1 and smaller than the total set, so that 's what the following line does:
for (int size = 2; size < values.length; size++) {
After that we compute the starting index of the subset, watching not to run into a IndexArrayOutOfBounds exception (see the line below)
for (int i = 0; i + size <= values.length; i++) {
From there we just print the values starting at i index and with the subset length of size
for (int j = 0; j <= size - 1; j++)
This is the sample code which is generating the desired result:
int[] array = { 1, 2, 3, 4 };
int size = 2;
for (int j = 0; j < array.length; j++) {
for (int i = 0; i <= array.length - size; i++) {
int[] temp = Arrays.copyOfRange(array, i, i + size);
for (int x : temp) {
System.out.print(x + ",");
}
System.out.println();
}
size++;
if (size == array.length) {
break;
}
}
Output:
1,2,
2,3,
3,4,
1,2,3,
2,3,4,

Categories