Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last year.
Improve this question
I'm trying to implement a code to mergeSort a list. I was told to use getFirst() and addAll() but I don't know how so this is what I came up with:
Also, I can't use a void for mergeSort method - because it gives me an error so I have to return something.
Any suggestions will be very appreciate
You were close in terms of getting your approach working. Here's what I came up with. I changed the logic to create new lists to contain the results at each level rather than creating new lists when you break up a list. There's no reason to copy a list just to keep it in the same order. It's the list in the new order that needs to be fresh storage. This limits the number of copies and I think makes the logic easier, since you can then just append onto the end of each result list instead of having to have logic to set the right position in each list.
import java.util.Arrays;
import java.util.LinkedList;
class Test {
public static LinkedList<Integer> mergeSort(LinkedList<Integer> list, int start, int count) {
if (count < 2) {
LinkedList<Integer> result = new LinkedList<>();
result.add(list.get(start));
return result;
}
int size1 = count / 2;
int size2 = count - size1;
LinkedList<Integer> list_1 = mergeSort(list, start, size1);
LinkedList<Integer> list_2 = mergeSort(list, start + size1, size2);
return merge(list_1, list_2);
}
public static LinkedList<Integer> merge(LinkedList<Integer> list_1, LinkedList<Integer> list_2) {
LinkedList<Integer> result = new LinkedList<>();
int i = 0, j = 0;
while (i < list_1.size() && j < list_2.size())
if (list_1.get(i) < list_2.get(j))
result.add(list_1.get(i++));
else
result.add(list_2.get(j++));
while (i < list_1.size())
result.add(list_1.get(i++));
while (j < list_2.size())
result.add(list_2.get(j++));
return result;
}
public static LinkedList<Integer> mergeSort(LinkedList<Integer> list) {
return mergeSort(list, 0, list.size());
}
public static void main(String[] args) {
LinkedList<Integer> myList = new LinkedList<>(Arrays.asList(22, 45, 1234, 77, 4, 1111, 999, 12, 88, 44, 7777, 22, 33, 44, 666));
LinkedList<Integer> sorted = mergeSort(myList);
System.out.println(sorted);
}
}
Result:
[4, 12, 22, 22, 33, 44, 44, 45, 77, 88, 666, 999, 1111, 1234, 7777]
UPDATE: As #rcgldr points out, the above solution doesn't meet the stated guidelines. With this new version of the merge() method, the guidelines are met. Note that this doesn't make the algorithm much more efficient (both versions create lots of lists and are quite INEFFICIENT), but it does save a bunch of walking to random positions in lists in favor of working from the front each list:
public static LinkedList<Integer> merge(LinkedList<Integer> list_1, LinkedList<Integer> list_2) {
LinkedList<Integer> result = new LinkedList<>();
while (list_1.size() > 0 && list_2.size() > 0)
if (list_1.peek() < list_2.peek()) {
result.add(list_1.getFirst());
list_1.remove();
}
else {
result.add(list_2.getFirst());
list_2.remove();
}
result.addAll(list_1);
result.addAll(list_2);
return result;
}
Also note that calling getFirst() and then remove() is redundant. remmove() can be called by itself to both grab the next element and remove it from the list. I went with calling both methods to meet the requirements.
Although there is an accepted answer, this code uses getFirst() and addAll() as mentioned in the original post, in what I assume is the intended purpose of this exercise. It uses a bottom up merge sort, which avoids the top down issue having to scan lists to find mid points to split lists.
The basic concept of a bottom up merge sort is two 1 node lists are merged to create a sorted 2 node list, two sorted 2 node lists are merged to create a sorted 4 node list, two sorted 4 node lists are merged to create a sorted 8 node list, and so on, similar to bottom up merge sort for arrays.
A bottom up merge sort uses a small array of lists (java), pointers to nodes (C), or iterators to nodes (C++) to hold the lists. For this example code, I use an array of 32 lists. For each member of array, the member is either null or refers to a list where the number of nodes for the list for array[i] has 2^i nodes: array[0] 1 node, array[1] 2 nodes, array[2] 4 nodes, ..., array[30] 2^30 = 1 billion nodes. The last member will have 2^31 = 2 billion nodes or more if the total number of nodes is >= 2^32 (4 billion) nodes.
Nodes are removed from the front of the source list one at a time and each node from the source list is used to create a list mm with 1 node, then mm is merged into the array, stopping at the first null encountered:
while(source_list not empty){
mm = source_list.removeNode(() // mm = next node from source list
for(i = 0; i < 32; i++){ // merge mm into array
if(array[i] != null){
mm = merge(array[i], mm)
array[i] = null
} else {
break
}
}
if(i == 32) // if i == 32, there is no array[32], so
i = 31 // use array[31] instead
array[i] = mm
}
The pattern looks like this:
mm = next node from source list // 1 node list
array[0] = mm
mm = next node from source list // 1 node list
mm = merge(array[0], mm) // 2 node list
array[0] = null
array[1] = mm
mm = next node from source list // 1 node list
array[0] = mm
mm = next node from source list // 1 node list
mm = merge(array[0], mm) // 2 node list
array[0] = null
mm = merge(array[1], mm) // 4 node list
array[1] = null
array[2] = mm
Once the last node is merged into the array, all the lists in the array are merged to form a single sorted list:
mm = empty list
for(i = 0; i < 32; i++){
if(all[i] != null){
mm = merge(all[i], mm);
all[i] = null; // (for garbage collection)
}
}
Java's native double linked list class doesn't provide a means to move nodes within a list or between lists, so a node has to be deleted when an element is retrieved from the front of a list, and a node has to be created when an element is appended to the back of a list, an extra overhead. In the case of C++ standard double link list class std::list, std::list::splice() can be used to move nodes within a list or between lists, reducing the overhead, such as dst.splice(dst.end(), src, src.begin()), which moves the beginning node (first node) from src to the ending node (last node) of dst.
public static LinkedList<Integer> merge(LinkedList<Integer> ll,
LinkedList<Integer> rr)
{
if(ll.isEmpty())
return rr;
if(rr.isEmpty())
return ll;
LinkedList<Integer> mm = new LinkedList<>();
while(true){
if(ll.getFirst().compareTo(rr.getFirst()) <= 0){
mm.add(ll.removeFirst());
if(!ll.isEmpty())
continue;
mm.addAll(rr);
break;
} else {
mm.add(rr.removeFirst());
if(!rr.isEmpty())
continue;
mm.addAll(ll);
break;
}
}
return mm;
}
public static LinkedList<Integer> mergeSort(LinkedList<Integer> ll)
{
if(ll == null || ll.size() < 2)
return ll;
int i;
final int ASZ = 32; // create array (of nulls)
LinkedList<Integer>[] all= new LinkedList[ASZ];
// merge nodes into array
LinkedList<Integer> mm;
do{
mm = new LinkedList<>(); // mm = next node
mm.add(ll.removeFirst());
// merge mm into array
for(i = 0; (i < ASZ) && (all[i] != null); i++){
mm = merge(all[i], mm);
all[i] = null;
}
if(i == ASZ) // don't go past end of array
i--;
all[i] = mm;
}while(!ll.isEmpty());
// merge array into single list
mm = new LinkedList<>();
for(i = 0; i < ASZ; i++){
if(all[i] != null){
mm = merge(all[i], mm);
all[i] = null;
}
}
return (mm);
}
test code, takes about 3 to 5 seconds to sort 4 million (2^22) nodes.
public static void main(String[] args) {
final int COUNT = 4*1024*1024;
LinkedList<Integer> ll = new LinkedList<>();
Random r = new Random();
for(int i = 0; i < COUNT; i++)
ll.addLast(r.nextInt());
long bgn, end;
bgn = System.currentTimeMillis();
ll = mergeSort(ll);
end = System.currentTimeMillis();
System.out.println("milliseconds " + (end-bgn));
// check sort
int i;
i = ll.removeFirst();
int j = i;
while(!ll.isEmpty()){
j = ll.removeFirst();
if(i > j)
break;
i = j;
}
if(i == j)
System.out.println("passed");
else
System.out.println("failed");
}
In the merge code, I'm getting faster and more consistent run times using a loop instead of addAll, from 3 to 5 seconds down to 2.8 to 3.2 seconds, but the assignment states to use addAll.
// mm.addAll(rr); // replace with loop is faster
do
mm.add(rr.removeFirst());
while(!rr.isEmpty());
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Assume we have a list of integers, for example:
L = [13,13,4,13,4,2]
I want to find the set of all palindromes, where each palindrome is a sub-list of L containing contiguous integers. For the above list that would be:
S = {[13], [4], [2], [13,13], [13,4,13], [4,13,4]}
Because the inverse of L would be L' = [2,4,13,4,13,13], and every element of S appears in L' in the correct order.
How can I find the set of all palindromes in general? My naive approach would be to check if each element of the power set of L appears in L', but this is inefficient and I am sure that there is a better solution.
I think my solution is pretty similar to solution from MC Emperor, but I focused on not creating temporary objects like lists.
I select sub-arrays of given array using left and right indices and check it for palindrome.
public static Set<List<Integer>> findAllPalindromes(int[] arr) {
Set<List<Integer>> res = new LinkedHashSet<>();
for (int length = 1; length < arr.length; length++)
for (int left = 0, right = left + length - 1; right < arr.length; left++, right++)
if (isPalindrome(arr, left, right))
res.add(sublist(arr, left, right));
return res;
}
This method check is given sub-array palindrome or not:
private static boolean isPalindrome(int[] arr, int left, int right) {
for (; left < right; left++, right--)
if (arr[left] != arr[right])
return false;
return true;
}
This method create separate list for given sub-array:
private static List<Integer> sublist(int[] arr, int left, int right) {
List<Integer> res = new ArrayList<>(right - left);
for (; left <= right; left++)
res.add(arr[left]);
return res;
}
You need two steps to do that.
First, you'll need to find all sublists within the list:
List<Integer> input = Arrays.asList(13, 13, 4, 13, 4, 2);
List<List<Integer>> subLists = new ArrayList<>();
for (int subListSize = 1; subListSize < input.size(); subListSize++) {
for (int startIndex = 0; startIndex < input.size() - subListSize + 1; startIndex++) {
List<Integer> subList = input.subList(startIndex, startIndex + subListSize);
subLists.add(subList);
}
}
// Also test the whole list:
subLists.add(input);
Then you need to check for each element if the list is a palindrome. To test if a list is a palindrome, element n must be compared to element listSize - 1 - n.
We only need to check half of the elements.
static boolean isPalindrome(List<Integer> subList) {
for (int i = 0; i < subList.size() / 2; i++) {
if (!Objects.equals(subList.get(i), subList.get(subList.size() - 1 - i))) {
return false;
}
}
return true;
}
If you want to remove duplicates, then you can put the elements into a Set.
I'm trying to sort an array from greatest to least using compareTo(), and the results aren't quite right.
public void insert(C data){
arr[currentSize++] = data; // <-- currentSize is initialized to 0 before this
C temp;
for(int i = 0; i < currentSize-1; i++) {
if(arr[i].compareTo(arr[i+1]) < 0) {
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
}
An example is an input of:
[0.32371583205781573, 0.8906211866288234, 0.5288455608245172, 0.9170569745456318, 0.5103102992069214]
With an output of:
[0.9170569745456318, 0.5288455608245172, 0.5103102992069214, 0.32371583205781573, 0.8906211866288234]
I tried running through it backwards below, and the result was still incorrect:
public void insert(C data){
arr[currentSize++] = data;
C temp;
for(int i = currentSize-1; i > 0; i--) {
if(arr[i].compareTo(arr[i-1]) < 0) {
temp = arr[i];
arr[i] = arr[i-1];
arr[i-1] = temp;
}
}
}
The code is tested with:
int n = 5;
PQ<Double> pq1 = new PQasSortedArray<Double>(n);
double[] arr1 = new double[n];
for(int i = 0; i < n; i++){
Random num = new Random();
arr1[i] = num.nextDouble();
}
for (int i=0; i < arr1.length; i++){
pq1.insert(arr1[i]);
}
The way you've written this is to always "insert" the new item at the end of the array, then attempt to bubble-sort it into place, however, your bubble sort only makes one pass, and at best the new item, which starts at the last position, will move into the second-to-last position.
If you really want to add the new element into the last position, then you should change the for loop so it starts at the last element and works backward to the first. That will cause it to keep bubbling the new element up until it reaches the correct position.
However, a far more efficient way to do this is to find the right position for the new element first, then insert it there.
Easy way: just loop through the existing elements starting at index 0 until you find one that's less than the new value (remember we're sorting greatest to least), then insert the new element before that one.
Faster way: implement a binary search by starting in the middle. If the element in the middle is greater than the new element, then you know the new element should be in the second half of the array, otherwise it's in the first half. Then go to the middle of the selected half and go through the same process again, until you have found the right place.
Java has a function for performing a binary search: Arrays.binarySearch. However, you'll have to give it a custom comparator that reverses the normal comparison logic for C.
Update: This implementation of the less-efficient first strategy works. I implemented in terms of Comparable since we don't really care what C is, only that it's Comparable.
public void insert(Comparable data){
arr[currentSize] = data; // <-- currentSize is initialized to 0 before this
for(int i = currentSize; i > 0; i--) {
if(arr[i].compareTo(arr[i-1]) > 0) {
Comparable temp = arr[i];
arr[i] = arr[i-1];
arr[i-1] = temp;
}
}
currentSize++;
}
Much faster implementation:
public void insert(Comparable data) {
int position = Arrays.binarySearch(arr, 0, currentSize, data, (left, right) -> right.compareTo(left));
if (position < 0)
position = -position - 1;
System.arraycopy(arr, position, arr, position + 1, currentSize - position);
arr[position] = data;
currentSize++;
}
I would like to write a function insertAndSort() that will take as parameter an Integer "num" and a List of integers "list". Let's assume the List lust is already sorted.
The algorithm is supposed to work this way :
Add "num" to L and keep the List sorted after "num" has been added.
Return the sorted List.
WARNING : We do not know whether the list is sorted ASC or DESC. And that is precisely my problem !
Example :
if "num" = 4 and L = {1, 3, 5, 7}, then the final sorted List is {1, 3, 4, 5, 7}
if "num" = 4 and L = {7, 5, 3, 1}, then the final sorted List is {7, 5, 4, 3, 1}
I can not use sorting API such as Collections.sort or Collections.reverseOrder etc...
So far, I've produced this code :
public static void main(String[] args) {
int num = 4;
List<Integer> myList = Arrays.asList(1, 3, 5, 7);
List<Integer> newList = new ArrayList<Integer>();
newList = insertAndSort(myList, num);
System.out.println(newList);
}
public static List<Integer> insertAndSort(List<Integer> list, int num) {
List<Integer> listSecond = new ArrayList<Integer>(list.size()+1);
for(int i = 0; i <= list.size() ; i++) {
if(num < list.get(i)) {
if(!listSecond.contains(num)){
listSecond.add(num);
} else {
listSecond.add(list.get(i-1));
listSecond.add(list.get(i));
break;
}
} else {
listSecond.add(list.get(i));
}
}
return listSecond;
}
The problem is that this seems to be working with a single type of List: the ascending one.
When I take a sorted descending List, it does not work anymore.
Do you have any idea to make this work with both type of List ?
Thanks and Regards.
First, you need to detect the sort order in the existing list.
If the list is empty, you don’t need to care, just add your element, you cannot break any existing sort order.
If the list contains one element, I cannot tell you what to do. Options include tossing a coin and throwing an exception, but there are more.
If the list contains two or more elements, iterate through them except for the last element, each time comparing the current element with the element in the next higher index. As soon as you encounter a pair of elements that are not equal, you know the sort order. If you only encounter equal elements, all the elements in the list are equal, and again I cannot tell you what to do.
Once you’ve detected a sort order, I suggest a big if-else statement to handle the two cases separately.
You already have the code for the ascending case. Except it doesn’t always work. If I try to insert 4 into { 1, 3, 5 }, I get an ArrayIndexOutOfBoundsException. If I try with { 1, 3, 5, 7, 9 }, the 9 is lost. You should probably find a fix for that.
You should be able to handle the descending case similarly to the ascending case. Only use num > list.get(i) instead of num < list.get(i).
First, you need to check whether the list is sorted in ASC or DESC. That's easy: compare the 1st two elements look for two consecutive non-identical elements and see whether the first one is greater or the second one (thanks tom for correcting the mistake).
Now, for a list sorted in ascending order, convert list to an ArrayList. Then, add num to the ArrayList and convert it to a TreeSet, since TreeSets sort their elements in ascending order. Finally, reassign the ArrayList to hold the contents of the TreeSet and return it.
For a list sorted in descending order, first, convert the TreeSet to an ArrayList, then iterate over this ArrayList in reverse order and add the elements to a new ArrayList. Return the second ArrayList.
public List<Integer> insertAndSort(List<Integer> list, int num){
ArrayList<Integer> a = new ArrayList<Integer>(list);
a.add(new Integer(num));
TreeSet t = new TreeSet(a);
a = new ArrayList<Integer>(t);
int l = list.size();
for(int i=1; i<l; i++){
if(list.get(i) != list.get(i-1))
break;
}
if(list.get(i) > list.get(i-1)) //ASC
return a;
else{ //DESC
ArrayList<Integer> a2 = new ArrayList<Integer>();
for(int i = a.size() - 1; i >= 0; i--)
a2.add(a.get(i));
return a2;
}
}
I would proceed with something like the code below. A few remarks :
it is possible to decide sort order if and only if there is at least 1 element AND first and last elements have different values.
the line int oo = list.get(p2) - list.get(p1); compute the
difference between the last and first element (negative = DESC,
positive = ASC)
the variable ox is positive if and only if the
added element is after the element pointed by the variable p3
whatever the order.
the position is found by a binary search algorithm by choosing p3 between p1 and p2 and deciding if the element is before or after p3.
This is not fully tested bu works with the examples you gave :
// static List<Integer> list = new ArrayList<>(Arrays.asList(7, 5, 3, 1));
static List<Integer> list = new ArrayList<>(Arrays.asList(1, 3, 5, 7));
static void add(int x)
{
// fixed code below (see Ole V.V. comment)
}
static public void main(String [ ] args)
{
add(4);
for(int x: list)
System.out.println(x);
}
EDIT: to be complete (see Ole V.V. comments)
When the new element is to be inserted before the first or after the last, two simple O(1) tests may be performed ; the general case has O(log N) complexity, this is more efficient than traversing the entire list which is O(N).
Be carefull too when comparing elements to deduce sort order, there may be several equal values ; the best is to compare the first and the last elements, this is O(1) - again better than O(N).
Algorithmic complexity is an important matter (to me) and was the primary aim of my post. The code of the add function becomes :
static void add(int x)
{
int p1 = 0;
int p2 = list.size() - 1;
if(list.size() == 0 || list.get(p1) == list.get(p2))
throw new IllegalStateException("Unable to decide sort order");
int oo = list.get(p2) - list.get(p1);
if(oo * (x - list.get(p1)) <= 0) // new element is before first
list.add(0, x);
else if(oo * (x - list.get(p2)) >= 0) // new element is after last
list.add(x);
else
{
while (p1 + 1 < p2)
{
int p3 = (p1 + p2) / 2;
int ox = (x - list.get(p3)) * oo;
if(ox >= 0) // new element is after p3
p1 = p3;
if(ox <= 0) // new element is before p3
p2 = p3;
}
list.add(p2, x);
}
}
Note : there may be still some undealed side effects. If the asker is interested, I am ready to give further help - just ask.
Your code and what you say is two different things.
Based on code you made, I see that List can't contain more than one instance of same value.
If thats the case, main method should look like this:
public static void main(String[] args){
int num = 4;
List<Integer> myList = Arrays.asList(1, 3, 4, 5, 7);
List<Integer> newList;
if (!myList.contains(num)) {
newList = insertAndSort(myList, num);
} else {
newList = copyList(myList);
}
System.out.println(newList);
}
if thats not the case:
public static void main(String[] args){
int num = 4;
List<Integer> myList = Arrays.asList(1, 3, 4, 5, 7);
List<Integer> newList;
newList = insertAndSort(myList, num);
System.out.println(newList);
}
Methods that main method use:
Assuming we can only know how list is sorted by values in list, we have to decide default sort method when there is only 1 value or all values are same. I picked ASC as default. If elements can be of same value and we are certain list is sorted its best to compare lowest value in list with the highest one. With this approach we have to compare 2 elements only once.
So method to see if list is sorted DESC would look like this:
private static boolean isDesc(List<Integer> list) {
return list.get(0) > list.get(list.size() - 1);
}
If method returns true its sorted DESC. With returning false its ASC. If we want to change default value, when values don't tell us how its sorted and we want it to be DESC we would replace '>' sign with '>='
private static boolean isDesc(List<Integer> list) {
return list.get(0) >= list.get(list.size() - 1);
}
Code for as you called it insertAndSort:
public static List<Integer> insertAndSort(List<Integer> list, int num) {
List<Integer> listSecond = new ArrayList<Integer>(list.size() + 1);
boolean isDescSortOrder = isDesc(list);
if (isDescSortOrder) {
int i = 0;
while ((i < list.size()) && (list.get(i) > num)) {
listSecond.add(list.get(i));
i++;
}
listSecond.add(num);
while (i < list.size()) {
listSecond.add(list.get(i));
i++;
}
} else { // is asc sort order
int i = 0;
while ((i < list.size()) && (list.get(i) < num)) {
listSecond.add(list.get(i));
i++;
}
listSecond.add(num);
while (i < list.size()) {
listSecond.add(list.get(i));
i++;
}
}
return listSecond;
}
Depending on how its sorted code got devided into 2 blocks. As we don't know on each iteration will be right place to insert our num value its better to use while loop. Using for loop and checking everytime if num value already exists in list is counterproductive. On top of that I dunno if your application should allow same values in the list. If I assume it should, you can't add num value if it already existed in the list with for loop and checking with contains every iteration.
And just to copy the table when list already has the element and we don't want to add elements that are already incuded:
public static List<Integer> copyList(List<Integer> list) {
List<Integer> listSecond = new ArrayList<Integer>(list.size());
for (int i = 0; i < list.size(); i++) {
listSecond.add(list.get(i));
}
return listSecond;
}
Also based on good programming practices I'd recommend to name methods based on what they do.
Calling method insertAndSort is asking for trouble. If I seen it, I'd say it alters list we are giving in parameter. Then it sorts it.
So putting unsorted list in it would give us unwanted outcome.
And I'd still ask myself why does it return a List when we are inserting an item to already existing list? I'd rather name it:
public static List<Integer> copySortedWithNewValue(List<Integer> sortedList, int newValue)
Try to use PriorityQueue. This collection contains a sorted sequence of elements which could be duplicated.
I have the following list:
list 1= 1,2,3,4,5,6
I am trying to make a list that contains the following:
list c= 1,6,2,5,3,4
However, I cannot figure out how to do it. I know how to iterate through 6 but I don't know how to get to the last number and iterate backwards. I know a ListIterator can be used to go backwards but I still cannot figure it out.
This is what I did to add the original, I just don't understand how to iterate backwards:
public static void q(Set<String>list1)
{
Set<String>combined = new HashSet();
Iterator<String> forward = list1.iterator();
Iterator <String> backwards = list1.iterator();
for (int i=0; i<list1.size(); i++)
{
combined.add(forward.next());
//code to go backwards
}
}
This isn't to solve your problem, but rather to show you how ListIterator can be used to go backwards since you couldn't figure it out.
List<Integer> list = new ArrayList<>();
for (int n = 1; n <= 6; n++) { // Add 1, 2, ... 6 to list
list.add(n);
}
ListIterator it = list.listIterator(list.size());
while (it.hasPrevious()) {
System.out.println(it.previous());
}
The listIterator method of a List allows you to specify the index to start at as a parameter.
The hasPrevious method of the ListIterator checks if there is a previous element (self-explanitory).
The previous() method of the ListIterator returns the previous element in the list and moves the cursor position backwards.
Using ListIterator you can go forwards and backwards as you please using next() and previous() respectively.
Alternatively, using a for statement instead of using ListIterator...
for (int i = list.size() - 1; i >= 0; i--) {
System.out.println(list.get(i));
}
I am not sure if you really wanted a Set given you were talking about lists. This is the idea without explicitly using list iterators however they would behave the similarly.
How to use a list iterator: http://www.java2s.com/Tutorial/Java/0140__Collections/ListIteratorInreverseorder.htm
public static List<Integer> interleaveFrontBack(List<Integer> list) {
if (list.size() <= 2){
return new LinkedList<Integer>(list);
}
List interleaved = new LinkedList<Integer>();
int end = list.size() - 1;
int front = 0;
while (end > front){
interleaved.add(list.get(front++));
interleaved.add(list.get(end--));
}
// if odd sized list need to add last element
if (end == front){
interleaved.add(list.get(front));
}
return interleaved;
}
Simple Algo would be
1.) just use two positions , i =0 for increment and j = size-1 for decrements
2.) add elements to new list using i and j positions while traversing to the middle of the content list
Integer []aa=new Integer[]{1,2,3,4,5,6};
List<Integer> list =Arrays.asList(aa);
int n=list.size();
List<Integer> list2 =new ArrayList<>();
for (int i = 0,j=list.size()-1; i <n/2 ; i++,j--) {
list2.add(list.get(i));
list2.add(list.get(j));
}
// if(n%2!=0) list2.add(list.get(n/2)); // un-comment this , to handle
// odd list size too ,dynamism
list2.forEach(i->System.err.print(i+" "));
Output:
1 6 2 5 3 4
Assuming that you simply want to put the last element of the first list on the second index, you can do something like:
List<Integer> input = Arrays.asList(1, 2, 3, 4, 5, 6);
// create new list that initially contains first and last element of input list
List<Integer> output = new ArrayList<>(Arrays.asList(input.get(0), input.get(input.size()-1)));
// now iterate the "in between" input elements and add them to output
for (int i=1; i < input.size() -1 ; i++) {
output.add(input.get(i));
}
System.out.println("in: " + input);
System.out.println("out: " + output);
Of course, the above is just one way of doing this; there are many others
Not sure what your exactly looking for and where your code has broke. You could try:
List<Integer> intergers = new ArrayList<>();
for(int i = 1; i < 7; i++) {
if(i < 6) {
intergers.add((i-1), i);
} else {
intergers.add(1, i); //when i is 6 place it in the second index
}
}
System.out.println("List: " + intergers.toString());
With java list you can chose the index and if that index has a value the value well be pushed to the next index. It was the simplest thing I could think of. This is what it printed out:
List: [1, 6, 2, 3, 4, 5]
I have an array containing duplicates in the following format:
arr[]={ 2,9,1,5,1,4,9,7,2,1,4 }
I want to sort the array in place such that all the duplicate elements are moved towards the end and sorted in different sub arrays like following:
arr[]={ 1,2,4,5,7,9, 1,2,4,9, 1 }
There is no range for Integers for the array specified.
Following is the code which i tried. This code recursively sorts the sub-arrays and then move duplicates towards the end. But Complexity wise this is not optimal solution.
Please suggest if it can be solve in O(n) or O(nlogn). Entire code is as follows:
public static int sortDuplicates(int a[],int start,int end){
int i, k,temp;
if(start==end)
return 1;
Arrays.sort(a, start, end);
k = start;
for (i = start+1; i < end; i++) {
if (a[k] != a[i] && a[k]<a[i])
{
temp=a[k+1];
a[k+1] = a[i];
a[i]=temp;
k++;
}
}
return sortDuplicates(a,k+1,a.length);
}
I would approach it as follows:
Put all elements and their counts in a hashmap:
int[] arr={ 2,9,1,5,1,4,9,7,2,1,4 };
Map<Integer, Integer> map = new HashMap<>();
for (int elt : arr) {
int val = 1;
if (map.containsKey(elt))
val = map.get(elt) + 1;
map.put(elt, val);
}
Fetch the batches one by one:
List<Integer> result = new ArrayList<>();
while (map.size() > 0) {
List<Integer> subList = new ArrayList<>(); // for the current segment
Iterator<Integer> it = map.keySet().iterator();
while (it.hasNext()) {
int elt = it.next();
subList.add(elt);
if (map.get(elt) == 1) { // remove all elements with occurence = 1
it.remove();
} else { // reduce occurence by 1
map.put(elt, map.get(elt)-1);
}
}
Collections.sort(subList); // sort this segment
result.addAll(subList); // append to result
}
for (int i : result) {
System.out.print(i + " ");
}
This prints
1 2 4 5 7 9 1 2 4 9 1
And if I'm not mistaken, it runs in O(n log n).
I would approach it as follows.
Put all the elements in a balanced binary search tree with their counts.
Now traverse the tree in an inorder way and keep putting the elements(with count > 0) in the array and decreasing their count by 1.
time complexity for creating the tree is O(nlgn) and for putting elements from tree is O(n) and space complexity is O(n).
Problem is if none of elements is being repeated then we are creating the tree in vain.