how to understand quick sort algorithm - java

I am learning quick sort in java, according to the material I have. The best case is the pivot is the median, worst case is when one side of the pivot is always empty.
For the following code, is "indexPartition" the pivot? What kind of parameters do you put in the following function so it will run in the worst situation?
private void quickSortSegment(E[] list, int start, int end)
{
if (end-start>1)
{
int indexPartition = partition(list, start, end);
quickSortSegment(list, start, indexPartition);
quickSortSegment(list, indexPartition+1, end);
}
}
private int partition(E[] list, int start, int end)
{
E temp;
E partitionElement = list[start];
int leftIndex = start;
int rightIndex = end-1;
while (leftIndex<rightIndex)
{
while (list[leftIndex].compareTo(partitionElement) <= 0 && leftIndex<rightIndex)
{
leftIndex++;
}
while (list[rightIndex].compareTo(partitionElement) > 0)
{
rightIndex--;
}
if (leftIndex<rightIndex)
{
temp = list[leftIndex];
list[leftIndex] = list[rightIndex];
list[rightIndex] = temp;
}
}
list[start] = list[rightIndex];
list[rightIndex] = partitionElement;
return rightIndex;
}

No the pivot is partitionElement. It also seems this code always selects the first element in the sequence to be the pivot. The function will run in all cases including the worst cases, but it will perform badly(have square complexity).
Different people propose different solutions for selecting the pivot but I personally like this one: Select 3 random elements from the interval in consideration, compute their average and use it as pivot.

This video along with the wikipedia article should clear things up. Wikipedia is pretty awesome for explaining sorting algorithms. With respect to your question, indexPartition is rightIndex, which is the index of partitionElement, the pivot.

Something wrong with this method partition(), e.g. for {3,1,2} we'll get {1,3,2}:
public class CompareApp {
public static void main(String... args) {
Integer[] arr = {3, 1, 2};
quickSortSegment(arr, 0, 2);
for (Integer i : arr) System.out.println(i);
}
private static <E extends Comparable> void quickSortSegment(E[] list, int start, int end) {
if (end - start > 1) {
int indexPartition = partition(list, start, end);
quickSortSegment(list, start, indexPartition);
quickSortSegment(list, indexPartition + 1, end);
}
}
private static <E extends Comparable> int partition(E[] list, int start, int end) {
E temp;
E partitionElement = list[start];
int leftIndex = start;
int rightIndex = end - 1;
while (leftIndex < rightIndex) {
while (list[leftIndex].compareTo(partitionElement) <= 0 && leftIndex < rightIndex) {
leftIndex++;
}
while (list[rightIndex].compareTo(partitionElement) > 0) {
rightIndex--;
}
if (leftIndex < rightIndex) {
temp = list[leftIndex];
list[leftIndex] = list[rightIndex];
list[rightIndex] = temp;
}
}
list[start] = list[rightIndex];
list[rightIndex] = partitionElement;
return rightIndex;
}}
java system.compare.CompareApp
1
3
2

Related

Finding an integer in a non sorted array using recursion and dividing

I need a little help with finding an integer in an array. The array must be non sorted, and the algorithm must be done recursively. My peers and I have came up with the solution to cut the array in half, check if the middle number is the value we are looking for, if not, it cuts itself in half and keeps repeating itself, until it moves on to other parts of the array and eventually stops. So far, I have been experimenting with my code, here it is. I would like to know where this is going wrong, and how can I improve it or make it fully work? Thank you
import java.util.*;
public class BinarySearch {
public static int search(int[] a, int low, int high, int value, int count)
{
int mid = (low + high) / 2;
if(a[mid] == value)
{
return mid;
}
if(a[mid] < value)
{
count = a[mid];
if(a[count] != value)
{
count--;
return search(a, mid + 1, high, value, count);
}
}
else
{
count = a[mid];
if(a[count] != value){
count++;
return search(a, low, mid - 1, value, count);
}
}
return low;
}
public static void main(String[] args)
{
BinarySearch BS = new BinarySearch();
int[] a = {5, 7, 1, 2, 4, 12, 9, 8, 89};
int value = 9;
int result = BS.search(a, 0, 0, value, 0);
if(result == -1)
{
System.out.print("the Value is not in the array!" );
}
else
{
System.out.print("the Value is in the array!" );
}
}
}

MergeSort on ArrayList only work with ArrayList(Collection<? extends E> c) not ArrayList(int initialCapacity)?

I am working on sort interval which exist on an ArrayList with its start property, the full definition of interval will show in sample code as private class.
The implementation I am using is MergeSort, and very similar to Princeton's stuff which I refer to, but problem is I find this implementation only work with creating auxiliary ArrayList aux with ArrayList(Collection<? extends E> c) and initialize it with aux.set(i, intervals.get(i)); which try to fill aux with same order of interval items from original list
I try to work it out with creating aux with ArrayList(int initialCapacity) and initialize it with aux.add(intervals.get(i)), but failed. And I still could not figure out why this way doesn't work ?
The full code which can directly used for debug:
public class Test {
private class Interval {
// Will use start property to sort
int start;
int end;
Interval() {
start = 0;
end = 0;
}
Interval(int s, int e) {
start = s;
end = e;
}
#Override
public String toString() {
return "[" + start + "," + end + "]";
}
}
public void sortHelper(List<Interval> intervals) {
int len = intervals.size();
// Only this way works
List<Interval> aux = new ArrayList<Interval>(intervals);
// This way NOT work ?
//List<Interval> aux = new ArrayList<Interval>(len);
sort(intervals, aux, 0, len - 1);
}
public void sort(List<Interval> intervals, List<Interval> aux, int lo, int hi) {
if(hi <= lo) {
return;
}
int mid = lo + (hi - lo) / 2;
sort(intervals, aux, lo, mid);
sort(intervals, aux, mid + 1, hi);
mergeHelper(intervals, aux, lo, mid, hi);
}
public void mergeHelper(List<Interval> intervals, List<Interval> aux, int lo, int mid, int hi) {
// Only this way works
for(int i = lo; i <= hi; i++) {
aux.set(i, intervals.get(i));
}
// Combine with List<Interval> aux = new ArrayList<Interval>(len);
// this way NOT work ?
//for(int i = lo; i <= hi; i++) {
// aux.add(intervals.get(i));
//}
int left = lo;
int right = mid + 1;
for(int k = lo; k <= hi; k++) {
if(left > mid) {
intervals.set(k, aux.get(right++));
} else if(right > hi) {
intervals.set(k, aux.get(left++));
} else if(less(aux.get(right), aux.get(left))) {
intervals.set(k, aux.get(right++));
} else {
intervals.set(k, aux.get(left++));
}
}
}
public boolean less(Interval a, Interval b) {
return a.start - b.start < 0;
}
public static void main(String[] args) {
Test m = new Test();
Interval one = m.new Interval(1, 3);
Interval two = m.new Interval(2, 6);
Interval three = m.new Interval(8, 10);
Interval four = m.new Interval(15, 18);
List<Interval> intervals = new ArrayList<Interval>();
// Adding order as [2,6],[1,3],[8,10],[15,18]
intervals.add(two);
intervals.add(one);
intervals.add(three);
intervals.add(four);
m.sortHelper(intervals);
// Expected sort result should be
// [1,3],[2,6],[8,10],[15,18]
for(Interval i : intervals) {
System.out.println(i);
}
}
}
Could anyone help me on understanding why must create auxiliary ArrayList aux with ArrayList<Collection<? extends E> c> and initialize it with aux.set(i, intervals.get(i)); ? Or my understanding goes the wrong way ?
Thanks
Thanks for important hint from #maraca and #Dukeling, after some work, below is my opinion for the issue here:
Q1: Why using List<Interval> aux = new ArrayList<Interval>(len); with aux.add(intervals.get(i)); not work ?
A1: There are two main issues here, I should admit I fail into some habitual thoughts as previous work with array implementation of MergeSort, the impact here are (1) new ArrayList<Interval>(len) equal to new Interval[len] or not ? (2) aux[i] = intervals[i](just for explain, not use = in real code) equal to aux.add(intervals.get(i)) ?
For problem (1), the real case here is using new ArrayList<Interval>(len) will only define the initial limitation of ArrayList size, but no real items used like space holder to fill into the initialized list, e.g If we set len = 4, the initialized list is actually [], not [interval obj, interval obj, interval obj, interval obj]. Assume using new ArrayList<Interval>(len) with aux.set(i, intervals.get(i)), IDE will throw out java.lang.IndexOutOfBoundsException: Index: 0, Size: 0, that's because no real object fill into this list as initialized and set method cannot work on an empty list. The solution for this issue is create len numbers of dummy interval objects to fill in list when initialized, such as
List<Interval> aux = new ArrayList<Interval>((Arrays.asList(new Interval(), new Interval(), new Interval(), new Interval())));, but since we don't care what initialized first on auxiliary list, just used as place holder and in case of the objects are too many, above code can be replaced with List<Interval> aux = new ArrayList<Interval>(intervals); which return to our right solution.
For problem (2), the real case here is using aux.add(intervals.get(i)) not equal to aux[i] = intervals[i], at least we should use set() instead of add(), because add() will continually append on aux, which not MergeSort suppose to, because MergeSort require exactly same size auxiliary collection copy to help sorting. Still use same example to explain what happened when using add()
Note after the 3rd merge, the aux size increase to double size of original list, this will cause indices issue when copy back to original list. But if we are using set() will not cause this trouble.
Q2: If still want to use add() what is the proper way ?
A2: As mentioned by #Dukeling, we need to clear() the aux before final round copy from original list to auxiliary list, e.g like before the 3rd merge happen on above example.
The working code with add() and clear() below:
public void mergeHelper(List<Interval> intervals, List<Interval> aux, int lo, int mid, int hi) {
aux.clear();
for(int i = 0; i < lo; i++) {
aux.add(null);
}
for(int i = lo; i <= hi; i++) {
aux.add(intervals.get(i));
}
int left = lo;
int right = mid + 1;
for(int k = lo; k <= hi; k++) {
if(left > mid) {
intervals.set(k, aux.get(right++));
} else if(right > hi) {
intervals.set(k, aux.get(left++));
} else if(less(aux.get(right), aux.get(left))) {
intervals.set(k, aux.get(right++));
} else {
intervals.set(k, aux.get(left++));
}
}
}

Reversing the order of sub-array using Recursion

I am trying to reverse the order of a sub-array between the indices of start and end strictly using recursion. For example, if the subarray is 1,2,3,4 , it will become 4,3,2,1.
However, I am getting the following runtime error:
java.lang.ArrayIndexOutOfBoundsException: -1
at finalExam.reverse(finalExam.java:13)
at finalExam.reverse(finalExam.java:17)
I am not sure how to fix this problem.
Thanks.
double[] reverse (double[] a, int start, int end) {
if (start == end) {return a;}
else {
a[start] = a[end];
a[end] = a[start];}
return reverse (a, start+1, end-1);
}
(Since you mention the exam is over). Here are the problems with your code:
Your check should be start >= end
Your code for swapping two numbers is incorrect.
Here is the correct solution:
public static double[] reverse (double[] a, int start, int end) {
if (start >= end) {
return a;
}
else {
// this code will swap two elements
double temp = a[start];
a[start] = a[end];
a[end] = temp;
}
return reverse (a, start+1, end-1);
}

Creating a QuickSort for an Array of names

So I am working on a project for my class and I am currently stuck on creating a QuickSort class to sort an Array of 1000 names. I have a template I am using from a previous Lab we did in class which we are supposed to base it off of; but in the lab we used an array of Integers and I am struggling with how to convert it so it will work with Strings; names. Thanks for your help or any suggestions, the code is below.
Updated post; So I made my comparison in my Name class
public int compareTo(Object other) {
int result;
if (name.equals(((Name) other).name))
result = name.compareTo(((Name) other).name);
else
result = name.compareTo(((Name) other).name);
return result;
}
And I've tried to re-work my QuickSort..I'm struggling with the swap method.
private ArrayList<Name> data;
public QuickSort(ArrayList<Name> initialValue){
data=initialValue;
}
public void sort(ArrayList<Name> namelist, int i, int j){
sort(0, data.size()-1);
}
public void sort(int from, int to){
if (from >= to)
return;
int p = partition(from, to);
sort(from, p);
sort( p + 1, to);
}
private int partition(int from, int to){
Name pivot = data.get(from);
int i = from - 1;
int j = to + 1;
while(i<j){
i++; while(data.get(i).compareTo(pivot) < 0) i++;
j--; while(data.get(j).compareTo(pivot) < 0) j--;
if(i<j) swap(i,j);
}
return j;
}
private void swap (int i, int j){
Name temp = data.get(i);
data.equals(i) = data.get(j);
data = temp;
}
particularly the "data.equals(i) = data.get(j) line and the data = temp; I am sure i'm doing something stupid and easy.
update;
private void swap (int i, int j){
Name temp = data.get(i);
data.get(j).equals(data.get(i));
data.get(j).equals(temp);
}
possibly?
Posting the code that will solve the problem would be easy but won't help you to learn the meaning of QuickSort (or another sorting algorithm).
The heart of the QuickSort is exchanging the elements here:
while(i<j){
i++; while(data[i] < pivot) i++;
j--; while(data[j] > pivot) j--;
if(i<j) swap(i,j);
}
As you can see, you're comparing the elements of the data array against the pivot variable. Since they're ints, you can easily compare them using <. Now, you have to do something similar but for Strings. Thankfully, Strings can be compared using String#compareTo method. I'll let you this implementation for String (otherwise I will present the homework assignment as mine =P).
For a more generic solution to the problem, you have two options:
Making your class implement the Comparable interface, so you will have a compareTo method. A basic
sample implementation:
public class Name implements Comparable<Name> {
#Override
public int compareTo(Name name) {
return ... //comparison logic...
}
}
Using it in your QuickSort
pivot.compareTo(...);
Using an instance of Comparator interface. You will use Comparator#compare for this. A basic sample implementation:
public class NameComparator implements Comparator<Name> {
#Override
public int compare(Name name1, Name name2) {
return ... //comparison logic...
}
}
Using it in your QuickSort
NameComparator nameComparator = new NameComparator();
nameComparator.compare(..., ...);
You can use a comparator: Comparator.compare(o1, o2) returns -1, 0 or 1 if the objects are less, equal or greater.
Strings in java are actually comparable, some sort of a companion interface:
int compareTo(T other);
API Do: http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html
Note that in string comparison is by equals method:
data.get(j) == pivot => data.get(j).equals(pivot)
You will have to set a String value to compare it to something. So by setting the pivot value to compare it to itself it will return zero. Since it is unlikely that all Strings will equal your pivot value then anything compared to pivot value will be returned as -1 OR 1. By doing this your if statement will determine which way the swap value is sent( Higher OR Lower) then your pivot value.
ObjectQuickSorter sortStrings = new ObjectQuickSorter();
sortStrings.sort(arrayHere);
class ObjectQuickSorter{
void sort(String[] array){
doQuickSort(array, 0, array.length -1);
}
private static void doQuickSort(String[] array,int start, int end){
int pivotPoint;
if(start < end){
pivotPoint = partition(array, start, end);
doQuickSort(array, start, pivotPoint -1);
doQuickSort(array, pivotPoint + 1, end);
}
}
private static int partition(String[] array, int start, int end){
String pivotValue;
int endOfLeftList;
int mid = (start + end)/2;
swap(array, start, mid);
pivotValue = array[start];
endOfLeftList = start;
for(int scan = start + 1; scan <= end; scan++){
// trying to compare pivot = string value to array[scan] position value
// doing this by setting pivot value compare to itself to return 0
// then also comparing pivot value to array[scan] to return -1, 0, 1
// if return is 0 or 1 then it ignores it
if( array[scan].compareTo(pivotValue) < array[start].compareTo(pivotValue)){
endOfLeftList++;
swap(array, endOfLeftList,scan);
}
}
swap(array, start, endOfLeftList);
return endOfLeftList;
}
private static void swap(String[] array, int a, int b){
String temp;
temp = array[a];
array[a] = array[b];
array[b] = temp;
}
}

Using Binary Search with sorted Array with duplicates [duplicate]

This question already has answers here:
Finding multiple entries with binary search
(15 answers)
Closed 3 years ago.
I've been tasked with creating a method that will print all the indices where value x is found in a sorted array.
I understand that if we just scanned through the array from 0 to N (length of array) it would have a running time of O(n) worst case. Since the array that will be passed into the method will be sorted, I'm assuming that I can take advantage of using a Binary Search since this will be O(log n). However, this only works if the array has unique values. Since the Binary Search will finish after the first "find" of a particular value. I was thinking of doing a Binary Search for finding x in the sorted array, and then checking all values before and after this index, but then if the array contained all x values, it doesn't seem like it would be that much better.
I guess what I'm asking is, is there a better way to find all the indices for a particular value in a sorted array that is better than O(n)?
public void PrintIndicesForValue42(int[] sortedArrayOfInts)
{
// search through the sortedArrayOfInts
// print all indices where we find the number 42.
}
Ex: sortedArray = { 1, 13, 42, 42, 42, 77, 78 } would print: "42 was found at Indices: 2, 3, 4"
You will get the result in O(lg n)
public static void PrintIndicesForValue(int[] numbers, int target) {
if (numbers == null)
return;
int low = 0, high = numbers.length - 1;
// get the start index of target number
int startIndex = -1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (numbers[mid] > target) {
high = mid - 1;
} else if (numbers[mid] == target) {
startIndex = mid;
high = mid - 1;
} else
low = mid + 1;
}
// get the end index of target number
int endIndex = -1;
low = 0;
high = numbers.length - 1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (numbers[mid] > target) {
high = mid - 1;
} else if (numbers[mid] == target) {
endIndex = mid;
low = mid + 1;
} else
low = mid + 1;
}
if (startIndex != -1 && endIndex != -1){
for(int i=0; i+startIndex<=endIndex;i++){
if(i>0)
System.out.print(',');
System.out.print(i+startIndex);
}
}
}
Well, if you actually do have a sorted array, you can do a binary search until you find one of the indexes you're looking for, and from there, the rest should be easy to find since they're all next to each-other.
once you've found your first one, than you go find all the instances before it, and then all the instances after it.
Using that method you should get roughly O(lg(n)+k) where k is the number of occurrences of the value that you're searching for.
EDIT:
And, No, you will never be able to access all k values in anything less than O(k) time.
Second edit: so that I can feel as though I'm actually contributing something useful:
Instead of just searching for the first and last occurrences of X than you can do a binary search for the first occurence and a binary search for the last occurrence. which will result in O(lg(n)) total. once you've done that, you'll know that all the between indexes also contain X(assuming that it's sorted)
You can do this by searching checking if the value is equal to x , AND checking if the value to the left(or right depending on whether you're looking for the first occurrence or the last occurrence) is equal to x.
public void PrintIndicesForValue42(int[] sortedArrayOfInts) {
int index_occurrence_of_42 = left = right = binarySearch(sortedArrayOfInts, 42);
while (left - 1 >= 0) {
if (sortedArrayOfInts[left-1] == 42)
left--;
}
while (right + 1 < sortedArrayOfInts.length) {
if (sortedArrayOfInts[right+1] == 42)
right++;
}
System.out.println("Indices are from: " + left + " to " + right);
}
This would run in O(log(n) + #occurrences)
Read and understand the code. It's simple enough.
Below is the java code which returns the range for which the search-key is spread in the given sorted array:
public static int doBinarySearchRec(int[] array, int start, int end, int n) {
if (start > end) {
return -1;
}
int mid = start + (end - start) / 2;
if (n == array[mid]) {
return mid;
} else if (n < array[mid]) {
return doBinarySearchRec(array, start, mid - 1, n);
} else {
return doBinarySearchRec(array, mid + 1, end, n);
}
}
/**
* Given a sorted array with duplicates and a number, find the range in the
* form of (startIndex, endIndex) of that number. For example,
*
* find_range({0 2 3 3 3 10 10}, 3) should return (2,4). find_range({0 2 3 3
* 3 10 10}, 6) should return (-1,-1). The array and the number of
* duplicates can be large.
*
*/
public static int[] binarySearchArrayWithDup(int[] array, int n) {
if (null == array) {
return null;
}
int firstMatch = doBinarySearchRec(array, 0, array.length - 1, n);
int[] resultArray = { -1, -1 };
if (firstMatch == -1) {
return resultArray;
}
int leftMost = firstMatch;
int rightMost = firstMatch;
for (int result = doBinarySearchRec(array, 0, leftMost - 1, n); result != -1;) {
leftMost = result;
result = doBinarySearchRec(array, 0, leftMost - 1, n);
}
for (int result = doBinarySearchRec(array, rightMost + 1, array.length - 1, n); result != -1;) {
rightMost = result;
result = doBinarySearchRec(array, rightMost + 1, array.length - 1, n);
}
resultArray[0] = leftMost;
resultArray[1] = rightMost;
return resultArray;
}
Another result for log(n) binary search for leftmost target and rightmost target. This is in C++, but I think it is quite readable.
The idea is that we always end up when left = right + 1. So, to find leftmost target, if we can move right to rightmost number which is less than target, left will be at the leftmost target.
For leftmost target:
int binary_search(vector<int>& nums, int target){
int n = nums.size();
int left = 0, right = n - 1;
// carry right to the greatest number which is less than target.
while(left <= right){
int mid = (left + right) / 2;
if(nums[mid] < target)
left = mid + 1;
else
right = mid - 1;
}
// when we are here, right is at the index of greatest number
// which is less than target and since left is at the next,
// it is at the first target's index
return left;
}
For the rightmost target, the idea is very similar:
int binary_search(vector<int>& nums, int target){
while(left <= right){
int mid = (left + right) / 2;
// carry left to the smallest number which is greater than target.
if(nums[mid] <= target)
left = mid + 1;
else
right = mid - 1;
}
// when we are here, left is at the index of smallest number
// which is greater than target and since right is at the next,
// it is at the first target's index
return right;
}
I came up with the solution using binary search, only thing is to do the binary search on both the sides if the match is found.
public static void main(String[] args) {
int a[] ={1,2,2,5,5,6,8,9,10};
System.out.println(2+" IS AVAILABLE AT = "+findDuplicateOfN(a, 0, a.length-1, 2));
System.out.println(5+" IS AVAILABLE AT = "+findDuplicateOfN(a, 0, a.length-1, 5));
int a1[] ={2,2,2,2,2,2,2,2,2};
System.out.println(2+" IS AVAILABLE AT = "+findDuplicateOfN(a1, 0, a1.length-1, 2));
int a2[] ={1,2,3,4,5,6,7,8,9};
System.out.println(10+" IS AVAILABLE AT = "+findDuplicateOfN(a2, 0, a2.length-1, 10));
}
public static String findDuplicateOfN(int[] a, int l, int h, int x){
if(l>h){
return "";
}
int m = (h-l)/2+l;
if(a[m] == x){
String matchedIndexs = ""+m;
matchedIndexs = matchedIndexs+findDuplicateOfN(a, l, m-1, x);
matchedIndexs = matchedIndexs+findDuplicateOfN(a, m+1, h, x);
return matchedIndexs;
}else if(a[m]>x){
return findDuplicateOfN(a, l, m-1, x);
}else{
return findDuplicateOfN(a, m+1, h, x);
}
}
2 IS AVAILABLE AT = 12
5 IS AVAILABLE AT = 43
2 IS AVAILABLE AT = 410236578
10 IS AVAILABLE AT =
I think this is still providing the results in O(logn) complexity.
A Hashmap might work, if you're not required to use a binary search.
Create a HashMap where the Key is the value itself, and then value is an array of indices where that value is in the array. Loop through your array, updating each array in the HashMap for each value.
Lookup time for the indices for each value will be ~ O(1), and creating the map itself will be ~ O(n).
Find_Key(int arr[], int size, int key){
int begin = 0;
int end = size - 1;
int mid = end / 2;
int res = INT_MIN;
while (begin != mid)
{
if (arr[mid] < key)
begin = mid;
else
{
end = mid;
if(arr[mid] == key)
res = mid;
}
mid = (end + begin )/2;
}
return res;
}
Assuming the array of ints is in ascending sorted order; Returns the index of the first index of key occurrence or INT_MIN. Runs in O(lg n).
It is using Modified Binary Search. It will be O(LogN). Space complexity will be O(1).
We are calling BinarySearchModified two times. One for finding start index of element and another for finding end index of element.
private static int BinarySearchModified(int[] input, double toSearch)
{
int start = 0;
int end = input.Length - 1;
while (start <= end)
{
int mid = start + (end - start)/2;
if (toSearch < input[mid]) end = mid - 1;
else start = mid + 1;
}
return start;
}
public static Result GetRange(int[] input, int toSearch)
{
if (input == null) return new Result(-1, -1);
int low = BinarySearchModified(input, toSearch - 0.5);
if ((low >= input.Length) || (input[low] != toSearch)) return new Result(-1, -1);
int high = BinarySearchModified(input, toSearch + 0.5);
return new Result(low, high - 1);
}
public struct Result
{
public int LowIndex;
public int HighIndex;
public Result(int low, int high)
{
LowIndex = low;
HighIndex = high;
}
}
public void printCopies(int[] array)
{
HashMap<Integer, Integer> memberMap = new HashMap<Integer, Integer>();
for(int i = 0; i < array.size; i++)
if(!memberMap.contains(array[i]))
memberMap.put(array[i], 1);
else
{
int temp = memberMap.get(array[i]); //get the number of occurances
memberMap.put(array[i], ++temp); //increment his occurance
}
//check keys which occured more than once
//dump them in a ArrayList
//return this ArrayList
}
Alternatevely, instead of counting the number of occurances, you can put their indices in a arraylist and put that in the map instead of the count.
HashMap<Integer, ArrayList<Integer>>
//the integer is the value, the arraylist a list of their indices
public void printCopies(int[] array)
{
HashMap<Integer, ArrayList<Integer>> memberMap = new HashMap<Integer, ArrayList<Integer>>();
for(int i = 0; i < array.size; i++)
if(!memberMap.contains(array[i]))
{
ArrayList temp = new ArrayList();
temp.add(i);
memberMap.put(array[i], temp);
}
else
{
ArrayList temp = memberMap.get(array[i]); //get the lsit of indices
temp.add(i);
memberMap.put(array[i], temp); //update the index list
}
//check keys which return lists with length > 1
//handle the result any way you want
}
heh, i guess this will have to be posted.
int predefinedDuplicate = //value here;
int index = Arrays.binarySearch(array, predefinedDuplicate);
int leftIndex, rightIndex;
//search left
for(leftIndex = index; array[leftIndex] == array[index]; leftIndex--); //let it run thru it
//leftIndex is now the first different element to the left of this duplicate number string
for(rightIndex = index; array[rightIndex] == array[index]; rightIndex++); //let it run thru it
//right index contains the first different element to the right of the string
//you can arraycopy this [leftIndex+1, rightIndex-1] string or just print it
for(int i = leftIndex+1; i<rightIndex; i++)
System.out.println(array[i] + "\t");

Categories

Resources