I am not using HeapSort to sort an array that is already filled, but am using HeapSort as the array is filled.
For a heap where the smallest values are at the top, my understanding was that when you insert a new value to the heap you checked the parent node to see if the new child is larger. If it is you do nothing, if it isn't you check and swap as need up the tree?
Is this not right because my implementation of it is not working at all:
public class HeapSort{
static int[] numbers = new int[] { 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
static int[] array = new int[16];
public static void main(String[] args) {
for (int i = 1; i < 15; i++) {
array[i] = numbers[i];
if (i > 1)
sort(i);
}
for (int i = 1; i < 15; i++) {
System.out.println(array[i]);
}
}
public static void sort(int i) {
int parentLocation = i / 2;
int childLocation = i;
int parentValue = array[parentLocation];
int childValue = array[childLocation];
if(parentValue > childValue){
array[parentLocation] = childValue;
array[childLocation] = parentValue;
}
if(parentLocation != 1){
sort(parentLocation);
}
}
}
TIA
If its anyhelp this is the output when I give it 1-15 backwards:
2
6
3
9
7
5
4
15
12
13
8
14
10
11
But you all seem as stumped as I am!
It looks like your not sorting the entire array. Say that you have 10 fields correctly sorted and you insert number. So you have
-, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11 and insert 10 (should go second last and the - is cause you never put anything there)
Now your algorithm compares parentLocation 5 (11/2) and childLocation 11 right? Well, 5 is smaller than 11 so nothing is swapped. Then you continue to sort again with input 5.
This time you compare parentLocation 2 (5/2) and childLocation 5. 2 is smaller than 5, still not change.
Until done. But you never test to see if 10 and 11 is in the correct order at all, you start half way down.
Easiest fix is to change your two iterations to
for (int i = 1; i < numbers.length; i++) {...}
...
for (int i = 1; i < array.length; i++) {...}
As your missing the end positions in your current code.
Then change the first line in sort() to
int parentLocation = i - 1;
That way your recursive check checks the entire array.
But this is regular sorting, nothing heapy about it :)
Added complete new solution :)
I'm sure this is not the optimal solution but it's easy to follow. I've replaced the target heap with an ArrayList to be able to shrink it easy.
package se.wederbrand.stackoverflow;
import java.util.ArrayList;
public class HeapSort {
static int[] numbers = new int[]{0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
static ArrayList<Integer> heap = new ArrayList<Integer>();
public static void main(String[] args) {
// add 0 at the first position
heap.add(0);
for (int i = 1; i < numbers.length; i++) {
heap.add(numbers[i]);
if (i > 1) {
reheapifyBottomUp(i);
}
}
while (heap.size() > 1) {
System.out.println(removeFirstFromHeap());
}
}
private static int removeFirstFromHeap() {
// the value at index 1 should be returned
int returnValue = heap.get(1);
// the last node is replacing the removed one
if (heap.size() > 2) {
heap.set(1, heap.remove(heap.size() - 1));
reheapifyTopDown(1);
}
else {
heap.remove(1);
}
return returnValue;
}
public static void reheapifyBottomUp(int childLocation) {
int parentLocation = childLocation / 2;
int parentValue = heap.get(parentLocation);
int childValue = heap.get(childLocation);
if (parentValue > childValue) {
heap.set(parentLocation, childValue);
heap.set(childLocation, parentValue);
}
if (parentLocation != 1) {
reheapifyBottomUp(parentLocation);
}
}
public static void reheapifyTopDown(int parentLocation) {
int childLocation1 = parentLocation * 2;
int childLocation2 = childLocation1 + 1;
int parentValue = heap.get(parentLocation);
int childValue1 = Integer.MAX_VALUE;
if (heap.size() > childLocation1) {
childValue1 = heap.get(childLocation1);
}
int childValue2 = Integer.MAX_VALUE;
if (heap.size() > childLocation2) {
childValue2 = heap.get(childLocation2);
}
if (childValue1 <= childValue2 && parentValue > childValue1) {
// swap them and continue down
heap.set(parentLocation, childValue1);
heap.set(childLocation1, parentValue);
reheapifyTopDown(childLocation1);
}
else if (childValue2 < childValue1 && parentValue > childValue2) {
// swap them and continue down
heap.set(parentLocation, childValue2);
heap.set(childLocation2, parentValue);
reheapifyTopDown(childLocation2);
}
}
}
All you have done here is add a bunch of numbers to a heap (which looks correct at first glance). The array contains values in a heap -- not a sorted list. To get the sorted list out, in heap sort, you need to keep popping the smallest element and re-heaping. You're missing this step; you're just printing out the final heap before you start that process.
Your sort method should be renamed as heapify(). Your current sort() method is just re-arranging the heap.
A min/max heap is never sorted, and hence you can never traverse it the way you can traverse Binary Search Tree. You will have to implement something like removeMin() which will remove the topmost element from the heap and the sort the remaining heap.
Related
I want to remove the duplicates by putting them in a new array but somehow I only get a first instance and a bunch of zeros.
Here is my code:
public class JavaApplication7 {
public static void main(String[] args) {
int[] arr = new int[] {1,1,2,2,2,2,3,4,5,6,7,8};
int[] res = removeD(arr);
for (int i = 0; i < res.length; i++) {
System.out.print(res[i] + " ");
}
}
public static int[] removeD(int[] ar) {
int[] tempa = new int[ar.length];
for (int i = 0; i < ar.length; i++) {
if (ar[i] == ar[i+1]) {
tempa[i] = ar[i];
return tempa;
}
}
return null;
}
}
expected: 1,2
result: 1,0,0,0,0,0,0....
why dont you make use of HashSet?
final int[] arr = new int[] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8 };
final Set<Integer> set = new HashSet<>();
for (final int i : arr) {
// makes use of Integer's hashCode() and equals()
set.add(Integer.valueOf(i));
}
// primitive int array without zeros
final int[] newIntArray = new int[set.size()];
int counter = 0;
final Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
newIntArray[counter] = iterator.next().intValue();
counter++;
}
for (final int i : newIntArray) {
System.out.println(i);
}
Edit
if you want your array to be ordered
final int[] arr = new int[] { 9, 9, 8, 8, 1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8 };
Set<Integer> set = new HashSet<>();
for (final int i : arr) {
// makes use of Integer's hashCode() and equals()
set.add(Integer.valueOf(i));
}
// priomitive int array without zeros
final int[] newIntArray = new int[set.size()];
int counter = 0;
// SetUtils.orderedSet(set) requires apache commons collections
set = SetUtils.orderedSet(set);
final Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
newIntArray[counter] = iterator.next().intValue();
counter++;
}
for (final int i : newIntArray) {
System.out.println(i);
}
A couple of points to help you:
1) With this: for(int i =0; i<ar.length; i++){ - you will get an IndexOutOfBoundsException because you are checking [i+1]. Hint: it is only the last element that will cause this...
2) Because you're initialising the second array with the length of the original array, every non-duplicate will be a 0 in it, as each element is initialised with a 0 by default. So perhaps you need to find how many duplicates there are first, before setting the size.
3) As mentioned in the comments, you are returning the array once the first duplicate is found, so remove that and just return the array at the end of the method.
4) You will also get multiple 2s because when you check i with i+1, it will find 3 2s and update tempa with each of them, so you'll need to consider how to not to include duplicates you've already found - based on your expected result.
These points should help you get the result you desire - if I (or someone else) just handed you the answer, you wouldn't learn as much as if you researched it yourself.
Here:
int[] tempa = new int[ar.length];
That creates a new array with the same size as the incoming one. All slots in that array are initialized with 0s!
When you then put some non-0 values into the first slots, sure, those stick, but so do the 0s in all the later slots that you don't "touch".
Thus: you either have to use a data structure where you can dynamically add new elements (like List/ArrayList), or you have to first iterate the input array to determine the exact count of objects you need, to then create an appropriately sized array, to then fill that array.
Return statement
As both commenters said, you return from the method as soon as you find your first duplicate. To resolve that issue, move the return to the end of the method.
Index problems
You will then run into another issue, an ArrayIndexOutOfBoundsException because when you are checking your last item (i = ar.length - 1) which in your example would be 11 you are then comparing if ar[11] == ar[12] but ar has size 12 so index 12 is out of the bounds of the array. You could solve that by changing your exit condition of the for loop to i < ar.length - 1.
Zeros
The zeros in your current output come from the initialization. You initialize your tempa with int[ar.length] this means in the memory it will reserve space for 12 ints which are initialized with zero. You will have the same problem after resolving both issues above. Your output would look like this: 1 0 2 2 2 0 0 0 0 0 0 0. This is because you use the same index for tempa and ar. You could solve that problem in different ways. Using a List, Filtering the array afterwards, etc. It depends what you want to do exactly.
The code below has the two first issues solved:
public class JavaApplication7 {
public static void main(String[] args) {
int[] arr = new int[] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8 };
int[] res = removeD(arr);
for (int i = 0; i < res.length; i++) {
System.out.print(res[i] + " ");
}
}
public static int[] removeD(int[] ar) {
int[] tempa = new int[ar.length];
for (int i = 0; i < ar.length - 1; i++) {
if (ar[i] == ar[i + 1]) {
tempa[i] = ar[i];
}
}
return tempa;
}
}
There were a some error mentioned already:
return exits the method.
with arr[i+1] the for condition should bei+1 < arr.length`.
the resulting array may be smaller.
So:
public static int[] removeD(int[] ar) {
// Arrays.sort(ar);
int uniqueCount = 0;
for (int i = 0; i < ar.length; ++i) {
if (i == 0 || ar[i] != ar[i - 1]) {
++uniqueCount;
}
}
int[] uniques = new int[uniqueCount];
int uniqueI = 0;
for (int i = 0; i < ar.length; ++i) {
if (i == 0 || ar[i] != ar[i - 1]) {
uniques[uniqueI] = arr[i];
++uniqueI;
}
}
return uniques;
}
I am trying to make a code with two arrays. The second array has the same values of the first except for the smallest number. I have already made a code where z is the smallest number. Now I just want to make a new array without z, any feedback would be appreciated.
public static int Second_Tiny() {
int[] ar = {19, 1, 17, 17, -2};
int i;
int z = ar[0];
for (i = 1; i < ar.length; i++) {
if (z >ar[i]) {
z=ar[i];
}
}
}
Java 8 streams have built in functionality that can achieve what you're wanting.
public static void main(String[] args) throws Exception {
int[] ar = {19, 1, 17, 17, -2, -2, -2, -2, 5};
// Find the smallest number
int min = Arrays.stream(ar)
.min()
.getAsInt();
// Make a new array without the smallest number
int[] newAr = Arrays
.stream(ar)
.filter(a -> a > min)
.toArray();
// Display the new array
System.out.println(Arrays.toString(newAr));
}
Results:
[19, 1, 17, 17, 5]
Otherwise, you'd be looking at something like:
public static void main(String[] args) throws Exception {
int[] ar = {19, 1, 17, 17, -2, -2, -2, -2, 5};
// Find the smallest number
// Count how many times the min number appears
int min = ar[0];
int minCount = 0;
for (int a : ar) {
if (minCount == 0 || a < min) {
min = a;
minCount = 1;
} else if (a == min) {
minCount++;
}
}
// Make a new array without the smallest number
int[] newAr = new int[ar.length - minCount];
int newIndex = 0;
for (int a : ar) {
if (a != min) {
newAr[newIndex] = a;
newIndex++;
}
}
// Display the new array
System.out.println(Arrays.toString(newAr));
}
Results:
[19, 1, 17, 17, 5]
I think the OP is on wrong track seeing his this comment:
"I am trying to find out the second smallest integer in array ar[]. I
should get an output of 1 once I am done. The way I want to achieve
that is by making a new array called newar[] and make it include all
the indexes of ar[], except without -2."
This is a very inefficient way to approach this problem. You'll have to do 3 passes, Once to find to smallest indexed element, another pass to remove the element (this is an array so removing an element will require a full pass), and another one to find smallest one again.
You should just do a single pass algorithm and keep track of the smallest two integers,
or even better use a tree for efficiency. Here are the best answers of this problem:
Find the 2nd largest element in an array with minimum number of comparisons
Algorithm: Find index of 2nd smallest element from an unknown array
UPDATE: Here is the algorithm with OP's requirements,
3 passes, and no external libraries:
public static int Second_Tiny() {
int[] ar = {19, 1, 17, 17, -2};
//1st pass - find the smallest item on original array
int i;
int z = ar[0];
for (i = 1; i < ar.length; i++) {
if (z >ar[i]){
z=ar[i];
}
}
//2nd pass copy all items except smallest one to 2nd array
int[] ar2 = new int[ar.length-1];
int curIndex = 0;
for (i=0; i<ar.length; i++) {
if (ar[i]==z)
continue;
ar2[curIndex++] = ar[i];
}
//3rd pass - find the smallest item again
z = ar2[0];
for (i = 1; i < ar2.length; i++) {
if (z >ar2[i]){
z=ar2[i];
}
}
return z;
}
This grabs the index of the element specified in variable z and then sets a second array to the first array minus that one element.
Essentially this gives ar2 = ar1 minus element z
public static int Second_Tiny() {
int[] ar = {19, 1, 17, 17, -2};
int[] ar2;
int i;
int z = ar[0];
int x = 0;
for (i = 1; i < ar.length; i++) {
if (z >ar[i]){
z=ar[i];
x=i;
}
}
ar2 = ArrayUtils.remove(ar, x);
return(z);
}
I have an array of random values, and a target value.
#!/bin/bash
objective='50'
declare -a values=(1 2 2 6 8 14.5 15 28.7 .. 42)
I need to find a way to extract any combination of numbers in the array 'values' that add up to 50
The array has duplicates, and floating point integers.
A solution set might look like:
50 = 42 + 8
50 = 42 + 6 + 2
Initially I started in bash with some nested for loops, however I'm quickly realizing that this will grow exponentially with my array length.
I took a couple of java classes in college, but I'm still inexperienced in programming. I'm starting to think this may require recursion.
Can anyone with more programming experience point me in the right direction?
Besides nested for loops, how else could you approach this problem?
Here is an algorithm that has time complexity O(M*N) whereas M is Target and N is total size of set. Use analogy with knapsack problem as follows :-
Knapsack capacity = Target
Items are elements in the set with weight & value same as itself
Calculate maximum profit using dynamic programming
maxprofit = Target then there is/are subset which sum up to target.
Retrace the solution.
Java Solution for the same :-
public class SubSetSum {
static int[][] costs;
public static void calSets(int target,int[] arr) {
costs = new int[arr.length][target+1];
for(int j=0;j<=target;j++) {
if(arr[0]<=j) {
costs[0][j] = arr[0];
}
}
for(int i=1;i<arr.length;i++) {
for(int j=0;j<=target;j++) {
costs[i][j] = costs[i-1][j];
if(arr[i]<=j) {
costs[i][j] = Math.max(costs[i][j],costs[i-1][j-arr[i]]+arr[i]);
}
}
}
System.out.println(costs[arr.length-1][target]);
if(costs[arr.length-1][target]==target) {
System.out.println("Sets :");
printSets(arr,arr.length-1,target,"");
}
else System.out.println("No such Set found");
}
public static void printSets(int[] arr,int n,int w,String result) {
if(w==0) {
System.out.println(result);
return;
}
if(n==0) {
System.out.println(result+","+arr[0]);
return;
}
if(costs[n-1][w]==costs[n][w]) {
printSets(arr,n-1,w,new String(result));
}
if(arr[n]<=w&&(costs[n-1][w-arr[n]]+arr[n])==costs[n][w]) {
printSets(arr,n-1,w-arr[n],result+","+arr[n]);
}
}
public static void main(String[] args) {
int[] arr = {1,2,3,8,9,7};
calSets(10,arr);
}
}
I would do it like this:
1.some init
const int N=array size;
int val[N]; // input data
bool flag[N]; // is val used ?
for (int i=0;i<N;i++) flag[i]=false;
sort val[] descending
2.create function bool find_sum(int s);
if it found solution returns true else false
set flag to true for all used values
{
for (int i=0;i<N;i++) // find first usable big number (could be faster with binary search or with tailing last used i index into recursion)
if ((val[i]<=s)&&(!flag[i]))
{
flag[i]=true; // flag it as used
if (val[i]==s) return true; // try to find reminder
if (find_sum(s-val[i])) return true; // if found return true
flag[i]=false; // else unflag val[i] and continue winth next number
}
return false; // if sum not found then return false
}
3.after find_sum(s) your sum consists of all val[i] where flag[i]!=false
[edit1] functional source tested even for your case [6,5,5] and sum=10 it is OK
//---------------------------------------------------------------------------
int find_sum(int *val,int *use,int N,int sum,bool init=true)
{
int i;
if (init)
{
for (i=0;i<N;i++) use[i]=0; // nothibg used yet
for (int e=1;e;) // bubble sort
for (e=0,i=1;i<N;i++)
if (val[i-1]<val[i])
{ e=val[i-1]; val[i-1]=val[i]; val[i]=e; e=1; }
}
for (i=0;i<N;i++) // find first usable big number (could be faster with binary search or with tailing last used i index into recursion)
if ((val[i]<=sum)&&(!use[i]))
{
use[i]=1; // val[i] is used
if (val[i]==sum) return 1; // try to find reminder
if (find_sum(val,use,N,sum-val[i],false)) return 1; // if found return true
use[i]=0; // else val[i] is unused and continue winth next number
}
return 0; // if sum not found then return false
}
//---------------------------------------------------------------------------
void main()
{
int in[]={6,5,5}; // input data
const int N=sizeof(in)/sizeof(int);
int ret,out[N];
if (find_sum(in,out,N,10))
for (int i=0;i<N;i++)
if (out[i])
{
cout << in[i] << " ";
}
}
//---------------------------------------------------------------------------
PS. in your question in the input array are also floating point values
so you have to change int val[],sum to float/double
and add some accuracy for sum comparison to work with floats
if (val[i]==sum) return 1;
change to
if (fabs(val[i]-sum)<1e-10) return 1;
or use any other accuracy instead of 1e-10
You can use recursion yes, you can break the array into sub-parts (I use List).
Start from 0th index of the Parent list and a blank list
Iterate over to subList your Parent from i+1 to the end and thereby increasing your working list from 0 to i
Check for the sum (calculated) equals your objective
Code:
static Integer[] array = { 1, 2, 2, 6, 8, 14, 15, 28, 30, 32, 12, 48, 6, 42 };
static int objective = 50;
public static void main(String args[]) {
add(new ArrayList<Integer>(Arrays.asList(array)),
new ArrayList<Integer>());
}
public static void add(List<Integer> digits, List<Integer> workingList) {
for (int i = 0; i < digits.size(); i++) {
// New sublist to store values from 0 to i
List<Integer> list = new ArrayList<Integer>(workingList);
list.add(digits.get(i));
// Here you call this recursively with your Parent list from i+1
// index and working list from 0 to i
add(digits.subList(i + 1, digits.size()), list);
}
int sum = 0;
for (int element : workingList) {
sum += element;
}
if (sum == objective) {
System.out.println(objective + " = "
+ Arrays.toString(workingList.toArray()));
}
}
Output:
50 = [1, 2, 2, 15, 30]
50 = [1, 2, 6, 8, 15, 12, 6]
50 = [1, 2, 6, 14, 15, 12]
50 = [1, 2, 14, 15, 12, 6]
50 = [1, 2, 15, 32]
50 = [1, 2, 6, 8, 15, 12, 6]
...
Please read the question before marking it as duplicate
I have written following code to remove duplicates from array without using Util classes but now I am stuck
public class RemoveDups{
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 3, 1, 4, 52, 1, 45, };
int temp;
for (int i : a) {
for (int j = 0; j < a.length - 1; j++) {
if (a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
a = removeDups(a);
for (int i : a) {
System.out.println(i);
}
}
private static int[] removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
for (int i : a) {
if (!isExist(result, i)) {
result[j++] = i;
}
}
return result;
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}
and now the output is
1
2
3
4
5
6
45
52
0
0
0
0
0
0
0
0
0
0
Here my problem is
My code is not working in case of 0s
I am not able to understand how sorting an array can reduce time of execution
Is there any way to remove elements from array without using Util classes I know one way to remove convert array into list and then remove but for that also we need Util classes is there any way to implement by myself.
Since the numbers you deal with are limited to a small range you can remove duplicates by a simple "counting sort": mark the numbers you have found in a set-like data structure and then go over the data structure. An array of boolean works just fine, for less memory usage you could create a basic bitset or hash table. If n is the number of elements in the array and m is the size of the range, this algorithm will have O(n+m) complexity.
private static int[] removeDups(int[] a, int maxA) {
boolean[] present = new boolean[maxA+1];
int countUnique = 0;
for (int i : a) {
if (!present[i]) {
countUnique++;
present[i] = true;
}
}
int[] result = new int[countUnique];
int j = 0;
for (int i=0; i<present.length; i++) {
if (present[i]) result[j++] = i;
}
return result;
}
I am not able to understand how sorting an array can reduce time of execution
In a sorted array you can detect duplicates in a single scan, taking O(n) time. Since sorting is faster than checking each pair - O(n log n) compared to O(n²) time complexity - it would be faster to sort the array instead of using the naive algorithm.
As you are making the result array of the same length as array a
so even if you put only unique items in it, rest of the blank items will have the duplicate values in them which is 0 for int array.
Sorting will not help you much, as you code is searching the whole array again and again for the duplicates. You need to change your logic for it.
You can put some negative value like -1 for all the array items first in result array and then you can easily create a new result array say finalResult array from it by removing all the negative values from it, It will also help you to remove all the zeroes.
In java , arrays are of fixed length. Once created, their size can't be changed.
So you created an array of size18.
Then after you applied your logic , some elements got deleted. But array size won't change. So even though there are only 8 elements after the duplicate removal, the rest 10 elements will be auto-filled with 0 to keep the size at 18.
Solution ?
Store the new list in another array whose size is 8 ( or whatever, calculate how big the new array should be)
Keep a new variable to point to the end of the last valid element, in this case the index of 52. Mind you the array will still have the 0 values, you just won't use them.
I am not able to understand how sorting an array can reduce time of execution
What ? You sort an array if you need it to be sorted. Nothing else. Some algorithm may require the array to be sorted or may work better if the array is sorted. Depends on where you are using the array. In your case, the sorting will not help.
As for your final question , you can definitely implement your own duplicate removal by searching if an element exists more than once and then deleting all the duplicates.
My code is not working in case of 0
There were no zeroes to begin with in your array. But because its an int[], after the duplicates are removed the remaining of the indexes are filled with 0. That's why you can see a lot of zeroes in your array. To get rid of those 0s, you need to create another array with a lesser size(size should be equal to the no. of unique numbers you've in your array, excluding 0).
If you can sort your array(I see that its already sorted), then you could either bring all the zeroes to the front or push them to the last. Based on that, you can iterate the array and get the index from where the actual values start in the array. And, then you could use Arrays.copyOfRange(array, from, to) to create a copy of the array only with the required elements.
try this
package naveed.workingfiles;
public class RemoveDups {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 3, 1, 4, 52, 1, 45, };
removeDups(a);
}
private static void removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
int count = 0;
for (int i : a) {
if (!isExist(result, i)) {
result[j++] = i;
count++;
}
}
System.out.println(count + "_____________");
for (int i=0;i<count;i++) {
System.out.println(result[i]);
}
// return result;
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}
public class RemoveDups {
public static void main(String[] args) {
int[] a = { 1, 2, 0, 3, 1,0, 3, 6, 2};
removeDups(a);
}
private static void removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
int count = 0;
boolean zeroExist = false;
for (int i : a) {
if(i==0 && !zeroExist){
result[j++] = i;
zeroExist = true;
count++;
}
if (!isExist(result, i)) {
result[j++] = i;
count++;
}
}
System.out.println(count + "_____________");
for (int i=0;i<count;i++) {
System.out.println(result[i]);
}
// return result;
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}
// It works even Array contains 'Zero'
class Lab2 {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 3, 1, 4, 52, 1, 45 };
removeDups(a);
}
private static void removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
int count = 0;
for (int i : a) {
if (!isExist(result, i)) {
result[j++] = i;
count++;
}
}
System.out.println(count + "_____________");
for (int i = 0; i < count; i++) {
System.out.println(result[i]);
}
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}
Does anyone have a good algorithm for taking an ordered list of integers, i.e.:
[1, 3, 6, 7, 8, 10, 11, 13, 14, 17, 19, 23, 25, 27, 28]
into a given number of evenly sized ordered sublists, i.e. for 4 it will be:
[1, 3, 6] [7, 8, 10, 11] [13, 14, 17, 19] [23, 25, 27, 28]
The requirement being that each of the sublists are ordered and as similar in size as possible.
Splitting the lists evenly means you will have two sizes of lists - size S and S+1.
With N sublists, and X elements in the original, you would get:
floor(X/N) number of elements in the smaller sublists (S), and X % N is the number of larger sublists (S+1).
Then iterate over the original array, and (looking at your example) creating small lists firsts.
Something like this maybe:
private static List<Integer[]> splitOrderedDurationsIntoIntervals(Integer[] durations, int numberOfIntervals) {
int sizeOfSmallSublists = durations.length / numberOfIntervals;
int sizeOfLargeSublists = sizeOfSmallSublists + 1;
int numberOfLargeSublists = durations.length % numberOfIntervals;
int numberOfSmallSublists = numberOfIntervals - numberOfLargeSublists;
List<Integer[]> sublists = new ArrayList(numberOfIntervals);
int numberOfElementsHandled = 0;
for (int i = 0; i < numberOfIntervals; i++) {
int size = i < numberOfSmallSublists ? sizeOfSmallSublists : sizeOfLargeSublists;
Integer[] sublist = new Integer[size];
System.arraycopy(durations, numberOfElementsHandled, sublist, 0, size);
sublists.add(sublist);
numberOfElementsHandled += size;
}
return sublists;
}
Here is my own recursive solution, inspired by merge sort and breadth first tree traversal:
private static void splitOrderedDurationsIntoIntervals(Integer[] durations, List<Integer[]> intervals, int numberOfInterals) {
int middle = durations.length / 2;
Integer[] lowerHalf = Arrays.copyOfRange(durations, 0, middle);
Integer[] upperHalf = Arrays.copyOfRange(durations, middle, durations.length);
if (lowerHalf.length > upperHalf.length) {
intervals.add(lowerHalf);
intervals.add(upperHalf);
} else {
intervals.add(upperHalf);
intervals.add(lowerHalf);
}
if (intervals.size() < numberOfIntervals) {
int largestElementLength = intervals.get(0).length;
if (largestElementLength > 1) {
Integer[] duration = intervals.remove(0);
splitOrderedDurationsIntoIntervals(duration, intervals);
}
}
}
I was hoping someone might have a suggestion for an iterative solution.
Here's a solution for Python. You can translate it to Java, you need a way to get a piece of of a list and then to return it. You cannot use the generator approach though, but you can append each sublist to a new list.
pseudocode...
private static void splitOrderedDurationsIntoIntervals(Integer[] durations, List<Integer[]> intervals, int numberOfInterals) {
int num_per_interval = Math.floor(durations.length / numberOfInterals);
int i;
int idx;
// make sure you have somewhere to put the results
for (i = 0; i < numberOfInterals; i++) intervals[i] = new Integer[];
// run once through the list and put them in the right sub-list
for (i = 0; i < durations.length; i++)
{
idx = Math.floor(i / num_per_interval);
intervals[idx].add(durations[i]);
}
}
That code will need a bit of tidying up, but I'm sure you get the point. Also I suspect that the uneven sized interval list will be at the end rather than at the beginning. If you really want it that way round you can probably do that by reversing the order of the loop.
That should be an Answer in a more iterative fashion.
public static void splitList(List<Integer> startList, List<List<Integer>> resultList,
int subListNumber) {
final int subListSize = startList.size() / subListNumber;
int index = 0;
int stopIndex = subListSize;
for (int i = subListNumber; i > 0; i--) {
resultList.add(new ArrayList<Integer>(startList.subList(index, stopIndex)));
index = stopIndex;
stopIndex =
(index + subListSize > startList.size()) ? startList.size() : index + subListSize;
}
}
You might consider something like this:
public static int[][] divide(int[] initialList, int sublistCount)
{
if (initialList == null)
throw new NullPointerException("initialList");
if (sublistCount < 1)
throw new IllegalArgumentException("sublistCount must be greater than 0.");
// without remainder, length / # lists will always be the minimum
// number of items in a given subset
int min = initialList.length / sublistCount;
// without remainer, this algorithm determines the maximum number
// of items in a given subset. example: in a 15-item sample,
// with 4 subsets, we get a min of 3 (15 / 4 = 3r3), and
// 15 + 3 - 1 = 17. 17 / 4 = 4r1.
// in a 16-item sample, min = 4, and 16 + 4 - 1 = 19. 19 / 4 = 4r3.
// The -1 is required in samples in which the max and min are the same.
int max = (initialList.length + min - 1) / sublistCount;
// this is the meat and potatoes of the algorithm. here we determine
// how many lists have the min count and the max count. we start out
// with all at max and work our way down.
int sublistsHandledByMax = sublistCount;
int sublistsHandledByMin = 0;
while ((sublistsHandledByMax * max) + (sublistsHandledByMin * min)
!= initialList.length)
{
sublistsHandledByMax--;
sublistsHandledByMin++;
}
// now we copy the items into their new sublists.
int[][] items = new int[sublistCount][];
int currentInputIndex = 0;
for (int listIndex = 0; listIndex < sublistCount; listIndex++)
{
if (listIndex < sublistsHandledByMin)
items[listIndex] = new int[min];
else
items[listIndex] = new int[max];
// there's probably a better way to do array copies now.
// it's been a while since I did Java :)
System.arraycopy(initialList, currentInputIndex, items[listIndex], 0, items[listIndex].length);
currentInputIndex += items[listIndex].length;
}
return items;
}
This isn't quite polished - I got into an infinite loop (I think) when I tried to pass an 18-item array in with 10 sublists. I think the algorithm breaks down when min == 1.
This should be fairly fast. Good luck :)