Kth Smallest Element in a Sorted Matrix - java

So I am working on a Leetcode question and my code works for some cases but fails for certain cases.
Here is the question:
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.
Note that it is the kth smallest element in the sorted order, not the kth distinct element.
Example:
matrix = [[1, 5, 9], [10, 11, 13], [12, 13, 15]]
k = 8
return: 13
My approach is to use a minHeap, even if it stated that the array is sorted I still needed to make sure that I have it sorted from least to greatest value.
Here is my code:
class Solution {
public int kthSmallest(int[][] matrix, int k) {
int row = matrix.length;
int col = matrix[0].length;
int result = 0;
HashMap<Integer, Integer> map = new HashMap<>();
//populate HashMap
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
map.put(matrix[i][j],
map.getOrDefault(matrix[i][j], 0) + 1);
}
}
PriorityQueue<Map.Entry<Integer, Integer>> pq =
new PriorityQueue<>((n1, n2) -> n1.getValue() - n2.getValue());
pq.addAll(map.entrySet());
for (int i = 0; i < k && !(pq.isEmpty()); i++) {
result = pq.poll().getKey();
}
return result;
}
}
Here are my inputs:
Input 1: [[1,5,9],[10,11,13],[12,13,15]]
k = 8
Input 2: [[1,2],[1,3]]
k = 1
Here are the outputs:
Output 1: 13
Output 2: 2
Notice that the code works just fine for my first input where the 8th smallest element in the 2d-array is 13, but for the second input, the code is returning 2 as my first smallest element rather than returning 1.
Can someone please help me fix the code? I ask that you please not implement some fancy shorthand sorting technique e.g. Arrays.sort... it's not ideal for me as I am trying to learn how to implement heaps. Thanks a bunch :)

For solving this problem we can also binary search (a bit more efficient):
public class Solution {
public static final int kthSmallest(final int[][] matrix, final int k) {
int lo = matrix[0][0];
int hi = matrix[matrix.length - 1][matrix[0].length - 1] + 1;
while (lo < hi) {
final int mid = lo + (hi - lo) / 2;
int count = 0;
int col = matrix[0].length - 1;
for (int row = 0; row < matrix.length; ++row) {
while (col >= 0 && matrix[row][col] > mid) {
col--;
}
count += (col + 1);
}
if (count < k) {
lo = mid + 1;
} else {
hi = mid;
}
}
return lo;
}
}

You can use the flatMapToInt method to iterate over the rows of a 2d array in one stream:
public static void main(String[] args) {
int[][] matrix1 = {{1, 5, 9}, {10, 11, 13}, {12, 13, 15}};
int[][] matrix2 = {{1, 2}, {1, 3}};
System.out.println(kthSmallest(matrix1, 8)); // 13
System.out.println(kthSmallest(matrix2, 1)); // 1
}
public static int kthSmallest(int[][] matrix, int k) {
return Arrays.stream(matrix)
.flatMapToInt(Arrays::stream)
.skip(k - 1)
.findFirst()
.getAsInt();
}

public static int kthSmallest(int[][] matrix, int k) {
return Arrays
.stream(matrix)
.flatMapToInt(x -> Arrays.stream(x))
.sorted()
.skip(k-1)
.findFirst()
.getAsInt();
}

public static int kthSmallestNumber(int[][] matrix, int k) {
return Arrays.stream(matrix).flatMapToInt(x->Arrays.stream(x))
.distinct()
.sorted()
.skip(k-1)
.findFirst()
.getAsInt();
}

Related

Rotate 2D matrix clockwise by 90 degree using array list only

Encountered this problem on hackerrank ,
Please guide on how to rotate a 2D array clockwise by 90 degree using ArrayList only?
Here is my code below:
public static List<List<Integer>> rotate(List<List<Integer>> matrix, int n) {
int N=n;
ArrayList<List<Integer>> temp = new ArrayList<>();
for (int j = 0; j < N; j++) {
for (int i = N - 1; i >= 0; i--)
matrix.get(i).get(j);
}
temp.add(matrix);
return temp;
}
}
It is possible to do it in place
public static List<List<Integer>> rotate(List<List<Integer>> matrix, int n) {
assert matrix.size() == n;
/*
1,2,3
4,5,6
7,8,9
*/
matrix.forEach(row -> {
assert row.size() == n;
for (int i = 0; i < n / 2; i++)
swap(row, i, row, n - 1 - i);
});
/*
3,2,1
6,5,4
9,8,7
*/
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
List<Integer> row1 = matrix.get(i - j);
List<Integer> row2 = matrix.get(n - 1 - j);
swap(row1, j, row2, n - 1 - i + j);
}
}
/*
7,4,1
8,5,2
9,6,3
*/
return matrix;
}
private static void swap(List<Integer> one, int i, List<Integer> two, int j) {
int tmp = one.get(i);
one.set(i, two.get(j));
two.set(j, tmp);
}
In case if according to the requirements of this challenge you're expected to return a newly created nested list, then you can prepopulate it and then manipulate with it as if it's a nested array.
The key point you need to understand in order to solve this problem - is how in indices are getting changed during rotation of element. And the best way to visualize this is to draw this process on a paper.
If you'll do that, you'll be able to observe that while rotating elements of a square matrix clockwise that:
a row becomes a column
row -> column // i -> j in the code
a new column index becomes equal to the matrix size n minus 1 minus previous row index
j -> (n - 1) - i
That's how it might be implemented:
public static List<List<Integer>> rotate(List<List<Integer>> matrix, int n) {
List<List<Integer>> result = getMatrix(n);
// i -> j & j -> (n - 1) - i
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int next = matrix.get(i).get(j);
result.get(j).set((n - 1) - i, next);
}
}
return result;
}
public static List<List<Integer>> getMatrix(int n) {
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i < n; i++) {
result.add(new ArrayList<>(Collections.nCopies(n, 0)));
}
return result;
}
main()
public static void main(String[] args) {
List<List<Integer>> rotatedList = rotate(List.of(
List.of(1, 2, 3),
List.of(4, 5, 6),
List.of(7, 8, 9)
), 3);
rotatedList.forEach(System.out::println);
}
Output:
[7, 4, 1]
[8, 5, 2]
[9, 6, 3]
Try this.
static <T> List<List<T>> rotate(List<List<T>> matrix) {
final int rows = matrix.size(), cols = matrix.get(0).size();
List<List<T>> result = new ArrayList<>(cols);
for (int c = 0; c < cols; ++c) {
List<T> newRow = new ArrayList<>(rows);
for (int r = rows - 1; r >= 0 ; --r)
newRow.add(matrix.get(r).get(c));
result.add(newRow);
}
return result;
}
and
List<List<Integer>> matrix = List.of(
List.of(1,2,3),
List.of(4,5,6));
List<List<Integer>> result = rotate(matrix);
for (List<Integer> row : result)
System.out.println(row);
output:
[4, 1]
[5, 2]
[6, 3]

Dividing a 1D array into a 2D array

So I have homework that asked me to:
Write a method that takes two parameters: an array of integers and an integer that represents a number of elements. It should return a two-dimensional array that results from dividing the passed one-dimensional array into rows that contain the required number of elements. Note that the last row may have less number of elements if the length of the array is not divisible by the required number of elements. For example, if the array {1,2,3,4,5,6,7,8,9} and the number 4 are passed to this method, it should return the two-dimensional array {{1,2,3,4},{5,6,7,8},{9}}.
I tried to solve it using this code:
public static int[][] convert1DTo2D(int[] a, int n) {
int columns = n;
int rows = a.length / columns;
double s = (double) a.length / (double) columns;
if (s % 2 != 0) {
rows += 1;
}
int[][] b = new int[rows][columns];
int count = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (count == a.length) break;
b[i][j] = a[count];
count++;
}
}
return b;
}
But I had a problem which is when I try to print the new array this is the output:
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 0, 0, 0]]
So how can I remove the 3 zeros at the end? Just a note that I can't use any method from java.util.* or any built-in method to do this.
Change the 2D array's initialization to not contain the second dimension: new int[rows][]. Your array now has null arrays inside it. You have to initialize those in your loop: b[i]=new int[Math.min(columns,remainingCount)]; where remainingCount is the amount of numbers outside the 2d array.
Populating a 2d array with values from a 1d array as long as they are present:
public static int[][] convert1DTo2D(int[] arr, int n) {
// row count
int m = arr.length / n + (arr.length % n == 0 ? 0 : 1);
// last row length
int lastRow = arr.length % n == 0 ? n : arr.length % n;
return IntStream.range(0, m)
.mapToObj(i -> IntStream.range(0, i < m - 1 ? n : lastRow)
.map(j -> arr[j + i * n])
.toArray())
.toArray(int[][]::new);
}
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int[][] arr2 = convert1DTo2D(arr1, 4);
System.out.println(Arrays.deepToString(arr2));
// [[1, 2, 3, 4], [5, 6, 7, 8], [9]]
}
See also: How to populate a 2d array with values from a 1d array?
It may be better to switch arguments in the method:
int[][] convert1DTo2D(int cols, int... arr)
to allow use of vararg.
Also, it is possible to iterate on the input array (single loop) instead of nested loops.
Example implementation:
public static int[][] convert1DTo2D(int cols, int... a) {
int lastRowCols = a.length % cols;
int rows = a.length / cols;
if (lastRowCols == 0) {
lastRowCols = cols;
} else {
rows++;
}
int[][] b = new int[rows][];
for (int i = 0; i < a.length; i++) {
int r = i / cols;
int c = i % cols;
if (c == 0) { // start of the row
b[r] = new int[r == rows - 1 ? lastRowCols : cols];
}
b[r][c] = a[i];
}
return b;
}
Adding this if-condition to your code will shorten the final array should it not be the right size:
...
final int[][] b = new int[rows][columns];
if ((a.length % columns) != 0) {
b[rows - 1] = new int[a.length % columns];
}
int count = 0;
...
% is the Modulo operator which gives you the remainder of a division of the first and second number.
9 % 4 would return 1, the exact size needed for our final array.
We then merely have to replace the final array with a new one of that size.

How can i find the smallest number in array while getting the element number

I have a problem that keep bugging me out. Finding the smallest number in array is easy but here is my problem; when you find the smallest number in array , the smallest number becomes a[0] th element of array.
What i want is , i want to find the smallest number and also which element it is. Such as this
a[0] a[1] a[2] a[3]
5 20 1 12
I want my code to write 1 is the smallest number and it's a[2] element of array
I just want to get the 2 from there so i can use it in rest of my code. Any help will be much appreciated. Thank you guys.
Edit : i tried this way before
int[] dizi = {5 , 12, 20, 1};
int gecici;
for (int i=0; i<4; i++) {
for (int y = 1; y<4; y++) {
if (dizi[i] > dizi[y]) {
gecici = dizi[i];
dizi[i] = dizi[y];
dizi[y] = gecici;
}
}
}
You could leverage IntStream.range in such case:
IntStream.range(0, arr.length)
.mapToObj(index -> new SimpleEntry<>(index, arr[index]))
.min(Comparator.comparingInt(SimpleEntry::getValue));
example:
int[] arr = new int[]{5,20 ,1 ,12};
IntStream.range(0, arr.length)
.mapToObj(index -> new SimpleEntry<>(index, arr[index]))
.min(Comparator.comparingInt(SimpleEntry::getValue))
.ifPresent(s -> System.out.println(s.getValue()+
" is the smallest number and it's index" + s.getKey() + "of array"));
int [] array = {0,1,2,3,4,5,6,7,8,9,10};
int smallestNum=array[0];
int smallestIndex=0;
for(int i=1;i<array[i];i++){
if(array[i] < smallestNum){ //if you want the last small number then use `<=` (if small number occur multiple times)
smallestNum = array[i];
smallestIndex=i;
}
}
If you are looking for every elements beginning from smaller to larger and their corresponding indices then you can do as follow:
public class Test {
public static class Pair implements Comparable<Pair> {
int value;
int index;
public Pair(int _value, int _index) {
this.value = _value;
this.index = _index;
}
#Override
public int compareTo(Pair that) {
return Integer.valueOf(this.value).compareTo(Integer.valueOf(that.value));
}
}
public static void main(String args[]) {
int[] a =new int[]{5, 20, 1, 12};
int n = a.length;
Pair[] p = new Pair[n];
for (int i = 0; i < n; ++i) p[i] = new Pair(a[i], i);
Arrays.sort(p);
for (int i = 0; i < n; ++i) {
System.out.println(i + "th minimum is "+ p[i].value +" and is located at index "+ p[i].index);
}
}
}
The complexity of above method will be of time complexity O(n log n). But, If you require to know only the minimum one and it's index , then you can easily retrieve it in O(n) time complexity as follows:
int[] a =new int[]{5, 20, 1, 12};
int n = a.length;
int minValue = Integer.MAX_VALUE, minIndex = 0;
for (int i = 0; i < n; ++i) {
if (minValue > a[i]) {
minValue = a[i];
minIndex = i;
}
}
System.out.println("Minimum value is : "+ minValue+ " and it is located at index: "+ minIndex);
Try this.
int[] a = {5, 20, 1, 12};
IntStream.range(0, a.length)
.mapToObj(i -> i)
.min(Comparator.comparing(i -> a[i]))
.ifPresent(i -> System.out.printf(
"%d is the smallest number and it's a[%d] element of array%n", a[i], i));
If your array is double then
double[] a = {5, 20, 1, 12};
IntStream.range(0, a.length)
.mapToObj(i -> i)
.min(Comparator.comparing(i -> a[i]))
.ifPresent(i -> System.out.printf(
"%f is the smallest number and it's a[%d] element of array%n", a[i], i));
You can do it in a method.
/**
* Returns min index of array x.
* (Returns -1 when length of array x is zero)
*/
static int findMinIndex(int[] x) {
return IntStream.range(0, x.length)
.mapToObj(i -> i)
.min(Comparator.comparing(i -> x[i]))
.orElse(-1);
}
And call like this.
int[] a = {5, 20, 1, 12};
int minIndex = findMinIndex(a);
System.out.printf("%d is the smallest number and it's a[%d] element of arraay%n",
a[minIndex], minIndex);
int[] arr = {3,66,22,44,55};
int small=arr[0];
int index=0;
for(int i=0;i<arr.length;i++){
if(arr[i]<small){
small = arr[i];
index = i;
}
}

How to rotate an array?

I have the following problem to test:
Rotate an array of n elements to the right by k steps.
For instance, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to
[5,6,7,1,2,3,4]. How many different ways do you know to solve this problem?
My solution in intermediate array:
With Space is O(n) and time is O(n), I can create a new array and then copy elements to the new array. Then change the original array by using System.arraycopy().
public void rotate(int[] nums, int k) {
if (k > nums.length)
k = k % nums.length;
int[] result = new int[nums.length];
for (int i = 0; i < k; i++) {
result[i] = nums[nums.length - k + i];
}
int j = 0;
for (int i = k; i < nums.length; i++) {
result[i] = nums[j];
j++;
}
System.arraycopy(result, 0, nums, 0, nums.length);
}
But is there a better way we can do it with bubble rotate (like bubble sort) in O(1) space?
Method 1 - The Reversal Algorithm(Good One):
Algorithm:
rotate(arr[], d, n)
reverse(arr[], l, n);
reverse(arr[], 1, n-d) ;
reverse(arr[], n - d + 1, n);
Let AB are the two parts of the input array where A = arr[0..n-d-1] and B = arr[n-d..n-1]. The idea of the algorithm is:
Reverse all to get (AB) r = BrAr.
Reverse A to get BrA. /* Ar is reverse of A */
Reverse B to get BA. /* Br is reverse of B */
For arr[] = [1, 2, 3, 4, 5, 6, 7], d =2 and n = 7
A = [1, 2, 3, 4, 5] and B = [ 6, 7]
Reverse all, we get BrAr = [7, 6, 5, 4, 3, 2, 1]
Reverse A, we get ArB = [7, 6, 1, 2, 3, 4, 5]
Reverse B, we get ArBr = [6, 7, 5, 4, 3, 1, 2]
Here is the Code Snippet:
void righttRotate(int arr[], int d, int n)
{
reverseArray(arr, 0, n-1);
reverseArray(arr, 0, n-d-1);
reverseArray(arr, n-d, n-1);
}
void reverseArray(int arr[], int start, int end)
{
int i;
int temp;
while(start < end)
{
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
Method 2 - A Juggling Algorithm
Divide the array in different sets where number of sets is equal to GCD of n and d and move the elements within sets.
If GCD is 1, then elements will be moved within one set only, we just start with temp = arr[0] and keep moving arr[I+d] to arr[I] and finally store temp at the right place.
Here is an example for n =12 and d = 3. GCD is 3 and
Let arr[] be {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
Elements are first moved in first set
arr[] after this step --> {4 2 3 7 5 6 10 8 9 1 11 12}
Then in second set.
arr[] after this step --> {4 5 3 7 8 6 10 11 9 1 2 12}
Finally in third set.
arr[] after this step --> {4 5 6 7 8 9 10 11 12 1 2 3}
Here is the code:
void leftRotate(int arr[], int d, int n)
{
int i, j, k, temp;
int gcd = gcd(d, n);
for (i = 0; i < gcd; i++)
{
/* move i-th values of blocks */
temp = arr[i];
j = i;
while(1)
{
k = j + d;
if (k >= n)
k = k - n;
if (k == i)
break;
arr[j] = arr[k];
j = k;
}
arr[j] = temp;
}
}
int gcd(int a,int b)
{
if(b==0)
return a;
else
return gcd(b, a%b);
}
Time complexity: O(n)
Auxiliary Space: O(1)
Method 3 - Rotate one by one:
righttRotate(arr[], d, n)
start
For i = 0 to i < d
Right rotate all elements of arr[] by one
end
To rotate by one, store arr[n-1] in a temporary variable temp, move arr[1] to arr[2], arr[2] to arr[3] …and finally temp to arr[0]
Let us take the same example arr[] = [1, 2, 3, 4, 5, 6, 7], d = 2, rotate arr[] by one 2 times. We get [7, 1, 2, 3, 4, 5, 6] after first rotation and [ 6, 7, 1, 2, 3, 4, 5] after second rotation.
Her is Code Snippet:
void leftRotate(int arr[], int d, int n)
{
int i;
for (i = 0; i < d; i++)
leftRotatebyOne(arr, n);
}
void leftRotatebyOne(int arr[], int n)
{
int i, temp;
temp = arr[n-n];
for (i = 0; i < n-1; i++)
arr[i] = arr[i+1];
arr[n - 1] = temp;
}
Time complexity: O(n*d)
Auxiliary Space: O(1)
The following code will do your job. This is for right rotate.
public void rightrotate(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
If you want to do left rotate just use the following
public void leftrotate(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
reverse(nums, 0, nums.length - 1);
}
When k is negative, it rotates to the left.
Space is O(1) and time is O(n)
static void rotate(int[] num, int k) {
int n = num.length;
k = k % n;
if (k < 0) k += n;
int[] result = new int[n];
System.arraycopy(num, 0, result, k, n - k);
System.arraycopy(num, n - k, result, 0, k);
System.arraycopy(result, 0, num, 0, n);
}
ArrayUtil class is used to provide following utilities in primitive array
swap array elements
reverse array between startIndex and endIndex
leftRotate array by shift
Algorithm for array rotation by shift-
If we have to reverse array by shift value then take mod(%) with array length so that shift will become smaller than array length.
Reverse array between index 0 and shift-1
Reverse array between index shift and length-1.
Reverse complete array between index 0 and length-1.
Space Complexity: In-place Algorithm, No extra space needed so O(1).
Time Complexity : Array reversal of size k take O(k/2) i.e swapping k/2 pairs of elements.
Array Reversal time- O(k) for k size array.
Total time in Rotation-
O(1) ..........for step 1
O(shift) ......for step 2
O(n - shift) ...for step 3
O(n) ...........for step 4
Total Time for array Rotation: O(1) + O(shift) + O(n-shift) + O(n) = O(n)
public class Solution {
public static void main(String[] args) {
int k = 3;
int a[] = {1,2,3,4,5,6,7};
ArrayUtil.leftRotate(a, k);
for (int i : a)
System.out.println(i);
}
}
class ArrayUtil {
public static final boolean checkIndexOutOfRange(int[] array, int index) {
if (index < 0 || index > array.length)
return true;
return false;
}
public static final void swap(int[] array, int i, int j) {
if (checkIndexOutOfRange(array, i) || checkIndexOutOfRange(array, j))
return;
int t = array[i];
array[i] = array[j];
array[j] = t;
}
public static final void reverse(int[] array, int startIndex, int endIndex) {
if (checkIndexOutOfRange(array, startIndex) || checkIndexOutOfRange(array, endIndex))
return;
while (startIndex < endIndex) {
swap(array, startIndex, endIndex);
startIndex++;
endIndex--;
}
}
public static final void reverse(int[] array) {
reverse(array, 0, array.length - 1);
}
public static final void leftRotate(int[] array, int shift) {
int arrayLength = array.length;
if (shift >= arrayLength)
shift %= arrayLength;
reverse(array, 0, shift - 1);
reverse(array, shift, arrayLength - 1);
reverse(array);
}
}
Partial Code for ONE time array rotation
last=number_holder[n-1];
first=number_holder[0];
//rotation
number_holder[0]=last;
for(i=1;i<n;i++)
{
last=number_holder[i];
number_holder[i]=first;
first=last;
}
Display the array
for(i=1;i<n;i++)
{
System.out.println(number_holder[i]);
}
AFAIK, there are three ways to rotate an array with O(1) extra space, or put it another way, to swap two contiguous subarray.
reverse approach. reverse both part, then reverse all. most easy to code.
successively swap two contiguous block, until all items are in place.
juggling rotate, shell sort like. -- worse cache performance.
C++ has builtin function std::rotate(), which takes three iterator first, middle, last,
and return new_middle, which is where the old first element lies in the rotated
sequence.
I have checked the implementation on my computer, which use second approach I listed above.
(line 1246 in /usr/lib/gcc/i686-pc-cygwin/5.4.0/include/c++/bits/stl_algo.h).
Below is my implementation of rotate, with test program.
#include <iostream>
#include <vector>
// same logic with STL implementation, but simpler, since no return value needed.
template <typename Iterator>
void rotate_by_gcd_like_swap(Iterator first, Iterator mid, Iterator last) {
if (first == mid) return;
Iterator old = mid;
for (; mid != last;) {
std::iter_swap(first, mid);
++first, ++mid;
if (first == old) old = mid; // left half exhausted
else if (mid == last) mid = old;
}
}
// same logic with STL implementation
template <typename Iterator>
Iterator rotate_by_gcd_like_swap_then_return_new_mid(Iterator first, Iterator mid, Iterator last) {
if (first == mid) return last;
if (mid == last) return first;
Iterator old = mid;
for(;;) {
std::iter_swap(first, mid);
++first, ++mid;
if (first == old) old = mid;
if (mid == last) break;
}
Iterator result = first; // when first time `mid == last`, the position of `first` is the new `mid`.
for (mid = old; mid != last;) {
std::iter_swap(first, mid);
++first, ++mid;
if (first == old) old = mid;
else if (mid == last) mid = old;
}
return result;
}
int main() {
using std::cout;
std::vector<int> v {0,1,2,3,4,5,6,7,8,9};
cout << "before rotate: ";
for (auto x: v) cout << x << ' '; cout << '\n';
int k = 7;
rotate_by_gcd_like_swap(v.begin(), v.begin() + k, v.end());
cout << " after rotate: ";
for (auto x: v) cout << x << ' '; cout << '\n';
cout << "sz = " << v.size() << ", k = " << k << '\n';
}
Above solutions talk about shifting array elements either by reversing them or any other alternative.
I've unique solution. How about determining the starting position of element after n rotations. Once we know that, then simply insert elements from that index and increment counter using modulus operation. Using this method we can avoid using extra array operations and so on.
Here is my code:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
void rotateLeft(int n,int r) {
vector<long int> vec(n);
int j = n;
// get the position of starting index after r left rotations.
while(r!=0) {
--j;
if(j==0)
j = n;
--r;
}
for(long int i=0;i<n;++i) {
// simply read the input from there and increment j using modulus operator.
cin>>vec[j];
j = (j+1)%n;
}
// print the array
for(long int i=0;i<n;++i)
cout<<vec[i]<<" ";
}
int rotateRight (int n,int r) {
// get the position of starting index after r left rotations.
int j = r % n;
vector<long int> vec(n);
for(int i=0;i<n;i++) {
cin>>vec[j];
j=(j+1)%n;
}
for(int i=0;i<n;i++)
cout<<vec[i]<<" ";
}
int main() {
long int n,r; // n stands from number of elements in array and r stands for rotations.
cin>>n>>r;
// Time Complexity: O(n+r) Space Complexity: O(1)
rotateLeft(n,r);
// Time Complexity: O(n) Space Complexity: O(1)
rotateRight(n,r);
return 0;
}
Python code:
def reverse(arr,start , end):
while(start <= end):
arr[start] , arr[end] = arr[end] , arr[start]
start = start+1
end = end-1
arr = [1,2,3,4,5,6,7]
n = 7
k = 2
reverse(arr,0,n-1)
# [7,6,5,4,3,2,1]
reverse(arr,0,n-1-k)
# [3,4,5,6,7,2,1]
reverse(arr,n-k,n-1)
# [3,4,5,6,7,1,2]
print arr
# [3, 4, 5, 6, 7, 8, 9, 1, 2]
In Ruby Its very simple, Please take a look, Its one line.
def array_rotate(arr)
i, j = arr.length - 1, 0
arr[j],arr[i], i, j = arr[i], arr[j], i - 1, j + 1 while(j<arr.length/2)
puts "#{arr}"
end
Input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
Output: [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
1.using a temp array and O(n) time
public static void rotateAnArrayUsingTemp(int arr[], int d, int n) {
int temp[] = new int[d];
int tempIndex = 0;
for (int i = 0; i < d; i++) {
temp[i] = arr[i];
}
for (int i = 0; i < arr.length - d; i++) {
arr[i] = arr[i + d];
}
for (int i = arr.length - d; i < arr.length; i++) {
arr[i] = temp[tempIndex++];
}
}
This is a simple solution to rotate an array.
public class ArrayRotate {
public int[] rotateArray(int array[], int k) {
int newArray[] = new int[array.length];
for (int i = 0; i < array.length; i++) {
newArray[(i + k) % array.length] = array[i];
}
System.arraycopy(newArray, 0, array, 0, array.length);
return newArray;
}
public static void main(String[] args) {
int array[] = { 1, 2, 3, 4, 5, 6, 7 };
ArrayRotate rotate = new ArrayRotate();
rotate.display(rotate.rotateArray(array, 3));
}
public void display(int array[]) {
for (int i : array) {
System.out.print(i + ",");
}
}
}
Runtime complexity is O(n)
There are several other algorithm to achieve the same.
using temp array
Rotate One By one
Juggling algorithm
reversal method
This solution is O(1) space and O(N) time. It is in C#, takes an array parameter and rotates it in place. The algorithm goes through the first s (the shift) elements, starting with the first element moves it to the s_th position, then moves the s_th to the 2s_th position etc. If each of the first s elements rotates back to itself then there will be (arrayLength / s) * s = arrayLength loops, and at the end the array will be rotated by s. If the first s elements do not rotate back themselves, then there will still be cycles, say if s = 4, there could be one cycle which is 1-3-1 and the second 2-4-2, the line - if (ind == indAtBeg), checks for a cycle and terminates the while loop. The variable loopCount increments, when there is a rotation starting at any of the first s elements.
public static void rotateArrayByS(int[] ar, int s)
{
int len = ar.Length, ind = 0, temp1 = ar[0],
temp2 /*temp1 and temp2 for switching elements*/,
loopCount /*rotations starting at the first s elemtns of ar*/ = 0;
s %= len;
while (loopCount < s)
{
int indAtBeg = ind;
temp1 = ar[ind];
bool done = false;
while (!done)
{
if (ind < s)
loopCount++;
ind = (ind + s) % len;
//cycle detected
if (ind == indAtBeg)
done = true;
//switch the elements
temp2 = ar[ind];
ar[ind] = temp1;
temp1 = temp2;
}
++ind;
}
}
#include <stdio.h>
int
main(void)
{
int arr[7] = {1,2,3,4,5,6,7};
int new_arr[7] = {0};
int k = 3;
int len = 7;
int i=0;
for (i = (len-1); i>=0; i--) {
if ((i+k) >= len) {
new_arr[(i+k-len)] = arr[i];
} else {
new_arr[(i+k)] = arr[i];
}
}
for (i=0;i<len;i++) {
printf("%d ", new_arr[i]);
}
return 0;
}
Time complexity O(n)
Space complexity O(2*n).
Thanks.
Here is the complete Java code for left and right array rotation by k steps
import java.util.*;
public class ArrayRotation {
private static Scanner sc;
public static void main(String[] args) {
int n,k;
sc = new Scanner(System.in);
System.out.print("Enter the size of array: ");
n = sc.nextInt();
int[] a = new int[n];
System.out.print("Enter the "+n+" elements in the list: ");
for(int i=0;i<n;i++)
a[i] = sc.nextInt();
System.out.print("Enter the number of left shifts to array: ");
k = sc.nextInt();
System.out.print("Array before "+k+" shifts: ");
display(a);
leftRoation(a,k);
System.out.println();
System.out.print("Array after "+k+" left shifts: ");
display(a);
rightRoation(a,k);
System.out.println();
System.out.print("Array after "+k+" right shifts: ");
display(a);
}
public static void leftRoation(int[] a, int k){
int temp=0, j;
for(int i=0;i<k;i++){
temp = a[0];
// j=0; // both codes work i.e. for loop and while loop as well
// while(j<a.length-1){
// a[j]=a[j+1];
// j++;
// }
for(j=0;j<a.length-1;j++)
a[j]=a[j+1];
a[j]=temp;
}
}
public static void rightRoation(int[] a, int k){
int temp=0, j;
for(int i=0;i<k;i++){
temp = a[a.length-1];
for(j=a.length-1;j>0;j--)
a[j]=a[j-1];
a[j]=temp;
}
}
public static void display(int[] a){
for(int i=0;i<a.length;i++)
System.out.print(a[i]+" ");
}
}
/****************** Output ********************
Enter the size of array: 5
Enter the 5 elements in the list: 1 2 3 4 5
Enter the number of left and right shifts to array: 2
Array before 2 shifts: 1 2 3 4 5
Array after 2 left shifts: 3 4 5 1 2
Array after 2 right shifts: 1 2 3 4 5 // here the left shifted array is taken as input and hence after right shift it looks same as original array.
**********************************************/
My solution... (a: the array, n : size of array, k: number of shifts) :
public static int[] arrayLeftRotation(int[] a, int n, int k) {
if (k == 0) return a;
for (int i = 0; i < k; i++) {
int retenue = a[0];
int[] copie = java.util.Arrays.copyOfRange(a, 1, n );
for (int y = 0; y <= copie.length - 1 ; y++) {
a[y] = copie[y];
}
a[n-1] = retenue;
}
return a;
}
Java implementation for right rotation
public int[] solution(int[] A, int K) {
int len = A.length;
//Create an empty array with same length as A
int arr[] = new int[len];
for (int i = 0; i < len; i++) {
int nextIndex = i + K;
if (nextIndex >= len) {
// wraps the nextIndex by same number of K steps
nextIndex = nextIndex % len;
}
arr[nextIndex] = A[i];
}
return arr;
}
>>> k = 3
>>> arr = [1,2,3,4,5,6,7]
>>> actual_rot = k % len(arr)
>>> left_ar = arr[:-actual_rot]
>>> right_ar = arr[-actual_rot:]
>>> result = right_ar + left_ar
>>> result
[5, 6, 7, 1, 2, 3, 4]
A better way to rotate an array by k steps is:
a = [1,2,3,4,5,6]
b = a[:]
k = 2
for i in range(len(a)):
a[(i + k) % len(a)] = b[i]## (rotate right by k steps)
#a[(i - k) % len(a)] = b[i]## (rotate left by k steps)
print(a)
o/p:
[6, 5, 1, 2, 3, 4]
how to rotate an array, IN this function first argument - array, the second argument is
a number or integer.
def rotLeft(a, d):
data = a
n = d
get = data[n:len(data)]
remains = data[0:n]
data.clear()
for i in get:
data.append(i)
for x in remains:
data.append(x)
return data
This is rotating the array to the right by k steps, where k is non-negative
for (int i = 0; i < k; i++) {
for (int j = nums.length - 1; j > 0; j--) {
int temp = nums[j];
nums[j] = nums[j - 1];
nums[j - 1] = temp;
}
}
return nums;
if (k > arr.length) {
k = k % arr.length;
}
int n = arr.length - k;
int count = 0;
outer:
for (int i = arr.length - 1; i >= n; i--) {
int temp = arr[i];
inner:
for (int j = i - 1; j >= 0; j--) {
arr[j + 1] = arr[j];
if (j == 0) {
int temp2 = arr[j];
arr[j] = temp;
i = arr.length;
count++;
if (count == k) {
break outer;
}
}
}
}
Here I have solved the same problem in go.
Try to run in go playground...
sample code.
func rotate(a []int, k int) {
for j := 0; j < k ; j++ {
temp := a[len(a)-1]
for i := len(a) - 1; i > 0; i-- {
a[i] = a[i-1]
}
a[0] = temp
}
}
If you are looking for the soltuion of Codility - Cyclic Rotation Problem then, here is the JavaScript code which gave 100% for me.
function solution(A, K) {
const L = A.length - (K % A.length); // to get the rotation length value below array length (since rotation of product of array length gives same array)
const A1 = A.slice(L); // last part of array which need to be get to front after L times rotation
const A2 = A.slice(0, L); // part which rotate L times to right side
const Result = [...A1, ...A2]; // reverse and join both array by spreading
return Result;
}
Rotate an array of n elements to the right by k steps.
For instance, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
In JS the solution will be 2 part, in two line:
function rotateArray(array,k){
// remove the rotation part
const splice = [...array].splice(0,k); //... for make a clone;
// add reversed version of the what left
return array.concat(splice.reverse()) from original array.
}

Optimize code for Nth largest element in sorted matrix

I have a code for nth largest element in a sorted matrix (sorted row and column wise increasing order)
I had some problem doing the (findNextElement) part in the code
i.e if the row is exhausted, then go up one row and get the next element in that.
I have managed to do that, but the code looks kind of complex. (My code does work and produces the output correctly) I will post my code here
k is the Kth largest element
m, n are matrix dimensions (right now it just supports NxN matrix but can be modified to support MxN)
public int findkthLargestElement(int[][] input, int k, int m, int n) {
if (m <=1 || n <= 1 || k > m * n) {
return Integer.MIN_VALUE;
}
int i = 0;
int j = 0;
if (k < m && k < n) {
i = m - k;
j = n - k;
}
PriorityQueue<Element> maxQueue = new PriorityQueue(m, new Comparator<Element>() {
#Override
public int compare(Element a, Element b) {
return b.value - a.value;
}
});
Map<Integer, Integer> colMap = new HashMap<Integer, Integer>();
for (int row = i; row < m; row++) {
Element e = new Element(input[row][n - 1], row, n - 1);
colMap.put(row, n - 1);
maxQueue.add(e);
}
Element largest = new Element(0, 0, 0);
for (int l = 0; l < k; l++) {
largest = maxQueue.poll();
int row = largest.row;
colMap.put(row, colMap.get(row) - 1);
int col = colMap.get(row);
while (col < j && row > i) {
row = row - 1;
colMap.put(row, colMap.get(row) - 1);
col = Math.max(0, colMap.get(row));
}
Element nextLargest = new Element(input[row][Math.max(0, col)], row, Math.max(0, col));
maxQueue.add(nextLargest);
}
return largest.value;
}
I need some help in the for loop specifically, please suggest me a better way to accomplish the task.
I have my code running here
http://ideone.com/wIeZSo
Ok I found a a simple and effective way to make this work, I changed my for loop to ths
for (int l = 0; l < k; l++) {
largest = maxQueue.poll();
int row = largest.row;
colMap.put(row, colMap.get(row) - 1);
int col = colMap.get(row);
if (col < j) {
continue;
}
Element nextLargest = new Element(input[row][Math.max(0, col)], row, Math.max(0, col));
maxQueue.add(nextLargest);
}
If we are exhausted with a column then we do not add anymore items till we reach an element from some other column.
This will also work for matrix which are only sorted row wise but not column wise.
In response to the comment: Even if there are duplicate elements, I don't think that it is necessary to use sophisticated data structures like priority queues and maps, or even inner classes. I think it should be possible to simply start at the end of the array, walk to the beginning of the array, and count how often the value changed. Starting with the value "infinity" (or Integer.MAX_VALUE here), after the kth value change, one has the kth largest element.
public class KthLargestElementTest
{
public static void main (String[] args) throws java.lang.Exception
{
testDistinct();
testNonDistinct();
testAllEqual();
}
private static void testDistinct()
{
System.out.println("testDistinct");
int[][] input = new int[][]
{
{1, 2, 3, 4},
{8, 9, 10, 11},
{33, 44, 55, 66},
{99, 150, 170, 200}
};
for (int i = 1; i <= 17; i ++)
{
System.out.println(findkthLargestElement(input, i, 4, 4));
}
}
private static void testNonDistinct()
{
System.out.println("testNonDistinct");
int[][] input = new int[][]
{
{ 1, 1, 1, 4 },
{ 4, 4, 11, 11 },
{ 11, 11, 66, 66 },
{ 66, 150, 150, 150 }
};
for (int i = 1; i <= 6; i++)
{
System.out.println(findkthLargestElement(input, i, 4, 4));
}
}
private static void testAllEqual()
{
System.out.println("testAllEqual");
int[][] input = new int[][]
{
{ 4, 4, 4, 4 },
{ 4, 4, 4, 4 },
{ 4, 4, 4, 4 },
{ 4, 4, 4, 4 }
};
for (int i = 1; i <= 2; i++)
{
System.out.println(findkthLargestElement(input, i, 4, 4));
}
}
public static int findkthLargestElement(
int[][] input, int k, int m, int n)
{
int counter = 0;
int i=m*n-1;
int previousValue = Integer.MAX_VALUE;
while (i >= 0)
{
int value = input[i/n][i%n];
if (value < previousValue)
{
counter++;
}
if (counter == k)
{
return value;
}
previousValue = value;
i--;
}
if (counter == k)
{
return input[0][0];
}
System.out.println("There are no "+k+" different values!");
return Integer.MAX_VALUE;
}
}

Categories

Resources