I was attempting this question of rotate array and getting TLE
Here is my code
class Solution
{
//Function to rotate an array by d elements in a counter-clockwise direction.
static void rotateArr(int arr[], int d, int n)
{
`// add your code here
for(int i=0;i<d;i++){
int left,j;
left=arr[0];
for(j=0;j<n-1;j++){
arr[j]=arr[j+1];
}
arr[n-1]=left;
}
}
}
The time complexity of your algorithm is O(d*n) or O(n^2) if d=n. You should do something more efficient than O(n^2). I think O(n) is the best you can do. I know an O(n) solution for this problem,
First, reverse all the elements in the array. Then reverse the first n-d element and then reverse the last d element. The length of the array is n
For example,
rotate the array A[] = {1, 2, 3, 4, 5, 6, 7} by 5 elements in a counter-clockwise direction.
first reverse all the elements,
A[] = {7, 6, 5, 4, 3, 2, 1}
then reverse first n-d or (7-5) or 2 elements,
A[] = {6, 7, 5, 4, 3, 2, 1}
now reverse the last d or 5 elements,
A[] = {6, 7, 1, 2, 3, 4, 5}
Related
Multiple solutions available online for union of arrays, I came up with one of my own which is working fine but again it has significant time complexities (which I obviously don't know). So in order to use similar logic in a better way I am asking here. Any suggestion would be great!
Initially there are two arrayList with different sizes and numbers in it.
First step is to append both of them in a single List
Second step is to sort the new array using Collections.sort()
method.
Third is to use .remove() to remove the duplicates from it.
Below is the code
//initial two arrays
array1[0, 2, 3, 4, 5] and array2[0, 1, 2, 3, 5, 7, 8]
//for loop to append them in one arrayList and sort
for(k = 0; k< array1.size();k++){
array3.add(array1.get(k));
}
for(k = 0; k< array2.size();k++){
array3.add(array2.get(k));
}
Collections.sort(array3);
//Now removing the duplicates
for(k=0; k<array3.size();k++){
if(k != array3.size()-1){
if(Objects.equals(array3.get(k), array3.get(k + 1))){
array3.remove(k);
}
}
}
You can do this optimally via hash sets
int[] array1 = {0, 2, 3, 4, 5};
int[] array2 = {0, 1, 2, 3, 5, 7, 8};
HashSet<Integer> union = new HashSet<>();
for (int element : array1) {
union.add(element);
}
// Add all the elements of the second array to the HashSet
for (int element : array2) {
union.add(element);
}
this solution does not guarantee the order of the elements in the union set.
IntStream.distinct
You can use distinct() operation, which maintains a LinkedHashSet under the hood to guarantee uniqueness of elements and preserve their order, to obtain the union of the given arrays:
int[] array1 = {0, 2, 3, 4, 5};
int[] array2 = {0, 1, 2, 3, 5, 7, 8};
int[] union = IntStream
.concat(Arrays.stream(array1), Arrays.stream(array2))
.distinct().toArray();
System.out.println(Arrays.toString(union));
Output:
[0, 2, 3, 4, 5, 1, 7, 8]
public class Main {
public static void main(String[] args) {
int[][] numbers = {{1, 2, 3} , {4, 5, 6, 7}}; //Is it defined?
int x = numbers[0][3]; // Should the output be 0?
System.out.println(x);
}
}
you may take a look here into the official oracle specification:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html
When you take a look on chapter (array access) you will see that:
"All arrays are 0-origin. An array with length n can be indexed by the integers 0 to n-1."
A 2D array is really an array of arrays. So you can do this.
int[][] arr = new int[4][];
arr[0] = new int[] {1,2,3};
arr[1] = new int[] {4,5,6,7};
arr[2] = new int[] {8,9,10,11,12,13};
arr[3] = new int[] {14,15};
And to print them.
for (int[] a : arr) {
System.out.println(Arrays.toString(a));
}
Prints
[1, 2, 3]
[4, 5, 6, 7]
[8, 9, 10, 11, 12, 13]
[14, 15]
Technically, there are no two-dimensional arrays. What you can have is an array of arrays; this is conveyed precisely by the [][] syntax.
In your example,
int[][] numbers = {{1, 2, 3} , {4, 5, 6, 7}};
the 0'th element of numbers, i.e., numbers[0], is a 3-element array, whereas numbers[1], is a 4-element array.
Accessing numbers[0][3] will raise an exception, since 3 is out of bounds for the 3-element array.
Reference to Java Language Specification: Chapter 10, Arrays.
Question: Given an array numbers = {2, 7, 8, 5, 1, 6, 3, 9, 4}. Check the below conditions, both the conditions should be satisfied.
a[i] > a[i-1] or if first element a[i] > a[i+1]
a[i] > a[i+1] or if last element a[lastelement] > a[lastelement - 1]
Therefore:
1st Iteration - 8, 6, 9 are peak values. Remove the smallest ele. Remove 6. New arr {2, 7, 8, 5, 1, 3, 9, 4}. Output Arr - {6}
2nd Iteration - 8, 9 are peak values. Remove the smallest ele. Remove 8. New arr {2, 7, 5, 1, 3, 9, 4}. Output Arr - {6, 8}
3rd Iteration - 7, 9 are peak values. Remove the smallest ele. Remove 7. New arr {2, 5, 1, 3, 9, 4}. Output Arr - {6, 7, 8}
4th Iteration - 5, 9 are peak values. Remove the smallest ele. Remove 5. New arr {2, 1, 3, 9, 4}. Output Arr - {6, 7, 8, 5}
5th Iteration - 2, 9 are peak values. Remove the smallest ele. Remove 2. New arr {1, 3, 9, 4}. Output Arr - {6, 7, 8, 5, 2}
6th Iteration - 9 are peak values. Remove the smallest ele. Remove 9. New arr {1, 3, 4}. Output Arr - {6, 7, 8, 5, 2, 9}
7th Iteration - 4 are peak values. Remove the smallest ele. Remove 4. New arr {1, 3}. Output Arr - {6, 7, 8, 5, 2, 9, 4}
8th Iteration - 3 are peak values. Remove the smallest ele. Remove 3. New arr {1}. Output Arr - {6, 7, 8, 5, 2, 9, 4, 3}
9th Iteration - 1 are peak values. Remove the smallest ele. Remove 1. New arr {1}. Output Arr - {6, 7, 8, 5, 2, 9, 4, 3, 1}
Output: {6, 8, 7, 5, 2, 9, 4, 3, 1}
My solution is working but I am looking for optimized solution. Please let me know.
Here is my code:
public int[] findMinimumPeaks(int[] arr){
List<Integer> list1 = new ArrayList<Integer>(arr.length);
int[] output = new int[arr.length];
for(int i: arr)
list1.add(i);
for(int i =0; i<arr.length; i++){
int minIndex = minimumPeakElement(list1);
output[i] = list1.get(minIndex);
list1.remove(minIndex);
}
return output;
}
public int minimumPeakElement(List<Integer> list1){
int minIndex = 0, peakStart = Integer.MAX_VALUE, peakEnd = Integer.MAX_VALUE;
int peak = Integer.MAX_VALUE, minPeak = Integer.MAX_VALUE;
if(list1.size() >= 2){
if(list1.get(0) > list1.get(1)) peakStart = list1.get(0);
if(list1.get(list1.size() - 1) > list1.get(list1.size() - 2)) peakEnd = list1.get(list1.size() - 1);
if(peakStart < peakEnd){
minPeak = peakStart;
minIndex = 0;
}
else if(peakEnd < peakStart){
minPeak = peakEnd;
minIndex = list1.size() - 1;
}
}
for(int i=1; i<list1.size() - 1; i++){
if(list1.get(i) > list1.get(i + 1) && list1.get(i) > list1.get(i-1)) peak = list1.get(i);
if(peak < minPeak){
minPeak = peak;
minIndex = i;
}
}
return minIndex;
}
Here is an idea how to optimize asymptotic complexity.
Use single pass over elements of your initial array to split it into "up-down" "slopes" or "hills", i.e. subsequence of elements in ascending order, followed by subsequence in descending order.
Store these slopes in the following datastructure:
val slopes = MinPriorityQueue<Slope>()
class Slope(
var first: Int, // first element of the slope
var last: Int, // last element of the slope
var peak: Int, // max or peak element
var els: MaxPriorityQueue<Int>(), // all elements of the slope
var prev: Slope?, // link to the previous slope in the list or null if first
var next: Slope? // link to the next slope in the list or null if last
)
Slopes should be comparable by their peak value.
Now, having this data structure, you can poll the slope that has minimal peak value in O(log(N)). After you polled the slope, you should update the slope by removing it's peak element (i.e. poll els, then update first, last, peak), also, slope might become eligible to be merged with the previous or next slope:
Admittedly, this solution is not an easy one, having a lot of things to maintain and large number of corner cases. However, it's much better in terms of asymptotic complexity.
Initial data structure build: O(n log(n))
Polling elements while maintaining slopes: O(n log (n))
Overall complexity: O(n log(n))
Notes:
One of the corner cases, if array can have duplicate elements, then inner priority queue (els) becomes MaxPriorityQueue<Pair<Int,Int>>, i.e. you need to store the number of potentially duplicate elements along with the element value.
MinPriorityQueue and MaxPriorityQueue is an abstract heap-based data structure with min and max element at the head respectively. Can be implemented with PriorityQueue in java
Is there a way to find the initial sequence from its prefix sums and suffix sums?
Prefix sum at ith position is the sum of all elements from beginning to ith position.
Suffix sum at ith position is the sum of all elements from last to ith position in reverse order.
For an example, the combined (prefix sums and suffix sums) sequence is as follows:
{1, 3, 3, 5, 6, 6}
The initial sequence was: {1, 2, 3}
Prefix sums: {1, 3, 6}, Suffix sums: {6, 5, 3}
In combined: {1, 3, 3, 5, 6, 6}
May be in some cases there are multiple possibilities.
Prefix Sum:
original array : {1, 2, 3}
prefix sum array : {1, 1+2, 1+2+3}
Suffix Sum:
original array : {1, 2, 3}
suffix sum array : {3+2+1, 3+2, 3}
As per your question, the combined array seems to be sorted. Therefore
Let combined array be c[] = {1, 1+2, 3, 3+2, 1+2+3, 3+2+1} = {1, 3, 3, 5, 6, 6}
Now, finding the original sequence:
If original array has n elements then combined array will have 2*n elements
Split the array like array1 = {c[0], c[2], c[4]} and array2 = {c[1], c[3], c[5]}
array1 will now have prefix sum and array2 will have suffix sum
Now array1 is sufficient to find the original sequence (as combined array is sorted
as per your question). Therefore original array would be {c[0], c[2]-c[0], c[4]-c[2]}
int length = combined_array.length/2;
int []prefix_breakup = new int[length];
int []original = new int[length];
for(int i=0; i<length ; i++){
if( i%2 == 0 ){
prefix_breakup[i] = combined_array[i];
}
}
original[0] = prefix_breakup[0];
for(int i=1; i<length ; i++){
original[i] = prefix_breakup[i] - prefix_breakup[i-1];
}
I have an array of 3 elements arraylist = {10000, 7000, 2000}.
I have 3 more elements {1,2,5,7}, {1,3,4,5,7} and {1,3,4,6,7}, where each of them are also arrays and I will get each of them from a loop. Each time the loop executes I will get an array like [1,2,5,7].
Now I want to execute each array {1,2,5,7}, {1,3,4,5,7} or {1,3,4,6,7} for only one value of array.
For example:
I want to execute
[1,2,5,7] for the value 10000,
[1,3,4,5,7] for 7000
and [1,3,4,6,7] for 2000.
I have tried to use for each loop but it does not fullfill my requirement.
Can anyone give me any solution or hint how to solve this problem??
int array[] = {10000, 7000, 2000};
int paths[][] = {
{1, 2, 5, 7},
{1, 3, 4, 5, 7},
{1, 3, 4, 6, 7}
};
for(int i = 0; i < array.length; i++){
int arrayElm = array[i]; // Here you will get array Element e.g. 10000, 2000 etc..
int pathElm[] = paths[i]; // Here you will get a path array e.g. [1, 2, 5, 7] etc..
// Do your operation here...
}
Code should look like this, it will read and print on console.
tempPath should be an array.
for(int i=0;i<array.length;i++)
{
System.out.println(array[i]) // Prints element of array.
tempPath = paths[i];
for(int j=0;j<tempPath.length;j++)
{
System.out.println(tempPath[j]); //prints individual elements from Path Array
}
}
Based on your example, you want some map, where arraylist contain keys, and paths is values.
For example you can use something like that:
List array = Arrays.asList(10000, 7000, 2000);
int paths[][] = {
{1, 2, 5, 7},
{1, 3, 4, 5, 7},
{1, 3, 4, 6, 7}
};
int requiredKey = 7000;
int[] result = paths[array.indexOf(requiredKey)];
but better just keep all this data into some Map