How to write a method like splice in Java - java

i'm tasked with creating a method which has the same functionality as splice however I cannot get the appropriate value into the appropriate index. My code works as follows,
public void PlaceElementAt(int newValue, int index) throws ArrayIndexOutOfBoundsException {
//check that index is valid
if (index >= 0 && index <= data.length) { //Checks that the index is within position 0 and 7 by default.
System.out.println ("Index is valid"); //returns index is valid if so
}
//increase size if necessary
if (data.length == numElements) { //checking if the number of elements is filling the spaces
doubleCapacity(); // calls upon the double capacity method if it is
}
if (numElements==0) {
data[numElements] = newValue;
System.out.println ("Element: " + data[numElements] + " at index: " + index);
numElements++;
}
//shuffle values down from index
else {
int bottompos = numElements-1;
int loopcount = numElements-index;
int NewBottom = numElements+1;
for (int i=0; i<loopcount; i++){
data[bottompos]=data[NewBottom];
bottompos--;
NewBottom--;
}
//insert newValue at index
data[numElements] = newValue;
System.out.println ("Element: " + data[numElements] +" at index: " + index);
numElements++;
}
}
My issue is apparent when I later give the commands in my main method.
myData.PlaceElementAt(3,0)
myData.PlaceElementAt(2,5)
myData.PlaceElementAt(7,3)
Once I check my breakpoints i see the values are being added to the array however they are being added on a 1 by 1 basis starting from index 0. Any suggestions greatly helps.

I'm making some assumptions about how your class is structured (adjust as needed), but generally I would recommend shifting right as it will simplify the overall process. Essentially we have an array with maximum allowed size given by MAX and current size given by size. Any time we add to the array, we increment the value of size by 1 (such as insertions or adding to the back of our list). Now, let's say we want to insert a value at index. This will entail shifting all elements at and right of this index by 1 to the right and then inserting our value in the space we have made. Before doing any inserting we first need to check that we have enough space to insert the item. If there is not enough space, we will need to allocate additional space, prohibit the insertion, or some other alternative. In your case, it looks like you want to allocate more space.
class MyList
{
private int MAX = 6;
private int size = 0;
private int[] array;
public MyList()
{
array = new int[MAX];
}
public void placeElementAt(int value, int index)
{
if (size == 0)
{
// If size is 0, just insert the value at index 0.
array[size++] = value;
return;
}
if (index < 0 || index >= size)
{
// Index is out of bounds.
System.out.println("Invalid index.");
return;
}
if (size >= MAX)
{
// Max capacity reached -> allocate more space.
doubleCapacity();
}
// Shift all elements at and above index right by 1.
for (int i = size - 1; i >= index; i--)
{
array[i + 1] = array[i];
}
// Insert element.
array[index] = value;
size++;
}
public void doubleCapacity()
{
int[] newArray = new int[MAX * 2];
// Copy old elements to new array.
for (int i = 0; i < size; i++)
{
newArray[i] = array[i];
}
// Double MAX to reflect new array.
MAX *= 2;
array = newArray;
System.out.println("Doubled");
}
public void add(int value)
{
if (size >= MAX)
{
// Max capacity reached -> allocate more space.
doubleCapacity();
}
// Add the element to the back of the list.
array[size++] = value;
}
public void print()
{
for (int i = 0; i < size; i++)
{
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[] args)
{
MyList data = new MyList();
data.placeElementAt(1, 0);
data.print();
data.placeElementAt(2, 0);
data.print();
data.placeElementAt(3, 0);
data.print();
data.placeElementAt(5, 0);
data.print();
data.placeElementAt(3, 0);
data.print();
data.placeElementAt(9, 0);
data.print();
data.placeElementAt(4, 0);
data.print();
data.placeElementAt(6, 0);
data.print();
}
}
The output of this program (with initial MAX = 6) would be...
1
2 1
3 2 1
5 3 2 1
3 5 3 2 1
9 3 5 3 2 1
Doubled
4 9 3 5 3 2 1
6 4 9 3 5 3 2 1

Well, seeing your code, you're receiving a "index" parameter. But you're not using the index to insert on your array.
Your code:
data[numElements] = newValue;
numElements++;
Try this:
data[index] = newValue;
numElements++;
I think this will solve it, but later you'll have to handle the cases where the specified index already have an element.

Related

Find different index in arrays compare

I'm trying to learn a bit Java with tutorials and currently I'm struggling with piece of code where I should find on which index is difference between arrays (if there is difference at all)
My code
Scanner scanner = new Scanner(System.in);
int[] arrOne = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int[] arrTwo = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int sumArrOne = 0;
int index = 0;
boolean diff = false;
for (int k : arrOne) {
if (Arrays.equals(arrOne, arrTwo)) {
sumArrOne += k;
} else {
for (int i : arrTwo) {
if (k != i) {
index = i;
diff = true;
break;
}
}
}
}
if (diff) {
System.out.println("Found difference at " + index + " index.");
} else {
System.out.println("Sum: " + sumArrOne);
}
So, if arrays are identical I'm sum array elements in arrOne. If they are not identical -> must show at which index they are not.
With this code when I input
1 2 3 4 5
1 2 4 3 5
I should get that difference is at index 2 instead I've got index 1.
I'm not quite sure why and would be glad if someone point me out where is my mistake.
I updated your code. Looks like you're misunderstanding the concept of indexes yet.
Use one common index to check with in both arrays, in my example it's simply called i:
import java.util.Arrays;
import java.util.Scanner;
public class BadArray {
static private final int INVALID_INDEX = Integer.MIN_VALUE;
public static void main(final String[] args) {
try (final Scanner scanner = new Scanner(System.in);) {
final int[] arrOne = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
final int[] arrTwo = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int sumArrOne = 0;
int diffIndex = INVALID_INDEX;
final int minLen = Math.min(arrOne.length, arrTwo.length);
for (int i = 0; i < minLen; i++) {
sumArrOne += arrOne[i];
if (arrOne[i] != arrTwo[i]) {
diffIndex = i;
break;
}
}
if (diffIndex != INVALID_INDEX) {
System.out.println("Found difference at " + diffIndex + " index.");
} else if (arrOne.length != arrTwo.length) {
System.out.println("Arrays are equal but have different length!");
} else {
System.out.println("Sum: " + sumArrOne);
}
}
}
}
I also put the scanner into a try-resource-catch to handle resource releasing properly.
Note you could also do the array lengths comparison right at the start if different array lengths play a more crucial role.
You are trying to find out which index has the first difference so you should iterate via the index rather than using a for-each loop (aka enhanced for loop). The following method should work for this.
/**
* Returns the index of the first element of the two arrays that are not the same.
* Returns -1 if both arrays have the same values in the same order.
* #param left an int[]
* #param right an int[]
* #return index of difference or -1 if none
*/
public int findIndexOfDifference(int[] left, int[] right) {
// short-circuit if we're comparing an array against itself
if (left == right) return -1;
for (int index = 0 ; index < left.length && index < right.length ; ++index) {
if (left[index] != right[index]) {
return index;
}
}
return -1;
}
In your code you compare, where the indexes are different, not the values at the indexes. Also your code has several other issues. I'll try to go through them step by step:
// compare the whole array only once, not inside a loop:
diff = !Arrays.equals(arrOne, arrTwo));
if (!diff) {
// do the summing without a loop
sumArrOne = Arrays.stream(arrOne).sum();
} else {
// find the difference
// it could be the length
index = Math.min(arrOne.length, arrTwo.length);
// or in some different values
for (int i = 0; i < index; i++) { // do a loop with counter
if (arrOne[i] != arrTwo[i]) {
index = i;
break;
}
}
}
It doesn't matter that I set index here above the loop as it's value will be overwritten anyways inside the loop, if relevant.

Between iterations of the same loop, are local variables reused or reallocated?

I always understood that defining a local variable within a loop does not slow it down because they are reused between iterations of the same loop.
I was surprised to find that when I move the definition of the local variable outside the loop, then it reduces memory significantly (39.4Mb vs 40 Mb).
Between iterations of the same loop, are local variables reused or reallocated?
I did also see Allocation of space for local variables in loops
Duplicate Zeroes Problem (leetcode): Given a fixed length array arr of integers, duplicate each occurrence
of zero, shifting the remaining elements to the right.
Note that elements beyond the length of the original array are not
written.
Do the above modifications to the input array in place, do not return
anything from your function.
import java.util.Arrays;
/**
* algorithm: the zeroes divide the array into sub-arrays or subsets.
* we move or shift the elements exactly once, to their final resting place R.I.P. ;)
* The last subset will be shifted n0s places, the one before it, n0s -1 places and so on...
* O(n)
* #author likejudo
*
*/
public class DuplicateZeroes {
static void arrayCopy(int[] arr, int begin, int end, int n) {
for (int i = end + 1; i >= begin ; i--) {
int destination = i + n;
if (destination < arr.length) {
arr[destination] = arr[i];
}
}
}
public static void duplicateZeros(int[] arr) {
int n0s = 0; // number of zeroes
int last0At = -1; // last zero at index
int boundary = 0; // rightmost boundary
// find total n0s, last0At
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 0) {
n0s++;
last0At = i;
}
}
// System.out.format("n0s=%d last0At=%d \n", n0s, last0At);
// if no zeroes or all zeroes, we are done
if(n0s == 0 || n0s == arr.length) {
return;
}
boundary = arr.length - n0s;
while (n0s > 0) {
// System.out.format("before arrayCopy(%s, %d, %d, %d) ", Arrays.toString(arr), last0At, boundary, n0s);
// move subset of all elements from last0At till boundary-1, by n0s spaces.
arrayCopy(arr, last0At, boundary, n0s);
// set start of subset to 0
arr[last0At] = 0;
// System.out.format("after arrayCopy : %s assigned arr[last0At=%d]=0\n", Arrays.toString(arr),last0At);
// update boundary
boundary = last0At - 1;
// next subset to the left will have one less zero
n0s--;
last0At--;
// find the next last zer0 At index
while (last0At > 0 && arr[last0At] != 0)
last0At--;
// if no more...
if (last0At <0 || arr[last0At] != 0) {
return;
}
}
}
public static void main(String[] args) {
// input: [1, 0, 2, 3, 0, 4, 5, 0]
// output: [1, 0, 0, 2, 3, 0, 0, 4]
int[] arr = {0,0,0,0,0,0,0};
System.out.println("input: " + Arrays.toString(arr));
duplicateZeros(arr);
System.out.println("output: " + Arrays.toString(arr));
}
}
In the method arrayCopy, when I move the local variable destination outside the loop,
Before
static void arrayCopy(int[] arr, int begin, int end, int n) {
for (int i = end + 1; i >= begin ; i--) {
int destination = i + n; // >>>>>>>>>>>>>>>>>>>>>>>
if (destination < arr.length) {
arr[destination] = arr[i];
}
}
}
After
memory usage improved! (39.4 Mb vs 40 Mb)
static void arrayCopy(int[] arr, int begin, int end, int n) {
int destination = 0; // >>>>>>>>>>>>>>>>>
for (int i = end + 1; i >= begin ; i--) {
destination = i + n;
if (destination < arr.length) {
arr[destination] = arr[i];
}
}
}
About your question
I always understood that defining a local variable within a loop does
not slow it down because they are reused between iterations of the
same loop.
declaring local variable inside loop does not slow it down?
Yes, you are right. Declaring local vars does not increase the time complexity, or if it does change the runtime just a bit, it's too insignificant to be considered.
Runtime and memory measurements of LeetCode are highly inaccurate, especially runtime. For instance, I just resubmitted the following solution and it says 39.6 MB, some days ago said 43.3 MB for the exact same solution without a byte change:
Their test cases are usually limited because it is costly I guess, thus their benchmarking is not valuable.
public final class Solution {
public static final void duplicateZeros(int[] arr) {
int countZero = 0;
for (int index = 0; index < arr.length; index++)
if (arr[index] == 0) {
countZero++;
}
int length = arr.length + countZero;
for (int indexA = arr.length - 1, indexB = length - 1; indexA < indexB; indexA--, indexB--)
if (arr[indexA] != 0) {
if (indexB < arr.length) {
arr[indexB] = arr[indexA];
}
} else {
if (indexB < arr.length) {
arr[indexB] = arr[indexA];
}
indexB--;
if (indexB < arr.length) {
arr[indexB] = arr[indexA];
}
}
}
}
Overall it'd be best to focus on asymptotically efficient algorithms mostly, because benchmarking has lots of "how-tos" and we'd want to have really good resources (CPU, memory, etc.) with isolated test systems.
References
For additional details, please see the Discussion Board where you can find plenty of well-explained accepted solutions with a variety of languages including low-complexity algorithms and asymptotic runtime/memory analysis1, 2.

Problem in implementing build-heap method for min-heap

I am trying to make min-heap algorithm and i am able to get insert,delete,pop ,trickleUp and trickleDown methods to work ,but i am having problems with the constructor which is to make use of build-heap algorithm.
The method is simple as it just wants to build a new heap from an array .Further,i am going to implement heap sort algorithm which requires heapify() to maintain the heap property.But,i am stuck if the constructor and so not sure if my heapify() is correct or not.Once constructor works,heap sort will become easy to implement.
/** Construct a new heap from an array of unsorted data.
*
* Complexity: O(n)
* #param data Array to populate the heap from
* #param capacity Capacity of the heap (must be >= data.length)
* #param comparator Comparator to use when comparing elements
*/
MinHeap(T[] data, int capacity) {
for(int i = data.length/2 + 1; i >= 0;i--){
heapify(data,i);
}
}
public void heapify(Comparable[] data,int i){
int smallest = i;
if(size >left(i) && data[left(i)].compareTo(data[i])< 0 )
{
smallest = left(i);
}
else{
smallest = i;
}
if(size>right(i) && data[right(i)].compareTo(data[i])< 0)
{
smallest = right(i);
}
if(smallest !=i)
{
Comparable temp = data[i];
data[i] = data[smallest];
data[smallest] = temp;
heapify(data,smallest);
}
}
////// Test File
#Test public void testArrayConstruction() {
System.out.println("array construction");
for(int i = 0; i < 100; ++i) {
Integer[] data = randomArray(i);
MinHeap h = new MinHeap(data, i*2);
assertEquals(h.capacity(), i * 2);
assertEquals(h.size(), i);
// Collections has min/max, but of course those don't work on arrays.
Integer smallest = data[0];
for(Integer x : data)
if(x < smallest)
smallest = x;
checkHeapOrder(h);
assertEquals(h.top(), smallest);
}
Integer[] randomArray(int size) {
Integer[] arr = new Integer[size];
for (int i = 0; i < size; ++i) {
arr[i] = Math.round((float) Math.random() * Integer.MAX_VALUE);
}
return arr;
}
void checkHeapOrder(MinHeap h) {
assertTrue(h != null);
for(int i = 1; i < h.size() / 2; ++i)
assertTrue("Heap order property is broken at element at position "
+ i,
h.data[i].compareTo(h.data[i*2]) < 0 &&
h.data[i].compareTo(h.data[i*2 + 1]) < 0);
}
This is the line in the test file where the problem occurs : integer smallest = data[0]; Here,the method is unable to initialize smallest to 0th element of array.I tried tweaking with the program,but every time got the same error.I believe that the test file can also be incorrect,so just want to make sure.
testArrayConstruction caused an Error: 0
java.lang.ArrayIndexOutOfBoundsException
You didn't include the code for randomArray() ...
Assuming that this method makes randomized array with size equal to the method's argument, then your call to
Integer[] data = randomArray(0);
makes an array of size 0 .
You can't read the element at index 0 because an array of size 0 has no elements.

Sorting Integer array using Comparable

I am working on a project in which I have to sort an array of Integer objects by using Comparable.
My add method takes an item of type E. If my size variable (which tracks the elements in my array theData[]) is = 0 (which it is initialized to), I simply put the item in theData[0].
If it is not, I use item.compareTo to compare the item against each item already in the array. If the result of compareTo is < 0 for a number in the array, I shift everything at that number and after to the right, and insert the item before it.
If compareTo returns a 0, meaning the item is equal to the number in the array, I do nothing as I don't want duplicates in the array.
If none of the compareTo statements in the loop return a -1 or a 0, I put the item in theData[size], the end of the array, as it must be larger than all the other numbers.
However, this doesn't work. Any time I make a new Set and add a few numbers to it, then try to print out the contents of my set using a for loop,I keep getting a java.lang.ArrayIndexOutOfBoundsException: 10 error for this line:
theData[j + 1] = theData[j];
I've tried starting from scratch and re-writing my loop with different logic, and each time I keep hitting this wall. I know I must either be shifting incorrectly or not increasing the size of the array correctly with my reallocate method, but I can't wrap my head around it.
import java.util.*;
public class Set<E extends Comparable<E>> {
String s;
String name;
private static final int INITIAL_CAPACITY = 10;
private E[] theData;
private int size = 0;
private int capacity = INITIAL_CAPACITY;
#SuppressWarnings("unchecked")
public Set() {
theData = (E[]) new Comparable[capacity];
}
public Set(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void add(E item) {
if (size == capacity) {
reallocate();
}
if (size == 0) { // If size is 0, add item to theData[0]
theData[size] = item;
size++;
return;
}
else { // Else compare the item to every item in loop.
for (int i = 0; i < size; i++) {
int result = item.compareTo(theData[i]);
if (result < 0) {
for (int j = 0; j < size; j++) { //If item is less than a number, shift everything
theData[j + 1] = theData[j]; //after that index to the right, and add item
theData[j] = item;
}
}
if (result == 0) {
return;
}
else { //If item is not less than or equal to any
theData[size] = item; //numbers in the array, add it to the end
size++;
}
}
}
}
/*
* if (size>=1){ int result = item.compareTo(theData[size-1]); if(result<0){
* E temp = theData[size-1]; theData[size-1] = item; theData[size] = temp; }
* if(result>1){ return; } }
*/
public E get(int index) {
if (index < 0 || index >= size) {
throw new ArrayIndexOutOfBoundsException(index);
}
return theData[index];
}
public int size() {
return size;
}
private void reallocate() {
capacity = 2 * capacity;
theData = Arrays.copyOf(theData, capacity);
}
}
Edit: The driver method I'm using to test it -
public class Driver {
String one = "two";
public static void main(String[] args){
Set<Integer> one = new Set<Integer>();
one.add(63);
one.add(20);
one.add(127);
one.add(10);
one.add(26);
one.add(15);
for(int i = 0; i < one.size(); i++){
System.out.println(one.get(i));
}
}
}
When j == size - 1, theData[j+1] will take you out of the array.
You want to loop to one before the end instead.
for (int j = 0; j < size - 1; j++) { //If item is less than a number, shift everything
theData[j + 1] = theData[j]; //after that index to the right, and add item
theData[j] = item;
}
So I've also taken a look at the logic you've got for the insertion, and it doesn't make a lick of sense. Why do you delay the insertion at all? If you've got the room, just add it!
Next, the double loops are essentially implementing bubble sort, but there's a fatal flaw with it: you don't ever complete the swap; you only overwrite your values repeatedly. You're also not comparing in the right direction; you want to swap if the value on the left is larger than the value on the right, since you're starting from the beginning of the array.
So, with that...this is what an implementation would have the form of...
public void add(E item) {
if (size == capacity) {
reallocate();
}
theData[size++] = item;
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - 1; j++) {
if (theData[j].compareTo(theData[j + 1]) > 0) {
// perform the swap (you need an extra variable!
}
}
}
}
I leave implementing the swap as an exercise for the reader.
First, in your shift loop, you are inserting the new item in every position instead of shifting then inserting in [i] because you copy theData[j] to the next position, but always assign item to theData[j], is that right?
Second, you are starting from the beginning of array since j starts with 0. J should start with i.
Third and main bug, you verify if result < 0 then you verify IF result == 0, change for a ELSE IF so the else don't get executed even when result < 0
shift elements to right can be done from right to left, like:
for (int j = size; j > i; j--) { // If item is less than a
// number, shift
// everything
theData[j] = theData[j - 1]; // after that index to the
// right, and add item
}
size++;
theData[i] = item;
break;// after insert the number, we can just break the for loop
once the new number is inserted, break the for loop, else, the size variable will not be correct
else { // If item is not less than or equal to any
theData[size] = item; // numbers in the array, add it to the end
size++;
break;
}

How to re-sort already sorted array where one element updates

I have array with constant size (size = 20 in real life), duplicates are allowed For example:
1 2 2 3 3 4 5 6 7 8 9
Now exactly one element updates:
1 5 2 3 3 4 5 6 7 8 9
I need to resort this array. Should I just use bubblesort?
update I don't know how to call what I wrote. But i suppose it is not possible to sort faster. comments are welcome!
// array is already almost sorted and INCREASING, element at pos need to be inserted to the right place
private void SortQuotes(List<Quote> quoteList, int pos)
{
var quoteToMove = quoteList[pos];
if (pos == 0 || quoteList[pos - 1].Price < quoteToMove.Price)
{
MoveElementsDown(quoteList, pos);
} else if (pos == quoteList.Count - 1 || quoteList[pos + 1].Price > quoteToMove.Price)
{
MoveElementsUp(quoteList, pos);
}
}
private void MoveElementsDown(List<Quote> quoteList, int pos)
{
var quoteToInsert = quoteList[pos];
var price = quoteToInsert.Price;
for (int i = pos - 1; i >= 0; i--)
{
var nextQuote = quoteList[i];
if (nextQuote.Price > price)
{
quoteList[i + 1] = quoteList[i];
if (i == 0) // last element
{
quoteList[i] = quoteToInsert;
}
}
else
{
quoteList[i + 1] = quoteToInsert;
break;
}
}
}
private void MoveElementsUp(List<Quote> quoteList, int pos)
{
var quoteToInsert = quoteList[pos];
var price = quoteToInsert.Price;
for (int i = pos + 1; i < quoteList.Count; i++)
{
var nextQuote = quoteList[i];
if (nextQuote.Price < price)
{
quoteList[i - 1] = quoteList[i];
if (i == quoteList.Count - 1) // last element
{
quoteList[i] = quoteToInsert;
}
}
else
{
quoteList[i - 1] = quoteToInsert;
break;
}
}
}
updated i do know which element is odd, i.e. it's position is known!
This solution shifts each element by one until the right position for the odd element is found. As it has been overwritten already in the first step, it is saved in a temporary variable 'h' and then written to the final position. It requires the minimum of comparisions and shift operations:
static void MoveOddElementToRightPosition(int[] a, int oddPosition)
{
int h = a[oddPosition];
int i;
if (h > a[oddPosition + 1])
for (i = oddPosition; i < a.Count()-1 && a[i+1] <= h; i++)
a[i] = a[i+1];
else
for (i = oddPosition; i > 0 && a[i-1] >= h; i--)
a[i] = a[i - 1];
a[i] = h;
}
Bubblesort will use n^2 time if the last element needs to get to the front. Use insertion sort.
As the array is small, insertion sort takes roughly ~O(n) time for small arrays and if you are just updating 1 value, insertion sort should fulfil your purpose in the best possible way.
It can be done in O(n). If you don't know the element then search for the element in O(n) and then You just need to compare and swap for each element and that would take O(n). So total 2n which means O(n).If you know the element which has been modified then compare and swap for each element.
If you're interested in replacing an element quickly, then you can also use a structure where deletion and insertion is fast, like for example a TreeSet in Java. That means O(log(n)) theoretically, but if you just manipulate arrays of 20 elements it may not be worth it
If the set of all different elements is finite, like in your example where you just use numbers for 1 to 9, then there is a solution in O(1). Instead of having a sorted list you just keep an array with the number of occurrences of your elements.
If you still want to keep everything in an array, then the fastest way is this
find the position A of of the element you're going to remove by bisection in O(log(n)).
find the position B of where your new element is going to end up in the same way. More precisely B is the smallest index where new_element < a[k] for every k > B
if A < B, move all elements between A + 1 and B to their left, then set the new element to position B. if B > A, you do the same thing but to the right. Now this step is in O(n), but there's no logic, it's just moving memory around. In C you'd use memmove for this and it's heavily optimized, but I don't know any Java equivalent.
You don't need to sort it again.
Only one element changes. So you just need to go through the list and put the changed number to appropriate place. This will be of O(n) complexity.
int a[] = {1, 5, 2, 3, 3, 4, 5, 6, 7, 8, 9};
int count = 0;
//find the odd element
for(int jj=1; jj< a.length; jj++){
if(a[jj] < a[count])
break;
else count++;
}
System.out.println(" Odd position " + count);
//put odd element to proper position
for(int k= count+1; k<a.length; k++){
if(a[count] > a[k]){
int t = a[count];
a[count] = a[k];
a[k] = t;
count++;
}
}
Above is the working code tested for given input.
Enjoy.
Bubblesort is quite OK in this case with 20 compares max.
But finding the new position with binary search is O(log(n)), that is 5 compares in this case.
Somewhat faster, if you need the last bit odd speed use the binary search otherwise you can stick with bubble sort.
Here is a naive implementation in plain C. Remove the fprintf(stderr, ... after testing. The ITEM can be anything, as long as a comparison function is possible. Otherwise: use pointers to ITEM, (and maybe add an extra sizeofelem argument, ala qsort)
#include <stdio.h>
#include <string.h>
typedef int ITEM;
int item_cmp(ITEM one, ITEM two);
unsigned one_bubble( ITEM *arr, unsigned cnt, unsigned hot , int (*cmp)(ITEM,ITEM) );
int item_cmp(ITEM one, ITEM two)
{
fprintf(stderr,"Cmp= %u to %u: %d\n", one, two, one-two);
if (one > two) return 1;
else if (one < two) return -1;
else return 0;
}
unsigned one_bubble( ITEM *arr, unsigned cnt, unsigned hot , int (*cmp)(ITEM,ITEM) )
{
unsigned goal = cnt;
int diff;
ITEM temp;
/* hot element should move to the left */
if (hot > 0 && (diff=cmp( arr[hot-1], arr[hot])) > 0) {
/* Find place to insert (this could be a binary search) */
for (goal= hot; goal-- > 0; ) {
diff=cmp( arr[goal], arr[hot]);
if (diff <= 0) break;
}
goal++;
fprintf(stderr,"Move %u LEFT to %u\n", hot, goal);
if (goal==hot) return hot;
temp = arr[hot];
/* shift right */
fprintf(stderr,"memmove(%u,%u,%u)\n", goal+1, goal, (hot-goal) );
memmove(arr+goal+1, arr+goal, (hot-goal) *sizeof temp);
arr[goal] = temp;
return goal; /* new position */
}
/* hot element should move to the right */
else if (hot < cnt-1 && (diff=cmp( arr[hot], arr[hot+1])) > 0) {
/* Find place to insert (this could be a binary search) */
for (goal= hot+1; goal < cnt; goal++ ) {
diff=cmp( arr[hot], arr[goal]);
if (diff <= 0) break;
}
goal--;
fprintf(stderr,"Move %u RIGHT to %u\n", hot, goal);
if (goal==hot) return hot;
temp = arr[hot];
/* shift left */
fprintf(stderr,"memmove(%u,%u,%u)\n", hot, hot+1, (goal-hot) );
memmove(arr+hot, arr+hot+1, (goal-hot) *sizeof temp);
arr[goal] = temp;
return goal; /* new position */
}
fprintf(stderr,"Diff=%d Move %u Not to %u\n", diff, hot, goal);
return hot;
}
ITEM array[10] = { 1,10,2,3,4,5,6,7,8,9,};
#define HOT_POS 1
int main(void)
{
unsigned idx;
idx = one_bubble(array, 10, HOT_POS, item_cmp);
printf("%u-> %u\n", HOT_POS, idx );
for (idx = 0; idx < 10; idx++) {
printf("%u: %u\n", idx, array[idx] );
}
return 0;
}

Categories