I have written a program to place all even elements of the array to the left and odd ones to the right half of the array. The order of elements is not of concern. I was wondering if there is more efficient algorithm than this. My worst case complexity is O(n/2). Here is the code.
// Program to shift all even numbers in an array to left and odd to the right. Order of digits is not important.
import java.util.*;
import java.lang.*;
import java.io.*;
class Rearrange
{
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
int[] array = new int[] {1,2,3,4,5,6,7};
// keep two pointers.
int odd, even;
odd = 0;
even = array.length-1;
int i;
// Code to re-arrange the contents of the array
i=0;
while(i<array.length){
if(array[i]%2!=0){
odd = i;
break;
}
i++;
}
i=array.length-1;
while(i>=0){
if(array[i]%2==0){
even = i;
break;
}
i--;
}
while(odd<even){
if((array[odd]%2!=0) && (array[even]%2==0)){
// swap contents
array[odd] = array[odd] + array[even];
array[even] = array[odd] - array[even];
array[odd] = array[odd] - array[even];
odd++;
even--;
}
else if(array[odd]%2==0){
odd++;
}
else if(array[even]%2!=0){
even--;
}
else
continue;
}
for(int val : array)
System.out.println(val+" ");
}
}
For any algorithm without sufficient information about structure of data you cannot do it in less than O(N) where N is the input size because if you do it faster that means you are not considering a part of the input hence algorithm might be incorrect.
Here is in-place code for you problem :-
int i=0,j=n-1;
while(i<j) {
if(arr[i]%2==0) {
i++;
}
else {
swap(arr[i],arr[j]);
j--;
}
}
I don't see how is your code O(N/2). If array contains all odd or all even then one of the while loop will iterate through all n elements.
Instead of splitting code like you have done to get first odd/even numbers you can do something like quick sort, pivot element being last element and instead of separating less than and greater than you can check your criteria.
int i = 0;
int j = arr.length -1;
while(i < j){
if(arr[i]%2 != 0){
i++;
}
if(arr[j]%2 == 0){
j--;
}
//swap
arr[i] = arr[i] + arr[j];
arr[j] = arr[i] - arr[j];
arr[i] = arr[i] - arr[j];
}
Related
I came across a Hackerearth coding problem where you have to perform the following tasks over an integer array-
Search for a particular number in the array and replace it's occurrences with 1
Move all the 1s to the first part of the array, maintaining the original order of the array
For example- if we have an integer array {22,1,34,22,16,22,35,1}, here we search for the number "22" (let us assume it is present in the array), replace it with 1 and move all those 1s (including the 1s already present) to the first part of the array and the resultant array should look like {1,1,1,1,1,1,34,16,35} -maintaining the original order of the array, preferably in Java.
I actually have coded a solution and it works fine but is not optimal, can anyone help me find an optimal solution (w.r.t. time-space complexity)?
Below is my solution-
public static void main(String[] args) {
int[] n = rearr(new int[] {22,1,34,22,16,22,1,34,1}, 22);
for(int i=0; i<n.length; i++) {
System.out.print(n[i]+" ");
}
}
static int[] rearr(int[] a, int x) {
int[] temp = new int[a.length];
int j=0, c=0, k=0;
//search and replace
for(int i=0; i<a.length; i++) {
if(a[i] == x) {
a[i] = 1;
}
}
//shift all 1s to first part of array or shift all non-1s to last part of the array
for(int i=0; i<a.length; i++) {
if(a[i] != 1) {
temp[j] = a[i];
j++;
}
if(a[i] == 1) {
c++;
}
}
j=0;
for(int i=0; i<a.length && c>0; i++, c--) {
a[i] = 1;
j++;
}
for(int i=j ;i<a.length; i++) {
a[i] = temp[k];
k++;
}
return a;
}
This can be done in linear time and space complexity, by returning a completely new list instead of modifying the original list.
static int[] rearr(int[] a, int x) {
// allocate the array we'll return
int[] b = new int[a.length];
int fillvalue = 1;
// iterate backwards through the list, and transplant every value OTHER than
// (x or 1) to the last open index in b, which we track with b_idx
int b_idx = b.length - 1;
for (int i = a.length - 1; i >= 0; i--) {
if (a[i] != x && a[i] != fillvalue)) {
b[b_idx] = a[i];
b_idx--;
}
}
// once we've gone through and done that, fill what remains of b with ones
// which are either original or are replacements, we don't care
for (int i = b_idx; i >= 0; i--) {
b[i] = fillvalue;
}
return b;
}
This is linear space complexity because it requires additional space equal to the size of the given list. It's linear time complexity because, in the worst case, it iterates over the size of the list exactly twice.
As a bonus, if we decide we want to leave the original 1s where they were, we can do that without any trouble at all, by simply modifying the if condition. Same if we decide we want to change the fill value to something else.
Doing this with constant space complexity would require O(n^2) list complexity, as it would require swapping elements in a to their proper positions. The easiest way to do that would probably be to do replacements on a first run through the list, and then do something like bubblesort to move all the 1s to the front.
This can be done in a single iteration through the array. We can use 2 pointer approach here where we will use on pointer to iterate through the array and other one to point to the index of 1 in the array.
The code is below:
public static void main(String[] args) {
// input array
int[] arr = { 22, 1, 34, 22, 16, 22, 35, 1, 20, 33, 136 };
// element to be replaced
int x = 22;
int j = -1;
for (int i = arr.length - 1; i >= 0; i--) {
if (arr[i] == 1 || arr[i] == x) {
if (j == -1) {
j = i;
}
// incase arr[i]==x
arr[i] = 1;
} else {
if (j != -1) {
arr[j] = arr[i];
arr[i] = 1;
j--;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
Here we initialise j=-1 since we consider there are no 1's present in the array.
Then we start iterating the array from the end towards the starting of the array as we have to push all the 1's to the starting of the array. Now when we reach to 1 or x (particular number in your case), we check if this is first occurrence of the x or 1, if yes then we initialise the j with this index and change arr[i] = 1 because this could be equal to x then we need to make it 1. If the arr[i] is not 1 or x it means its a number which we need to push at back of the array. We check if we have position of 1 or j=-1. If j=-1 it means this number is already pushed back at end of array else we swap the number at i and j, and decrement j by 1.
At the end of the array we will have the array sorted in a fashion which is required.
Time Complexity: Since we are only iterating the array one, hence the time complexity is O(n).
Space Complexity: Since there are no extra space being used or constant space being used hence the space complexity is O(1)
I have the methods to find the smallest and largest value, and also to place them where they need to be. I also have a method to call those methods, and shrink to a subarray. The problem is, even though it is sorting, I can't print the array once I've moved into the subarray. Please help, there has to be a better way and I've banged my head against the wall for a while now.
package mySort;
import java.util.Arrays;
public class MyAlg {
public static int findSmall(int[] input){
int sm = input[0];
for(int i = 0; i <= input.length - 1; i++){
if(sm < input[i])
sm = input[i];
}
input[0] = sm;
return sm;
}
public static int findLarge(int[] input){
int lg = input[input.length -1];
for(int i = 0; i <= input.length - 1; i++){
if(input[i] > lg)
lg = input[i];
}
input[input.length -1] = lg;
return lg;
}
public static int[] sort(int[] input){
findSmall(input);
findLarge(input);
for(int i = 0; i<= (input.length - 1) / 2; i++){
int[] tmp = Arrays.copyOfRange(input, i + 1, input.length - 2 );
findSmall(tmp);
findLarge(tmp);
}
}
}
I am not sure if you are required to use an array or not, but if you are free to use whatever data structure you like I would recommend a TreeSet. This data structure implements SortedSet which means as the objects are added they are sorted already for you. Then you can use methods such as
first() - to return the lowest value
last() - to return the highest value
Then you could remove those highest and lowest elements or use these methods after that
ceiling(int) - highest number lower than given int
floor(int) - smallest number higher than given int
Lmk if you need more help or just need an implementation for an array.
Unfortunately your code is quite flawed, so I just rewrote everything. The below code will sort any int[] by placing the smallest int in the input array in the left most unfilled position of a new array and placing the biggest in the right most unfilled position of a new array, until the new array is a sorted version of the input array. Enjoy
private static int[] sort(int[] input) {
//create an empty array the same size as input
int[] sorted = new int[input.length];
//create another empty array the same size as input
int[] temp = new int[input.length];
// copy input into temp
for (int i = 0; i <= (input.length - 1); i++) {
temp[i] = input[i];
}
//create variables to tell where to put big and small
//in the sorted array
int leftIndex = 0;
int rightIndex = sorted.length - 1;
//create variables to hold the biggest and smallest values in
//input. For now we'll give them the values of the first element
//in input, they'll change
int big = input[0];
int small = input[0];
// sort
//sort the array as you described
while (temp.length != 0) {
//find the biggest and smallest value in temp
big = findBig(temp);
small = findSmall(temp);
//place the biggest at the end of the sorted array
//and place the smallest at the beginning of the sorted array
sorted[leftIndex] = small;
sorted[rightIndex] = big;
//move the left index of the sorted array up, so we don't over write
//the element we put in on the next iteration, same for the right index to,
//but down
leftIndex++;
rightIndex--;
if(temp.length != 1){
//remove the biggest and smallest values from the temp array
temp = removeElement(temp, big);
temp = removeElement(temp, small);
}else{
//only remove one element in the event the array size is odd
//also not at this point leftIndex == rightIndex as it will be the last
//element
temp = removeElement(temp, big);
}
//repeat, until the temp array is empty
}
// print out the content of the sorted array
for (int i = 0; i <= (sorted.length - 1); i++) {
System.out.println("Index " + i + ": " + sorted[i]);
}
//return the sorted array
return sorted;
}
//find the smallest number in an int array and return it's value
private static int findSmall(int[] input) {
int smallest = input[0];
for (int i = 0; i <= (input.length - 1); i++) {
if (smallest > input[i]) {
smallest = input[i];
}
}
return smallest;
}
//find the biggest value in an int array and return it's value
private static int findBig(int[] input) {
int biggest = input[0];
for (int i = 0; i <= (input.length - 1); i++) {
if (biggest < input[i]) {
biggest = input[i];
}
}
return biggest;
}
//remove an element from an int array, based on it's value
private static int[] removeElement(int[] input, int elementValue) {
//create a temp array of size input - 1, because there will be one less element
int[] temp = new int[input.length - 1];
//create variable to tell which index to remove, set to 0 to start
//will change unless it is right
int indexToRemove = 0;
//find out what the index of the element you want to remove is
for (int i = 0; i <= (input.length - 1); i++) {
if (input[i] == elementValue) {
//assign the value to
indexToRemove = i;
break;
}
}
//variable that says if we've hit the index we want to remove
boolean removeFound = false;
for (int i = 0; i <= (input.length - 1); i++) {
//check if we are at the index we want to remove
if (indexToRemove == i) {
//if we are say so
removeFound = true;
}
//done if we aren't at the index we want to remove
if (i != indexToRemove && removeFound == false) {
//copy input to temp as normal
temp[i] = input[i];
}
//done if we've hit the index we want to remove
if (i != indexToRemove && removeFound == true) {
//note the -1, as we've skipped one and need the to decrement
//note input isn't decremented, as we need the value as normal
//note we skipped the element we wanted to delete
temp[i - 1] = input[i];
}
}
//return the modified array that doesn't contain the element we removed
//and it is 1 index smaller than the input array
return temp;
}
}
Also, I'd place all of these methods into a class Sort, but I wrote it in this way to mimic the way you wrote your code to a certain extent. This would require you to create a getSorted method, and I'd also change the sort method to a constructor if it was placed in a class Sort.
I have written an algorithm to solve your this problem. Using divide and conquer we can solve this problem effectively. Comparing each value to every one the smallest and the largest value can be found. After cutting off 2 values the first one(smallest) and the last one (largest) the new unsorted array will be processed with the same algorithm to find the smallest and largest value.
You can see my algorithm in [GitHub] (https://github.com/jabedhossain/SortingProblem/)
Although its written in C++, the comments should be enough to lead you through.
So, I have to write an algorithm for my Coursera assignment in Data Structures. I have used Java for the following problem set.
Problem:- So, lets consider a sequence of numbers in an array of say 5 elements.
Number of elements - 5
Array elements - 2, 2 3, 9, 2
The majority element algorithm states that if an element appears more than n/2 times then it is the majority element in the array. Hence, my program should output 1(indicates that a majority element found), 0 (no majority element found).
As per the above question- 2 appears 3 times in the array which means n/2 times more (5/2 = 2(integer,ignoring the decimal) + 1 = 3)
So, I was asked to write an algorithm that could solve this problem. The options were divide and conquer (i.e. breaking the array into two halves and looking for majority element in both halves and then getting the answer)
Another option was to scan the elements in the array using two for loop and finally getting the majority element. This is what i tried. I ran through the grader but my program exceeds the time limit. Can anyone suggest any suggestions. Thank You.!
Java Code:-
import java.util.*;
import java.io.*;
public class MajorityElement {
private static int getMajorityElement(int[] a, int left, int right) {
int count = 1;
int num = a.length/2 + 1;
Arrays.sort(a);
if (left == right) {
return -1;
}
if (left + 1 == right) {
return a[left];
}
else
{
for(int i=0;i<a.length;i++)
{
for(int j=i+1;j<a.length;j++)
{
if(a[i]==a[j])
{
count++;
}
}
if(count>1)
{
if(count>=num)
{
return 1;
}
i = i + count-1;
count = 1;
}
}
return -1;
}
}
public static void main(String[] args) {
FastScanner scanner = new FastScanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
if (getMajorityElement(a, 0, a.length) != -1) {
System.out.println(1);
} else {
System.out.println(0);
}
}
static class FastScanner {
BufferedReader br;
StringTokenizer st;
FastScanner(InputStream stream) {
try {
br = new BufferedReader(new InputStreamReader(stream));
} catch (Exception e) {
e.printStackTrace();
}
}
String next() {
while (st == null || !st.hasMoreTokens()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
}
}
The two-for-loop approach is pretty much just this:
for (int x: a) {
int count = 0;
for (int y: a) {
if (x == y) {
count++;
if (count > a.length/2) {
return true;
}
}
}
}
return false;
That will certainly take too long in cases where there is no majority element, since it will require n^2 comparisons, where n is the number of elements in the list. Don't do that. You can sort first, like a commenter on your question said, which will allow you to break out a little early, but you still have the overhead of sorting, followed by some scanning. That would look something like (NOT TESTED, since it's for you to write):
Arrays.sort(a); // actually I hate this because it mutates your array (BAD!)
for (int i = 0; i < a.length; i++) {
int count = 0;
for (int j = i; i < j.length; j++) {
if (a[j] == a[i]) {
count++;
if (count > a.length / 2) {
return true;
}
} else if (a[j] > a[i]) {
break; // no more to count
}
}
}
return false;
You might instead want to go with the divide and conquer approach (n log n). There are also O(n) algorithms, including one by J. Moore, which goes like this:
count = 0
for (int x: a) {
if (count == 0) {
candidate = x;
}
if (x == candidate) {
count += 1
} else {
count -= 1
}
}
count = 0;
for (int x: a) if (a==candidate) count++;
return count > a.length / 2;
Treat the above as pseudo code, as it is not tested.
More information on majority element here but it's all in Python so it might not help.
Both of your options do not sound good to me. The problem you described is a standard problem in streaming algorithms (where you have a huge (potentially infinite) stream of data) and you have to calculate some statistics from this stream, passing through this stream once.
It can be solved using Boyer–Moore majority vote algorithm. I do not know Java, but here is my explanation and few lines of python code, which you can surely convert to Java.
The majority element is the element that occurs more than half of the size of the array. This means that the majority element occurs more than all other elements combined or if you count the number of times, majority element appears, and subtract the number of all other elements, you will get a positive number.
So if you count the number of some element, and subtract the number of all other elements and get the number 0 - then your original element can't be a majority element. This if the basis for a correct algorithm:
Have two variables, counter and possible element. Iterate the stream, if the counter is 0 - your overwrite the possible element and initialize the counter, if the number is the same as possible element - increase the counter, otherwise decrease it. Python code:
def majority_element(arr):
counter, possible_element = 0, None
for i in arr:
if counter == 0:
possible_element, counter = i, 1
elif i == possible_element:
counter += 1
else:
counter -= 1
return possible_element
It is clear to see that the algorithm is O(n) with a very small constant before O(n) (like 3). Also it looks like the space complexity is O(1), because we have only three variable initialized. The problem is that one of these variables is a counter which potentially can grow up to n (when the array consists of the same numbers). And to store the number n you need O(log (n)) space. So from theoretical point of view it is O(n) time and O(log(n)) space. From practical, you can fit 2^128 number in a longint and this number of elements in the array is unimaginably huge.
Also note that the algorithm works only if there is a majority element. If such element does not exist it will still return some number, which will surely be wrong. (it is easy to modify the algorithm to tell whether the majority element exists)
i don't understand what is the way to access the data in the array and use it as a condition the condition is to stop looping after the content exceeds 4,000,000 and also store and add the value if its value is an even number!
int[] a=new int[40];
int add=0;
a[0]=1;
a[1]=2;
int i=2;
do{
a[i]=a[i-1]+a[i-2];
System.out.println(a[i]);
if(a[i]%2==0)
{
add=add+a[i];
}
i++;
}
while(i<32);
System.out.println(add);
Just put a check for your variable add to see if its value is greater than 4,000,000 and break out of the loop. Do something like this:
if(add > 4000000) {
break;
}
So your final code will look like this:
int[] a=new int[40];
int add=0;
a[0]=1;
a[1]=2;
int i=2;
do{
a[i]=a[i-1]+a[i-2];
System.out.println(a[i]);
if(a[i]%2==0){add=add+a[i];}
if(add > 4000000) {
break; //this will get you out of your loop
}
i++;
}while(i<32);
System.out.println(add);
I would just throw this out there: Using a do-while loop may be making this harder than it has to be. The first part of your code is totally reasonable, but the while i > 32 is less than clear.
I'd look at it this way. After you initialize your array and its first two values with
int[] a = new int[40];
a[0] = 1;
a[1] = 2;
You know that you've accounted for one even value (2). So just initialized add to 2.
Now for the loop. You want to start at i = 2, and iterate as long as add is less than or greater than 4,000,000, right? So make a for loop to express it:
for (int i = 2; add <= 4000000; i++) {
a[i] = a[i - 2] + a[i -1];
if (a[i] % 2 == 0) {
add += a[i];
}
}
No need for the i < 32, and no need for any break statements!
As a matter of interest, this is a good application for Java 8 streams.
class Fib implements IntSupplier {
private int current = 1;
private int previous = 0;
public int getAsInt() {
int next = current + previous;
previous = current;
current = next;
return current;
}
IntStream.generate(new Fib())
.limit(4000000)
.filter(n - > n % 2 == 0)
.sum();
I'm trying to find the median from an unsorted array in Java. First, I need to use the selection sort technique to sort the array, and I cannot use any Java library methods for sorting (so no Arrays.sort(array)). Also, I cannot sort the entire array either. I can only sort as many elements as necessary to find the median of the array. I suppose for an even array, it would be just half of the elements plus one (then find the average of the last two elements), and for an odd array it would just be half of the elements (the last being the median).
So I'm not sure how to stop the selection sort at just the right time and find the median from the last element or two of the partly sorted array. Below is what I have so far.
import java.util.Arrays;
public class EfficientMedian
{
public static void median(int[] values)
{
int i, j, temp;
double median;
//selection sort below
for (i = 0; i < values.length - 1; i++)
{
for (j = i + 1; j < values.length; j++)
{
if (values[i] > values[j])
{
temp = values[i];
values[i] = values[j];
values[j] = temp;
}
}
}
if (values.length % 2 == 0) //if the array is even
{
median = values[values.length/2]; //just a placeholder
}
else //if the array is odd
{
median = values[values.length/2];
}
System.out.println(Arrays.toString(values));
System.out.println(median);
}
public static void main(String[] args)
{
int[] array1 = {567, 2, 600, 6, 601}, array2 = {45, 300, 46, 49};
median(array1);
median(array2);
}
}
Your first loop selects elements to sort. If you only need median, you only need to sort values.length/2 elements. So you should edit this:
for (i = 0; i < values.length - 1; i++)
{
...
}
to
for (i = 0; i < values.length/2; i++)
{
...
}
and fyi in the "length of the array is odd" case, the convention is to average middle two values.