What is the Nth card after k piles? - java

You have 100 cards, numbered 1 to 100. You distribute them into k piles and collect back the piles in order. For example, if you distribute them into 4 piles, then the first pile will contain the cards numbered 1, 5, 9, … and the 4 th pile will contain the cards numbered 4, 8, 12, …. While collecting back the cards you collect first the last pile, flip it bottom to top, then take the third pile, flip it bottom to top and put the cards on top of the 4th pile and so on. Next round, you distribute the cards into another set of piles and collect in the same manner (last pile first and first pile last).
If we have 10 cards, and put them into 2 piles, the order of the cards in the piles (top to bottom) would be 9, 7, 5, 3, 1 and 10, 8, 6, 4, 2
We flip the piles to get the order 1, 3, 5, 7, 9 and 2, 4, 6, 8, 10
We put the second pile at the bottom and first on top of it to get the deck 1, 3, 5, 7, 9, 2, 4, 6, 8, 10
Given the number of rounds (m), the number of piles in each round (ki), you need to write a program to find the Nth card from the top at the end of the final round.
Input:
The input consists of a single line of (m+2) comma-separated integers.
The first number is m, the number of rounds. The next m numbers are ki which represent the number of piles in each round.
The last number in the input is N, the position in the final pile whose value is to be determined.
Output: One integer representing the Nth card after all rounds have been played.
Constraints: Number of rounds <= 10, number of piles in each round <= 13.
Example 1
Input: 2, 2, 2, 4
Output: 13
Explanation:
m = 2, k1 = 2, k2 = 2 and N = 4.
We have two rounds. The first round has two piles. At the end of the round, the deck is in the following order: 1, 3, 5, …, 99, 2, 4, 6, …, 100
The next round also has 2 piles and after the second round, the cards are in the order 1, 5, 9, 13, ….
The fourth card from the top has number 13.
Example 2
Input: 3, 2, 2, 3, 2
Output: 13
Explanation:
m = 3, k1 = 2, k2 = 2, k3 = 3 and N = 2.
After the second round, the cards are in the order 1, 5, 9, 13, …
The third round has 3 piles. Thus after this round the cards will be in the order 1, 13, …. the Second card is 13

package leetcode;
import java.util.*;
public class Cards {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int arr[] = new int[100];
int temp[] = new int[100];
for(int i=0;i<100;i++)arr[i]=i+1;
int m = sc.nextInt();
for(int i=0;i<m;i++) {
int k = sc.nextInt();
int j=0,count=0;
while(count < k) {
for(int l=count;l<100;l=l+k) {
temp[j] = arr[l];j++;
}
count++;
}
for(int i1=0;i1<100;i1++) {
//System.out.print(temp[i1] + " ");
arr[i1] = temp[i1];
}
System.out.println("\n");
}
int res = sc.nextInt();
System.out.println(arr[res-1]);
}
}

Related

Find minimum peak elements in an array

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

how to find latest element added or deleted in dynamic array

I am getting an input array in loop which contains numbers in sorted order. on Every iteration the input array will either be added or be deleted with any one number (no duplicates in input array). Example
1st iteration: Input Array [3,4,8,19]
2nd iteration: Input Array [3,4,5,8,19]
Output: 5 added
3rd iteration: Input Array [3,4,5,8,19,40]
Output: 40 added
4th iteration: Input Array [3,5,8,19,40]
Output: 4 deleted
5th iteration: Input Array [1,3,5,8,19,40]
Output: 1 added
Note: I have a solution where I can take a map or different array and copy the input array in new array then from next iteration onward I'm going to iterate input array and compare the input array's elements with new array, the one not present in new array is the one added; and the one present in new array but not present in input array is the one deleted. I am looking for a better approach with most optimized logic in terms of space and time.
Given below is one of the simplest ways:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int first[] = { 3, 4, 8, 19 };
int second[] = { 3, 4, 5, 8, 19 };
int diff = Arrays.stream(second).sum() - Arrays.stream(first).sum();
System.out.println(Math.abs(diff) + (diff > 0 ? " added." : diff < 0 ? " deleted." : ""));
}
}
Output:
5 added.
Demo:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[][] testArrs = {
{ 3, 4, 8, 19 },
{ 3, 4, 5, 8, 19 },
{ 3, 4, 5, 8, 19, 40 },
{ 3, 5, 8, 19, 40 },
{ 1, 3, 5, 8, 19, 40 } };
int i, diff = 0, lastSum = Arrays.stream(testArrs[0]).sum(), currentSum;
for (i = 1; i < testArrs.length; i++) {
currentSum = Arrays.stream(testArrs[i]).sum();
diff = currentSum - lastSum;
System.out.println(Math.abs(diff) + (diff > 0 ? " added." : diff < 0 ? " deleted." : ""));
lastSum = currentSum;
}
}
}
Output:
5 added.
40 added.
4 deleted.
1 added.
If the array is always sorted and the input only changes in one place, then if you have access to both the old and the new array at each iteration, an efficient algorithm could search for the first different elememt between the arrays in O(log n) time with binary search. If mid points to different elements, look in the left half; otherwise, in the right.

How do I count repeated occurrences of an element in a list?

Say I have an arraylist = [1, 1, 1, 1, 1, 5, 5, 6, 3, 5, 6 2, 5, 1 , 1, 1, 1, 1, 4, 2, 4, 2, 5 ,2 ,6 ,3,5, 2, 5, 1 , 1, 1, 1, 1, 1, 4, 1, 5, 2,]
I would like to find all the start indexes of a sequence of x.
The sequence length must be > 2
For example x = 1
My expected output is this:
start at element 0, interval of size 5.
start at element 13, interval of size 5.
start at element 29, interval of size 6.
I am new to programming in java and I don't know what the logic would be.
I was thinking of using a for loop and looping through each element in the array and using a counter when the element i == 1. My problem is I'm not sure how to stop counting and resume counting between intervals.
public void count() {
int count = 0;
for(Integer number: ArrayList) {
if (number == 1 ) {
count++;
}
if (number != 1 ) {
break;
}
}
}
As you can see my attempts are pretty bad. I'm missing something crucial and just can't see it.
Please check sliding window approach:
https://medium.com/outco/how-to-solve-sliding-window-problems-28d67601a66
In general, you should use 2 pointers in the array,
The first one will indecte the beginning of the sequence, the second one will indecte about the length or the sequence.
You start moving with that start index untill you getting to you value, then moving with the second index untill reaching to a different number.
Then you record you result bye saving Pair of start index and length inside an ArrayList or any structure, and setting the startIndex =endindex+1
You can visit leetcode / geeksforgeeks for more related questions and topics
Try this
import java.util.*;
public class Main
{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
List<Integer> numbers = new ArrayList<Integer>();
numbers.addAll(Arrays.asList(1, 1, 1, 1, 1, 5, 5, 6, 3, 5, 6, 2, 5, 1, 1, 1, 1, 1, 4, 2, 4, 2, 5 ,2 ,6 ,3,5, 2, 5, 1, 1, 1, 1, 1, 1, 4, 1, 5, 2));
int startIndex = -1;
int count = 0;
System.out.print("Enter a number to count: ");
int x = scan.nextInt();
numbers.add(x-1);
for(int i = 0; i < numbers.size(); i++){
if(numbers.get(i) == x){
if(count == 0)
startIndex = i;
count++;
} else{
if(count > 2)
System.out.printf("start at index %d, interval of size %d \n", startIndex, count);
count = 0;
}
}
}
}
Output:
Enter a number to count: 1
start at index 0, interval of size 5
start at index 13, interval of size 5
start at index 29, interval of size 6
I am new to programming in java
...but this is not related to java, is it?
I don't know what the logic would be.
That's what you need to solve before trying to implement it.
Hint: Can you implement something slightly different? Change the input to number occurrences of 1s in a list, so your output would be [5, 5, 6, 1].
Hint 2: sometimes it's easier to add extra number (terminator) to original list, so let say if -1 cannot be there, add -1 to the end, so once you find -1, you know you are at the end...

Java change the position of integers in an array

I have to introduce 10 integers in an array. For example int A[] = {1,2,3,4,5,6,7,8,9,10}. Then I have to print the array in normal order which is fine, and after I have to make each element of the array hop over to the next position and the last element to the first position. Assuming we have the same integers in the array as before the result would be this: A[] = {10,1,2,3,4,5,6,7,8,9}
Here's my code so far but I get the out of bounds error. Also I don't know how to flip the last element to the first position
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int A[] = new int[10];
System.out.println("Introduce the array numbers");
for (int i = 0; i < 10; i++) {
A[i] = sc.nextInt();
}
//array in normal order
for (int i = 0; i < 10; i++) {
System.out.print("["+A[i]+"]");
}
//here i have to print the modified array
System.out.println("");
for (int i = 0; i < 10; i++) {
System.out.print("["+A[i+1]+"]");
}
}
As stated, the goal is to start with this array:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
And to modify it such that you wind up with this:
[10, 1, 2, 3, 4, 5, 6, 7, 8, 9]
What you are doing here, in essence, is pushing every number one spot to the right. The right-most number, when "pushed one spot to the right", will wrap around to the start of the array.
If we start by just taking the first number and copying it to the right, we run into a problem. The start of the array [1, 2] is now [1, 1]... which means we no longer know what number to push forward into the third slot. In other words, if we just blindly started at the beginning of the array and pushed numbers to the right, we'd wind up with this:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
The best way to solve this issue is to do our work starting at the end of the array, and then to work backwards. So first we push the 9 over to the right, then the 8, and so on.
Once we do that, the only problem is what we do with the first position. If we just moved everything over by one, we'd have this:
[???, 1, 2, 3, 4, 5, 6, 7, 8, 9]
To make matters worse, we might actually crash the program by trying to acces the "negative one-th" element to move it over to the zero index.
The best way around this is to break our problem up into three steps:
Save the last number in the array for later
For each position, starting from the end and working back to the second position, set the number to be equal to the number at the position before it
Set the first number in the array to the saved "last" number
Here's what that looks like in code:
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int last = numbers[numbers.length - 1]; // last now stores 10
// for index 9 to index 1, copy numbers to the right
for (int i = numbers.length - 1; i > 0; --i) {
numbers[i] = numbers[i - 1];
}
numbers[0] = last; // the first number is now 10

How to auto generate overlapping integers in a certain range

If the number range is 0 - 10. I would like to generate the following numbers
e.g.
unique 5 numbers [3, 8, 5, 1, 9]
unique 3 numbers [2, 6, 5]
5 numbers of which 2 numbers occur twice [2, 3, 2, 6, 3]
7 numbers of which 2 numbers occur twice [2, 5, 9, 2, 7, 5, 3] (Here 2, 5 occur twice)
5 numbers of which 1 number occur thrice [2, 3, 8, 3, 3] (Here 3 occurs twice)
7 numbers of which 1 number occur thrice and 1 number occurs twice [1, 5, 9, 1, 1, 5, 3] (Here 1 occurs thrice, 5 occurs twice)
How would you implement a generic function which caters to the above requirements.
EDIT1:
This is what I have right now..
protected List<Integer> fetchOverlapIntegers(int min, int max,
int howMany, int overlap) {
// The following code fetches unique numbers within the range
List<Integer> numbers = this.fetchRandomIntegers(min, max, howMany);
if (overlap > 0) {
int size = numbers.size();
for (int i = 0; i < overlap; i++) {
numbers.set(size - 1 - i, numbers.get(i));
}
}
Collections.shuffle(numbers);
return numbers;
}
Just for grins I wrote this up for this very underspecified problem:
public static List<Integer> weirdFunction(List<Integer> criteria, List<Integer> candidateNumbers) {
List<Integer> results = new ArrayList<Integer>();
for (int occurrenceCount = 0; occurrenceCount < criteria.size(); occurrenceCount++) {
int thisMany = criteria.get(occurrenceCount);
for (int i=0; i < thisMany; i++) {
Integer theChoice = candidateNumbers.get(new Random().nextInt(candidateNumbers.size()));
for (int ct=0; ct < occurrenceCount; ct++) {
results.add(theChoice);
}
}
}
Collections.shuffle(results);
return results;
}
It takes two lists, one which is the criteria which is basically a list of how many times it'll place a randomly chosen number in the results (the 1st one gets chosen once, the 2nd twice, etc.), and a list of candidateNumbers from which they'll be chosen.
But, this way only allows you to specify one particular "count" for each criteria. e.g. you can't have a list where "two numbers appear twice" because "appear twice" only has one slot. You could make this a list of lists or some other data structure of course.
Also, it doesn't eliminate duplicates when it pulls them in. So if we had a criteria of {1, 1, 1} it'd try and pull one number once, one number twice, and one number thrice. But it doesn't check if any of those are the same number - so it could end up pulling the same number each time and effectively pulling just one number six times instead of 3 separate numbers once, twice, and thrice.
You can randomly pull out items from the list of contender values, for example:
List<int> numbers = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Random r = new Random();
for (int i = 0; i < 4; i++)
{
int index = r.Next() % numbers.Count;
Console.WriteLine(numbers[index]);
numbers.RemoveAt(index);
}
If you want a value tripled, just triple the first removed. Then shuffle your results at the end.

Categories