I have a simple rotation function which takes an array and a number to rotate the numbers left
e.g. [1,2,3,4,5] & 2 - output: [3,4,5,1,2].
I want to know the most efficient way of completing this function, whether it would be to convert the int array into a string a splice it or whether to copy the array or to convert to an List<Integer>.
If anyone wants additional information please ask!
my solution at the moment:
static int[] rotLeft(int[] a, int d) {
int lengthOfArray = a.length;
int[] temp = new int[lengthOfArray];
for(int i = 0; i < lengthOfArray; i++){
int newLocation = (i + (lengthOfArray - d)) % lengthOfArray;
temp[newLocation] = a[i];
}
return temp;
}
Simple way to do it with O(n) complexity is as below along with handling of valid shifts int[] arr: is an int array, n=length of an array, d=how many shifts required.
public int[] leftRotate(int[] arr, int n, int d) {
int rot = 0;
int[] marr = new int[n];
if (d < 0 || d == 0 || d>n) {
return arr;
}
else {
for (int i = 0; i < n; i++) {
if (i < n - d) {
marr[i] = arr[i + d];
} else {
marr[i] = arr[rot];
rot++;
}
}
return marr;
}
}
public void GetArray(int[] arr, int n, int d) {
int[] arr1 = leftRotate(arr, n, d);
for (int j : arr1) {
System.out.println(j);
}
}
public static void main(String args[]) {
int[] arr = { 1,2,3,4,5 };
int n = arr.length;
Test2 obj = new Test2();
obj.GetArray(arr, n, 2);
}
Why don't you try this one
void Rotate(int arr[], int d, int n)
{
for (int i = 0; i < d; i++)
leftRotatebyOne(arr, n);
}
void leftRotatebyOne(int arr[], int n)
{
int i, temp;
temp = arr[0];
for (i = 0; i < n - 1; i++)
arr[i] = arr[i + 1];
arr[i] = temp;
}
and to call this invoke method like below
int arr[] = { 1, 2, 3, 4, 5 };
Rotate(arr, 2, 5);
Related
The purpose of this project is to create two arrays of random numbers and run a quick sort and heap sort of them. Keep track of the number of comparison's and then compare them. Both sorts work, but my heap sort wont keep track of the comparison's. it just says 0. My quick sort works and puts the comparisons in an array. How do i fix this?
package sorting;
import java.util.Arrays;
//import java.util.Random;
import java.util.*;
public class project2
{
static int [] heap_sort_comparison = new int[21];
static int [] quick_sort_comparison = new int[21];
static int [] array1 = new int [20];
static int [] array2 = new int [20];
static int compares = 0;
static int heap_compares = 0;
private static void quickSort(int[] array1, int l, int h) {
if(l < h ) {
compares++;
int position = partition(array1, l, h);
quickSort(array1,l, position -1);
quickSort(array1, position +1, h);
}
}
private static int partition(int[] array1, int i, int j) {
int pivot = array1[j] -1;
int small = i -1;
for(int k = i; k < j; k++) {
if(array1[k] <= pivot) {
compares++;
small++;
swap(array1, k, small);
}
}
swap(array1, j, small + 1);
//System.out.println("Pivot = " + array1[small + 1]);
print_quick_sort(array1);
return small + 1;
}
public static void swap(int[] array1, int a, int b) {
int temp;
temp = array1[a];
array1[a] = array1[b];
array1[b] = temp;
}
public static void print_quick_sort(int[] array1) {
for(int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + " ");
}
System.out.println();
}
//HEAP SORT
public void build(int array2[]) {
int length = array2.length;
for(int i = length/2-2; i >=0; i--) {
bubble_down(array2, i, array2.length-1);
heap_compares++;
}
for(int i = length-1; i>= 0; i--) {
swap2(array2, 0,i);
bubble_down(array2,i,0);
heap_compares++;
}
}
void bubble_down(int[] array2, int parent, int size) {
int left = parent*2+1;
int right = 2*parent+2;
int largest = 0;
if(left <= size && array2[left] > array2[largest]) {
largest = left;
heap_compares++;
}
if(right <= size && array2[right] > array2[largest]) {
largest = right;
heap_compares++;
}
if(largest != parent) {
swap2(array2,parent, largest);
bubble_down(array2,largest,size);
heap_compares++;
}
}
public static void swap2(int[] array2, int a, int b) {
int temp = array2[a];
array2[a] = array2[b];
array2[b] = temp;
}
public static void print_heap_sort(int[] array2) {
for(int i = 0; i < array2.length; i++) {
System.out.print(array2[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
for(int x = 0; x < 20; x++) {
for(int y = 0; y < 20; y++) {
for(int i = 0; i < array1.length; i++) {
array1[i] = array2[i]= (int)(Math.random()*20 + 0);
}
System.out.println("Numbers Generated in Array 1: " + Arrays.toString(array1));
System.out.println("");
System.out.println("Numbers Generated in Array 2: " + Arrays.toString(array2));
System.out.println("");
//quickSort
print_quick_sort(array1);
quickSort(array1, 0, array1.length -1);
System.out.println("The number of comparisons in quick sort: "+ compares);
System.out.println("=============================");
quick_sort_comparison[x] = compares;
compares = 0;
System.out.println("Array of quick sort comparison's: ");
System.out.println(Arrays.toString(quick_sort_comparison));
System.out.println("=============================");
//Heap Sort
System.out.println("Before Heap Sort: ");
System.out.println(Arrays.toString(array2));
heap_sort_comparison[y] = heap_compares;
heap_compares = 0;
HeapSort ob = new HeapSort();
ob.sort(array2);
System.out.println("Sorted array is (heap Sort): ");
print_heap_sort(array2);
System.out.println("=============================");
System.out.println("Array of heap sort comparison's: " + heap_compares);
System.out.println(Arrays.toString(heap_sort_comparison));
}
}
}
}
You do not even call the HeapSort method that you've built.
look here...
HeapSort ob = new HeapSort();
ob.sort(array2);
I think you are trying to use a built in sorting method from HeapSort class, So how do you think the counter heap_compares will increase!
My method should return the combination of array "a" and "b" returning the combination as a ordered array "c".
For a[5] and b[4,6] c[] should return [4,5,6]
In the end for these case my code is returning [4,5],i think there is a problem in the sorting method that i can't see.
package combinaum;
import java.util.Scanner;
/**
*
* #author 201627010262
*/
public class CombinaUm {
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
Scanner teclado = new Scanner (System.in);
int n1 = teclado.nextInt();
int n2 = teclado.nextInt();
int[] a = new int [n1];
int[] b = new int [n2];
for(int i = 0; i < n1; i++)
{
a[i] = teclado.nextInt();
}
for(int i = 0; i < n2; i++)
{
b[i] = teclado.nextInt();
}
System.out.println(Arrays.toString(Combine(a, b, n1, n2)));
}
public static int Combine(int a[], int b[], int n1, int n2)
{
int e = 0;
int d = 0;
int i = 0;
int n3 = n1+n2;
int [] c = new int [n3];
while(e < a.length && d <b.length )
{
if(a[e] < b[d])
{
c[i] = a[e];
e++;
i++;
}
else
{
c[i] = b[d];
d++;
i++;
}
}
while(e < a.length)
{
e++;
}
while(d <b.length)
{
d++;
}
return Arrays.copyOf(c, i);
}
}
You don't have to pass n1 and n2 parameters. Arrays know their size, and you can get it using a.length and b.length. Also you want to return int[] to have the whole array instead of single int.
public static int[] Combine(int a[], int b[]) {
int[] c = Arrays.copyOf(a, a.length + b.length);
System.arraycopy(b, 0, c, a.length, b.length);
return c;
}
I have a function
int[ ] fill(int[ ] arr, int k, int n) that returns an array with the length n and values consists of repetition of first k elements.
My code is:
class Repeat_block {
public static void main(String[] args) {
// TODO Auto-generated method stub
int k = 3;
int n = 10;
int arr[] = { 1, 2, 3, 5, 9, 12, -2, -1 };
System.out.println(Arrays.toString(fill(arr, k, n)));
}
public static int[] fill(int[] arr, int k, int n) {
int arr2[] = new int[n];
if (k == 0 || n <= 0) {
return null;
}
for (int i = 0; i < n; i++) {
if (i <k) {
arr2[i] = arr[i];
}
}
return arr2;
}
}
The function should return 1,2,3,1,2,3,1,2,3,1
but it's returning 1, 2, 3, 0, 0, 0, 0, 0, 0, 0 . I tried with so many ideas
but could not figure out to get the right logic. Anybody with some best ideas.
Once i == k, you need to reset it to 0. Hence you need to use two loop variables.
for (int i = 0, j = 0; i < n; i++, j++) {
if (j == k) {
j = 0;
}
arr2[i] = arr[j];
}
Replace your for-loop with:
for (int i = 0; i < n; i++) {
arr2[i] = arr[i % k]
}
Try this.
public static int[] fill(int[] arr, int k, int n) {
if (k == 0 || n <= 0) {
return null;
}
int[] ret = new int[n];
int counter = 0;
int value = 1;
while (counter < n) {
if (value > k) value = 1;
ret[counter] = value;
value++;
counter++;
}
return ret;
}
I thought it will be easy using streams and I am sure that it can be done much easier but here is my poor attempt:
import java.util.*;
import java.lang.*;
import java.util.stream.Collectors;
class Main
{
public static void main(String[] args) {
// TODO Auto-generated method stub
int k = 3;
int n = 10;
int arr[] = { 1, 2, 3, 5, 9, 12, -2, -1 };
fill(arr, k, n);
}
public static void fill(int[] arr, int k, int n) {
String elementsToCopy = Arrays.stream(arr)
.limit(k)
.mapToObj(String::valueOf)
.reduce((a,b) -> a.concat(",").concat(b))
.get();
List<String> resultInList = Collections.nCopies(n, elementsToCopy);
resultInList
.stream()
.collect(Collectors.toList());
System.out.println(resultInList
.toString()
.replace(" ", "")
.replace("[", "")
.substring(0, n+n-1));
}
}
Just for practice, I done that in Python3 :
def fill(arr,k,n):
c = math.ceil(n/k)
return (arr[0:k]*c)[0:n]
I'm given 2 integrals, the first is the number of segments (Xi,Xj) and the second is the number of points that can or cant be inside those segments.
As an example, the input could be:
2 3
0 5
8 10
1 6 11
Where, in first line, 2 means "2 segments" and 3 means "3 points".
The 2 segments are "0 to 5" and "8 to 10", and the points to look for are 1, 6, 11.
The output is
1 0 0
Where point 1 is in segment "0 to 5", and point 6 and 11 are not in any segment. If a point appears in more than one segment, like a 3, the output would be 2.
The original code, was just a double loop to search the points between segments. I used the Java Arrays quicksort (modified so when it sorts endpoints of segments, sorts also startpoints so start[i] and end[i] belong to the same segment i) to improve the speed of the double loop but it isnt enought.
The next code works fine but when there's too many segments it gets very slow:
public class PointsAndSegments {
private static int[] fastCountSegments(int[] starts, int[] ends, int[] points) {
sort(starts, ends);
int[] cnt2 = CountSegments(starts,ends,points);
return cnt2;
}
private static void dualPivotQuicksort(int[] a, int[] b, int left,int right, int div) {
int len = right - left;
if (len < 27) { // insertion sort for tiny array
for (int i = left + 1; i <= right; i++) {
for (int j = i; j > left && b[j] < b[j - 1]; j--) {
swap(a, b, j, j - 1);
}
}
return;
}
int third = len / div;
// "medians"
int m1 = left + third;
int m2 = right - third;
if (m1 <= left) {
m1 = left + 1;
}
if (m2 >= right) {
m2 = right - 1;
}
if (a[m1] < a[m2]) {
swap(a, b, m1, left);
swap(a, b, m2, right);
}
else {
swap(a, b, m1, right);
swap(a, b, m2, left);
}
// pivots
int pivot1 = b[left];
int pivot2 = b[right];
// pointers
int less = left + 1;
int great = right - 1;
// sorting
for (int k = less; k <= great; k++) {
if (b[k] < pivot1) {
swap(a, b, k, less++);
}
else if (b[k] > pivot2) {
while (k < great && b[great] > pivot2) {
great--;
}
swap(a, b, k, great--);
if (b[k] < pivot1) {
swap(a, b, k, less++);
}
}
}
// swaps
int dist = great - less;
if (dist < 13) {
div++;
}
swap(a, b, less - 1, left);
swap(a, b, great + 1, right);
// subarrays
dualPivotQuicksort(a, b, left, less - 2, div);
dualPivotQuicksort(a, b, great + 2, right, div);
// equal elements
if (dist > len - 13 && pivot1 != pivot2) {
for (int k = less; k <= great; k++) {
if (b[k] == pivot1) {
swap(a, b, k, less++);
}
else if (b[k] == pivot2) {
swap(a, b, k, great--);
if (b[k] == pivot1) {
swap(a, b, k, less++);
}
}
}
}
// subarray
if (pivot1 < pivot2) {
dualPivotQuicksort(a, b, less, great, div);
}
}
public static void sort(int[] a, int[] b) {
sort(a, b, 0, b.length);
}
public static void sort(int[] a, int[] b, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
dualPivotQuicksort(a, b, fromIndex, toIndex - 1, 3);
}
private static void rangeCheck(int length, int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new IllegalArgumentException("fromIndex > toIndex");
}
if (fromIndex < 0) {
throw new ArrayIndexOutOfBoundsException(fromIndex);
}
if (toIndex > length) {
throw new ArrayIndexOutOfBoundsException(toIndex);
}
}
private static void swap(int[] a, int[] b, int i, int j) {
int swap1 = a[i];
int swap2 = b[i];
a[i] = a[j];
b[i] = b[j];
a[j] = swap1;
b[j] = swap2;
}
private static int[] naiveCountSegments(int[] starts, int[] ends, int[] points) {
int[] cnt = new int[points.length];
for (int i = 0; i < points.length; i++) {
for (int j = 0; j < starts.length; j++) {
if (starts[j] <= points[i] && points[i] <= ends[j]) {
cnt[i]++;
}
}
}
return cnt;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n, m;
n = scanner.nextInt();
m = scanner.nextInt();
int[] starts = new int[n];
int[] ends = new int[n];
int[] points = new int[m];
for (int i = 0; i < n; i++) {
starts[i] = scanner.nextInt();
ends[i] = scanner.nextInt();
}
for (int i = 0; i < m; i++) {
points[i] = scanner.nextInt();
}
//use fastCountSegments
int[] cnt = fastCountSegments(starts, ends, points);
for (int x : cnt) {
System.out.print(x + " ");
}
}
I believe the problem is in the CountSegments() method but I'm not sure of another way to solve it. Supposedly, I should use a divide and conquer algorithm, but after 4 days, I'm up to any solution.
I found a similar problem in CodeForces but the output is different and most solutions are in C++. Since I have just 3 months that I started to learn java, I think I have reached my knowledge limit.
Given the constrains by OP, let n be the # of segments, m be the number of points to be query, where n,m <= 5*10^4, I can come up with a O(nlg(n) + mlg(n)) solution (which should be enough to pass most online judge)
As each query is a verifying problem: Can the point be covered by some intervals, yes or no, we do not need to find which / how many intervals the point has been covered.
Outline of the algorithm:
Sort all intervals first by starting point, if tie then by length (rightmost ending point)
Try to merge the intervals to get some disjoint overlapping intervals. For e.g. (0,5), (2,9), (3,7), (3,5), (12,15) , you will get (0,9), (12,15). As the intervals are sorted, this can be done greedily in O(n)
Above are the precomputation, now for each point, we query using the disjoint intervals. Simply binary search if any interval contains such point, each query is O(lg(n)) and we got m points, so total O(m lg(n))
Combine whole algorithm, we will get an O(nlg(n) + mlg(n)) algorithm
This is an implementation similar to #Shole's idea:
public class SegmentsAlgorithm {
private PriorityQueue<int[]> remainSegments = new PriorityQueue<>((o0, o1) -> Integer.compare(o0[0], o1[0]));
private SegmentWeight[] arraySegments;
public void addSegment(int begin, int end) {
remainSegments.add(new int[]{begin, end});
}
public void prepareArrayCache() {
List<SegmentWeight> preCalculate = new ArrayList<>();
PriorityQueue<int[]> currentSegmentsByEnds = new PriorityQueue<>((o0, o1) -> Integer.compare(o0[1], o1[1]));
int begin = remainSegments.peek()[0];
while (!remainSegments.isEmpty() && remainSegments.peek()[0] == begin) {
currentSegmentsByEnds.add(remainSegments.poll());
}
preCalculate.add(new SegmentWeight(begin, currentSegmentsByEnds.size()));
int next;
while (!remainSegments.isEmpty()) {
if (currentSegmentsByEnds.isEmpty()) {
next = remainSegments.peek()[0];
} else {
next = Math.min(currentSegmentsByEnds.peek()[1], remainSegments.peek()[0]);
}
while (!currentSegmentsByEnds.isEmpty() && currentSegmentsByEnds.peek()[1] == next) {
currentSegmentsByEnds.poll();
}
while (!remainSegments.isEmpty() && remainSegments.peek()[0] == next) {
currentSegmentsByEnds.add(remainSegments.poll());
}
preCalculate.add(new SegmentWeight(next, currentSegmentsByEnds.size()));
}
while (!currentSegmentsByEnds.isEmpty()) {
next = currentSegmentsByEnds.peek()[1];
while (!currentSegmentsByEnds.isEmpty() && currentSegmentsByEnds.peek()[1] == next) {
currentSegmentsByEnds.poll();
}
preCalculate.add(new SegmentWeight(next, currentSegmentsByEnds.size()));
}
SegmentWeight[] arraySearch = new SegmentWeight[preCalculate.size()];
int i = 0;
for (SegmentWeight l : preCalculate) {
arraySearch[i++] = l;
}
this.arraySegments = arraySearch;
}
public int searchPoint(int p) {
int result = 0;
if (arraySegments != null && arraySegments.length > 0 && arraySegments[0].begin <= p) {
int index = Arrays.binarySearch(arraySegments, new SegmentWeight(p, 0), (o0, o1) -> Integer.compare(o0.begin, o1.begin));
if (index < 0){ // Bug fixed
index = - 2 - index;
}
if (index >= 0 && index < arraySegments.length) { // Protection added
result = arraySegments[index].weight;
}
}
return result;
}
public static void main(String[] args) {
SegmentsAlgorithm algorithm = new SegmentsAlgorithm();
int[][] segments = {{0, 5},{3, 10},{8, 9},{14, 20},{12, 28}};
for (int[] segment : segments) {
algorithm.addSegment(segment[0], segment[1]);
}
algorithm.prepareArrayCache();
int[] points = {-1, 2, 4, 6, 11, 28};
for (int point: points) {
System.out.println(point + ": " + algorithm.searchPoint(point));
}
}
public static class SegmentWeight {
int begin;
int weight;
public SegmentWeight(int begin, int weight) {
this.begin = begin;
this.weight = weight;
}
}
}
It prints:
-1: 0
2: 1
4: 2
6: 1
11: 2
28: 0
EDITED:
public static void main(String[] args) {
SegmentsAlgorithm algorithm = new SegmentsAlgorithm();
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
for (int i = 0; i < n; i++) {
algorithm.addSegment(scanner.nextInt(), scanner.nextInt());
}
algorithm.prepareArrayCache();
for (int i = 0; i < m; i++) {
System.out.print(algorithm.searchPoint(scanner.nextInt())+ " ");
}
System.out.println();
}
I'm having a really big issue with finding the solution to my problem. I have to create a recursive, divide-and conquer algorithm that computes the length of the longest non-decreasing subsequence of elements in an array of integers. I have the following code, but it's not really working, any help would be much appreciated!!!
public class LongestSubSequence {
public static int getPartition(int[] a, int p, int r)
{
int mid = ((p+r)/2)-1;
int q=0;
int i = 1;
int j= mid+i;
int k = mid -i;
while (a[mid]<=a[j] && j < r)
{
q = j;
i++;
}
while (a[mid] >=a [k] && k > p)
{
q = k;
i++;
}
return q;
}
public static int getCount (int[]a, int p, int r)
{
int i = p;
int j = p+1;
int count = 0;
while (i<r && j<r)
{
if(a[i]<=a[j])
count++;
i++;
j++;
}
return count;
}
public static int getLongestSubsequence (int[] a, int p, int r) {
int count = 0;
if (p<r)
{
int q = getPartition (a, p, r);
count = getCount(a,p,r);
if (count < getLongestSubsequence(a,p,q))
count = getLongestSubsequence(a, p, q);
else if (count < getLongestSubsequence(a, q+1, p))
{
count = getLongestSubsequence(a, q+1, p);
}
}
return count;
}
public static int LongestSubsequence (int[] a) {
return getLongestSubsequence(a, 0, a.length);
}
public static void main(String[] args) {
int[] a = {1,3,5,9,2, 1, 3};
System.out.println(LongestSubsequence(a));
}
}
This is a pretty big body of code, and it's a little hard to follow with all the a's, r's, q's, etc.
In general, I would create an array (call it longestSeq) where longestSeq[i] is the length of the longest non-decreasing sequence found so far that starts at index, i, of your original sequence. For instance, if I had
int[] sequence = new int[] { 3, 5, 1, 2 }
then the algorithm would yield
longestSeq[0] = 2;
longestSeq[1] = 1;
longestSeq[2] = 2;
longestSeq[3] = 1;
So you would initialize longestSeq to all 0's, and then iterate through your list and fill in these values. At the end, just take the max of longestSeq.
Maybe start with just trying to make it work iteratively (without recursion) and then add recursion if that's a requirement.