Insert an element into a sorted array - java

I wrote this function to insert an element into a sorted array such that array would still be sorted after adding the element.
But something is wrong. I know that my code has a lot of edge cases and probably I'm over complicating the algorithm but I really want to fix it.
My Code :
private static <E> void insert(E e, E[] arr, int count, Comparator<E> comp) {
if (count == 0) arr[0] = e;
for (int i = 0; i < count; i++) {
if (comp.compare(arr[i], e) >= 0) {
// we found an element that is >= to e
// we want to add new element at index i, currently arr[i] is occupied
// by larger element, so we need to adjust
if (i != 0) {
i--;
} else {
// do nothing
}
} else if (i + 1 == count) {
// this is the last iteration of the loop so we want to add element at i + 1
i++;
} else {
// keep looping to find an element
continue;
}
// we need to move elements to the right to make space
for (int j = count; j > i; j--) {
arr[j] = arr[j - 1];
}
arr[i] = e;
break;
}
}
My repo

I fixed the code, I should have not decremented i
private <E> void insert(E e, E[] arr, int count, Comparator<E> comp) {
if (count == 0) {
arr[0] = e;
return;
}
for (int i = 0; i < count; i++) {
if (comp.compare(arr[i], e) >= 0) {
// we found an element that is >= to e
// we want to add new element at index i, currently arr[i] is occupied
// by larger element, so we need to adjust
} else if (i + 1 == count) {
// this is the last iteration of the loop so we want to add element at i + 1
i++;
} else {
// keep looping to find an element
continue;
}
// we need to move elements to the right to make space
for (int j = count; j > i; j--) {
arr[j] = arr[j - 1];
}
arr[i] = e;
break;
}
}

Related

Find first occurrence of an integer in a sorted list with duplicates

This code prints the first occurence of element 'k' in the array properly but the question I'm doing wants me to print -1 if the element 'k' is entirely not present in the array. I know its easy but I'm just stuck and its frustatiting any help?
n = sc.nextInt();
k = sc.nextInt();
int arr[] = new int[n];
for(int i=0;i<n;i++) {
arr[i] = sc.nextInt();
}
for(int i=0;i<n;i++) {
if(arr[i]==k) {
System.out.println(i);
break;
}
}
Use Arrays#binarySearch:
int firstIndexOf(int[] sortedArray, int x) {
int p = Arrays.binarySearch(sortedArray, x);
if (p < 0) {
return -1;
}
while (p > 0 && sortedArray[p - 1] == x) {
--p;
}
return p;
}
Binary search splits the searched range in half repetively looking in which half to continue. It returns either the found position or the complement (~p) of the insert position.
int findOccurenceOfElemet(int[] a, int k) {
if(a.length == 0) {
return -1;
}
for(int i = 0; i < a.length; i++) {
if(a[i] == k) {
return i;
}
}
//return -1 if element not found
return -1;
}
What you are asking in the title, and what you are asking in the post body, are two different questions; however, if we will follow your question's body, that has nothing to do with binary search, and introducing boolean flag would get you what you are asking for:
boolean notFound = true;
for(int i=0; i<n; i++) {
if(arr[i] == k) {
System.out.println(i);
notFound = false;
break;
}
}
if(notFound) System.out.println("-1");

REPLACEMENT SELECTION SORT:

I am working on Replacement Selection sort project but i keep getting the error Exception in thread main Java.lang.ArrayIndexOutOfBoundsException:10 at ReplacementSelection.swap(ReplacementSelection.java:42) at ReplacementSelection.siftDown(ReplacementSelection.java:69) at Replacement..
class ReplacementSelection {
static int[] array = new int[]{ 1,2,3,4,5,6,7,8,9,10 };
public static void sort() {
System.out.println("before:" + Arrays.toString(array));
for (int i = array.length/2; i >= 0; i--) {
siftDown(i);
}
int count = array.length-1;
while (count > 0)
{
swap(array[0], array[count]);
--count;
siftDown(0);
}
System.out.println("after:" + Arrays.toString(array));
}
public static void swap(int i, int j)
{
int tmp;
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
public static void siftDown(int index)
{
int count = array.length;
// Left child is at index*2+1. Right child is at index*2+2;
while (true)
{
// first find the largest child
int largestChild = index*2+1;
// if left child is larger than count, then done
if (largestChild >= count)
{
break;
}
// compare with right child
if (largestChild+1 < count && array[largestChild] < array[largestChild+1])
{
++largestChild;
}
// If item is smaller than the largest child, then swap and continue.
if (array[index] < array[largestChild])
{
swap(array[index], array[largestChild]);
index = largestChild;
}
else
{
break;
}
}
}
public static void main(String[] args){
ReplacementSelection a = new ReplacementSelection();
a.sort();
}
}
You have written a swap method which takes indices as arguments. However, you pass it the values in the array at those indices instead of the indices themselves:
swap(array[0], array[count]);
and
swap(array[index], array[largestChild]);
To fix the exception error just pass the indices to the method:
swap(0, count);
and
swap(index, largestChild);
As #Pajacar123 mentioned, you should learn to use debugger.
In line
swap(array[index], array[largestChild]);
You are passing value from array which is at last index of table(index 9 value 10). Then when in method sawp in line array[i] = array[j];
j value is 10 while max index of table is 9. That causes exception. You are trying to refer to not existing elemnt.

CodingBat commonTwo method, help examine the output?

Question Summary:
Given two String arrays, return an integer representing how many matches are between them (ignore duplicates).
Real Answer:
http://www.javaproblems.com/2013/11/java-ap-1-commontwo-codingbat-solution.html
My Code
public int commonTwo(String[] a, String[] b) {
int count = 0;
boolean done = false;
for (int i = 0; i<a.length-1; i++){
if(a[i].equals(a[i+1])){
i++;
for (String j:b)
if (a[i].equals(j) && !done){
done = true;
count++;
}
}
else{
for (String j:b)
if(a[i].equals(j) && !done){
done = true;
count++;
}
}
done = false;
if(i == a.length-2)
for (String j:b)
if (a[i+1].equals(j) && !done){
done = true;
count++;
}
}
return count;
}
Image of output: [1]: http://i.stack.imgur.com/0esjC.png
So what it was intended to do was to go through all of the array a,if it equals the next one then go to that index, then add to count if there's a match between the arrays. The done boolean was used to make it so it doesn't add to count if there're duplicates of b that matches a and to end it once a match is found.
Lastly,
if(i == a.length-2)
was intended to make it so if it's the second before the last index number (as the last index number won't be checked in some cases), and not the same as the last index number, then it would check for matches for the last index number after checking the one before the last essentially. I understand why both errors occur and was wondering what could be done to fix it, particularly for the second one/comments on the code. Also, a third issue I notice would be (["a"], ["a"]) → 1 but the code will result in 0.
This question can be done is linear time O(N) that is a single traversal of both arrays a and b.
You should increment i as long as same string appears.So
if(a[i].equals(a[i+1]))
i++;
should be replaced by
while(i+1<a.length&&a[i].equals(a[i+1])){
i++;}
Also you do not need to go through entire array b for a single string of array a since both are in alphabetical order.You should only compare the string from the array b as long there is no match.Once a match is found then you should remember that index and next time matching should continue from that index onwards for the array b
Also you don't need the boolean variable done.
Keeping these things in mind the correct code is:
public static int commonTwo(String[] a, String[] b) {
int count = 0;
int j=0,i;
for (i = 0; i<a.length-1&&j<b.length-1;){
//SKIP DUPLICATES FOR ARRAY a
while(i+1<a.length&&a[i].equals(a[i+1])){
i++;}
//SKIP DUPLICATES FOR ARRAY b
while(j+1<b.length&&b[j].equals(b[j+1])){
j++;}
//MATCH THE STRINGS FROM ARRAY a AND ARRAY b
while(i<a.length&&j<b.length&&a[i].compareTo(b[j])!=0)
{
//INCREMENT I IF STRING IN ARRAY a IS LESS THAN STRING IN ARRAY b
if(a[i].compareTo(b[j])<0)
++i;
//INCREMENT J IF STRING IN ARRAY b IS LESS THAN STRING IN ARRAY a
else ++j;
}
//IF ABOVE LOOP BREAKS BECAUSE OF MATCH
if(i<a.length&&j<b.length)
{count++; ++j; ++i;}
}
//IF THE LAST ELEMENT OF ARRAY a IS LEFT FOR COMPARISON
if(i==a.length-1)
{
while(j<b.length)
{
//SKIP DUPLICATES OF ARRAY b
while(j+1<b.length&&b[j].equals(b[j+1]))
++j;
if(a[i].equals(b[j]))
{++count;}
++j;
}
}
//IF THE LAST ELEMENT OF ARRAY b IS LEFT FOR COMPARISON
if(j==b.length-1)
{
while(i<a.length)
{
//SKIP DUPLICATES OF ARRAY a
while(i+1<a.length&&a[i].equals(a[i+1]))
++j;
if(a[i].equals(b[j]))
++count;
++i;
}
}
return count;
}
This is the simplest solution i could come up with that uses only one loop.
public int commonTwo(String[] a, String[] b) {
int count = 0;
int i = 0;
int j = 0;
String s = "";
while (i < a.length && j < b.length) {
if (a[i].compareTo(b[j]) < 0)
i++;
else if (a[i].equals(b[j]) && a[i] != s) {
s = a[i];
count++;
i++;
j++;
}
else j++;
}
return count;
}
public int commonTwo(String[] a, String[] b) {
int ctr = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < b.length; j++) {
if (i > 0 && a[i] == b[j] && a[i] != a[i - 1]) {
ctr++;
break;
} else if (i == 0 && a[i] == b[j]) {
ctr++;
break;
}
}
}
return ctr;
}

At a total loss with java list processing code

Okay, this is probably going to come across as a really easy question, but honestly I'm new to coding and I've run up against a brick wall here. I need to insert a value into an array, shift the data to the right, and update the size of the array. The professor provided comments for us to structure our code around, and I've got most of it, but this last part is killing me. Can anyone help? Here's the code (the relevant portion is under //insert value and shift data...etc):
public class List {
// Declare variables
private int size = 0;
private int maxSize = 100;
private int[] data;
Scanner keyboard = new Scanner(System.in);
// constructors
public List() {
data = new int[maxSize];
}
public List(int maxSize) {
this.maxSize = maxSize;
data = new int[maxSize];
}
// methods
// Adds a value into the array and updates the size
public boolean add(int value) {
if (size == maxSize) {
System.out.println("Cannot add value since the list is full");
return false;
}
data[size] = value;
size++;
return true;
}
// add multiple values to the list obtained from the keyboard
public void addValues() {
// declare local variables
int count = 0;
System.out.println("Enter multiple integers separated by spaces");
String line = keyboard.nextLine();
Scanner scanLine = new Scanner(line);
try {
while (scanLine.hasNext()) {
data[size] = scanLine.nextInt();
count++;
size++;
}
} catch (ArrayIndexOutOfBoundsException aiobe) {
System.out.println("Only " + count + " values could be added before the list is full");
return;
} catch (InputMismatchException ime) {
System.out.println("Only " + count + " values could be added due to invalid input");
return;
}
}
// This will print all the elements in the list
public void print() {
System.out.println();
for (int i = 0; i < size; i++) {
System.out.print(data[i] + " ");
}
System.out.println();
}
// This methods returns the index of the key value if found in the list
// and returns -1 if the key value is not in the list
public int find(int key) {
for (int i = 0; i < size; i++) {
if (data[i] == key) {
return i;
}
}
return -1;
}
// This methods deletes the given value if exists and updates the size.
public boolean delete(int value) {
int index = find(value);
if (index == -1) {
System.out.println("The specified value is not in the list");
return false;
}
for (int i = index; i < size - 1; i++) {
data[i] = data[i + 1];
}
size--;
return true;
}
// This methods inserts the value at the given index in the list
public boolean insertAt(int index, int value) {
// validate index value and insertability
if (index < 0 || index > size || size == maxSize) {
System.out.println("Invalid index or list is already full");
return false;
}
// insert value and shift data to the right and update the size
return true;
}
// This method removes the value at given index and shifts the data as needed
public boolean removeAt(int index) {
if (index >= 0 && index < size) {
for (int i=index+1; i<size; i++)
data[i-1] = data[i];
size--;
return true;
}
return false;
}
// This method sorts the values in the list using selection sort
public void sort() {
int temp;
for (int j=size; j>1; j--) {
int maxIndex = 0;
for (int i=1; i<j; i++)
if (data[maxIndex] < data[i])
maxIndex = i;
temp = data[j-1];
data[j-1] = data[maxIndex];
data[maxIndex] = temp;
}
}
}
I apologize if the code is structured really horribly as well, by the way, I was unsure how to format it on this site so it looked right.
// insert value and shift data to the right and update the size
// I think the size is globally declared right?
size++;
for(int i=size - 1; i < 0; i--) {
data[i] = data[i - 1];
}
data[index] = value;
If you have a max size there will also be a check for size <= maxSize. Hope it helps
Think below answer should help. As there is already a size check, no need to check it again
public boolean insertAt(int index, int value) {
// validate index value and insertability
if (index < 0 || index > 5) {
System.out.println("Invalid index or list is already full");
return false;
}
// insert value and shift data to the right and update the size
for(int i=index;i<size;i++) {
data[++i] = data[i];
}
data[index] = value;
return true;
}
public boolean insertAt(int index, int value) {
// validate index value and insertability
if (index < 0 || index > size || size == maxSize) {
System.out.println("Invalid index or list is already full");
return false;
}
// insert value and shift data to the right and update the size
for (int i=size - 1; i > index; i--)
data[i+1] = data[i];
data[index] = value
size++;
return true;
}

Split method for unordered array list

i am trying to create method named split that divides a list into 2 lists according to a key. If list_1 and list_2 are the resulting lists, list_1 should contain all the items of the original list whose keys are less than or equal to the key passed and list_2 should contain all the items of the original list whose keys are larger than the key passed. I will post my code so far and what other people have suggested
public class UnorderedArrayList extends ArrayListClass {
public UnorderedArrayList() {
super();
}
public UnorderedArrayList(int size) {
super(size);
}
//Bubble Sort
public void bubbleSort() {
for (int pass = 0; pass < length - 1; pass++) {
for (int i = 0; i < length - 1; i++) {
if (list[i] > list[i + 1]) {
int temp = list[i];
list[i] = list[i + 1];
list[i + 1] = temp;
}
}
}
}
//implementation for abstract methods defined in ArrayListClass
//unordered list --> linear search
public int search(int searchItem) {
for(int i = 0; i < length; i++)
if(list[i] == searchItem)
return i;
return -1;
}
public void insertAt(int location, int insertItem) {
if (location < 0 || location >= maxSize)
System.err.println("The position of the item to be inserted is out of range.");
else if (length >= maxSize)
System.err.println("Cannot insert in a full list.");
else {
for (int i = length; i > location; i--)
list[i] = list[i - 1]; //shift right
list[location] = insertItem;
length++;
}
}
public void insertEnd(int insertItem) {
if (length >= maxSize)
System.err.println("Cannot insert in a full list.");
else {
list[length] = insertItem;
length++;
}
}
public void replaceAt(int location, int repItem) {
if (location < 0 || location >= length)
System.err.println("The location of the item to be replaced is out of range.");
else
list[location] = repItem;
}
public void remove(int removeItem) {
int i;
if (length == 0)
System.err.println("Cannot delete from an empty list.");
else {
i = search(removeItem);
if (i != -1)
removeAt(i);
else
System.out.println("Cannot delete! The item to be deleted is not in the list.");
}
}
public void merge(UnorderedArrayList list2,UnorderedArrayList list1){
int num=0;
for(int j=0; j<list1.length;j++){
num= list1.retrieveAt(j);
insertEnd(num);
}
for(int i=0; i<list2.length-1;i++){
num=list2.retrieveAt(i);
insertEnd(num);
}
}
public void split(UnorderedArrayList list2, UnorderedArrayList list1, UnorderedArrayList list, int item){
int listItem = item;
while(!list.isEmpty()){
list.retrieveAt(listItem);
if(listItem>item){
if(!list2.isFull()){
list2.insertAt(listItem);
}
}
}
}
//what i got so far from the internet
/* void UnsortedType::SplitLists(ItemType item, UnsortedType& list1, UnsortedType& list2){
ItemType listItem;
list.ResetList();
while ( !list.IsLastItem()) {
list.GetNextItem(listItem);
if(listItem > item) {
if (!list2.IsFull())
list2.InsertItem(listItem);
}
else {
if ( !list1.IsFull())
list1.InsertItem(listItem);
} }}
*/
You have a lot of code, most unrelated to your requirement. Given the list and the key, I would simply:
create the two result lists
iterate through the original list, copying the element to one of the result lists depending on its value relative to key
return the two result lists
That's all you need.
Had this same problem. You will want to clear the two lists you have already done away with(list1 and list2) so that they are available to receive values. Look at the following code I put together, which worked in my program, as a guide. For the method call in your client, your parameters should be: (list_1, list_2, result, split) . Your new lists will be available to you in the client in accordance with their names there.
public void split(UnorderedArrayList list1, UnorderedArrayList list2, UnorderedArrayList list3, int key) {
int num = 0;
list1.clearList();
list2.clearList();
for(int x = 0; x < list3.length; x++) {
num = list3.retrieveAt(x);
if(num <= key)
list1.insertEnd(num);
else
list2.insertEnd(num);
}
}
Hope this helps.

Categories

Resources