I am trying to write a method called permutations. Basically, I want it to take in an integer and then return all of the permutations of the numbers from 0 to x -1. I realize this should return an array of arrays. However I am struggling to actually implement this. Can someone help me think about this in a better way? I am coding this in java. I realize this will probably be a recursion problem but other than that I am at a loss.
I thought about having two methods, one that takes in the integer and makes the first array from 0 - x-1. Then another method that takes in an array and some integer "start". This way the integer at index start will not change, but there will be swapping with the other numbers. This would be inside of a for loop so that the "start" position will change throughout the array. The only hint I have for this was that my for loop is going to recursively call the method. However I am having trouble thinking about how to actually implement this and the algorithm for the swapping.
Can someone tell me if I am thinking about this right and if they have any ideas or hints to give me? I do not have code to share since I have been white boarding the majority of my thoughts for this.
Permutation can be solved in a typical Backtrack algorithm in which we have to traverse all possibilities in the state space. Backtrack is a very important algorithm and my suggestion is that you have a look at it(which is usually in a recursion form) and try to master the basic idea of it, rather than trying to solving permuation problem in your own way.
Basically to find a permutaion we have to walk n steps(setting one bit is one step), after we choose one bit for each step, we have a permutation, so we have one possible solution(say, it is 1,2,3,4,5,6). After that, we backtrack to the second last bit, note that we chosed 5 in our first solution, but we can have another choice 6, after that we only have one choice for the last bit which is 5. For other solutions we continue to backtrack to the third last bit, fourth last bit..., and so on. That is the reason why backtrack is named.
You can compare backtrack with DFS, or traveral algorithm on a binary tree. They are in many places very similar with each other.
Below is my solution for this problem in which the result is an arrayList and permutaion is given according to 1...n instead of 0...n-1, but the thought in it is exactly the same.
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> permutations=new ArrayList();
backtrack(permutations,new ArrayList<Integer>(),nums);
return permutations;
}
private void backtrack(List<List<Integer>> permutations,List<Integer> tempList,int[] nums){
if(tempList.size()==nums.length){
permutations.add(new ArrayList<Integer>(tempList));
return;
}
for(int i=0;i<nums.length;i++){
if(tempList.contains(nums[i])){
continue;
}
tempList.add(nums[i]);
backtrack(permutations,tempList,nums);
tempList.remove(tempList.size()-1);
}
}
}
If I understood you correctly,this is smt you want?
public class MyClass_3928{
static List<String> listOfAllArrays = new ArrayList<>();
public static void calculate(int[] list, int n) {
if (n == 1) {
listOfAllArrays.add(Arrays.toString(list));
} else {
for (int i = 0; i < n; i++) {
calculate(list, n - 1);
int j = (n % 2 == 0) ? i : 0;
int t = list[n - 1];
list[n - 1] = list[j];
list[j] = t;
}
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("How many numbers would you like to permute?");
int numbers = Integer.valueOf(scanner.nextLine());
int[] numbersArray = new int[numbers-1];
System.out.println("Those numbers are");
for (int i = 0; i < numbers-1; i++) {
numbersArray[i] = i+1;
}
calculate(numbersArray, numbersArray.length);
for (int i = 0; i < listOfAllArrays.size(); i++) {
System.out.println(listOfAllArrays.get(i));
}
}
Related
I am trying to write a program that will iterate through all possible permutations of a String array, and return a two dimensional array with all the permutations. Specifically, I am trying to use a String array of length 4 to return a 2D array with 24 rows and 4 columns.
I have only found ways to print the Strings iteratively but not use them in an array. I have also found recursive ways of doing it, but they do not work, as I am using this code with others, and the recursive function is much more difficult.
For what I want the code to do, I know the header should be:
public class Permutation
{
public String[][] arrayPermutation(String[] str)
{
//code to return 2D array
}
}
//I tried using a recursive method with heap's algorithm, but it is very //complex with its parameters.
I am very new to programming and any help would be greatly appreciated.
Your permutation-problem is basically just an index-permutation problem.
If you can order the numbers from 0 to n - 1 in all possible variations, you can use them as indexes of your input array, and simply copy the Strings. The following algorithm is not optimal, but it is graphic enough to explain and implement iteratively.
public static String[][] getAllPermutations(String[] str) {
LinkedList<Integer> current = new LinkedList<>();
LinkedList<Integer[]> permutations = new LinkedList<>();
int length = str.length;
current.add(-1);
while (!current.isEmpty()) {
// increment from the last position.
int position = Integer.MAX_VALUE;
position = getNextUnused(current, current.pop() + 1);
while (position >= length && !current.isEmpty()) {
position = getNextUnused(current, current.pop() + 1);
}
if (position < length) {
current.push(position);
} else {
break;
}
// fill with all available indexes.
while (current.size() < length) {
// find first unused index.
int unused = getNextUnused(current, 0);
current.push(unused);
}
// record result row.
permutations.add(current.toArray(new Integer[0]));
}
// select the right String, based on the index-permutation done before.
int numPermutations = permutations.size();
String[][] result = new String[numPermutations][length];
for (int i = 0; i < numPermutations; ++i) {
Integer[] indexes = permutations.get(i);
String[] row = new String[length];
for (int d = 0; d < length; ++d) {
row[d] = str[indexes[d]];
}
result[i] = row;
}
return result;
}
public static int getNextUnused(LinkedList<Integer> used, Integer current) {
int unused = current != null ? current : 0;
while (used.contains(unused)) {
++unused;
}
return unused;
}
The getAllPermutations-method is organized in an initialization part, a loop collecting all permutations (numeric), and finally a convertion of the found index-permutation into the String-permutations.
As the convertion from int to String is trivial, I'll just explain the collection part. The loop iterates as long, as the representation is not completely depleted, or terminated from within.
First, we increment the representation (current). For that, we take the last 'digit' and increment it to the next free value. Then we pop, if we are above length, and look at the next digit (and increment it). We continue this, until we hit a legal value (one below length).
After that, we fill the remainder of the digits with all still remaining digits. That done, we store the current representation to the list of arrays.
This algorithm is not optimal in terms of runtime! Heap is faster. But implementing Heap's iteratively requires a non-trivial stack which is tiresome to implement/explain.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
I am working on a problem. Out of 17 test cases 10 works fine and gives the result in less than a second but in 7 cases it is taking 2 seconds which are beyond the time limit. Following is the code
import java.util.*;
import java.io.*;
class TestClass
{
static PrintWriter wr = new PrintWriter(System.out);
public static void func1(int arr[], int n)
{
int temp = arr[0];
for (int jj = 0; jj < n; jj++)
{
if (jj == (n - 1))
arr[jj] = temp;
else
arr[jj] = arr[jj + 1];
}
}
public static void func2(int arr[], int n, int rt)
{
int count = 0;
for (int a = 0; a < n; a++)
{
for (int b = a; b < n; b++)
{
if (arr[a] > arr[b])
count++;
}
}
if (rt == (n - 1))
wr.print(count);
else
wr.print(count + " ");
}
public static void main(String args[]) throws Exception
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine().trim();
StringTokenizer st = new StringTokenizer(str);
int t = Integer.parseInt(st.nextToken());
for (int i = 0; i < t; i++) //for test cases
{
str = br.readLine().trim();
st = new StringTokenizer(str);
int n = Integer.parseInt(st.nextToken());
int arr[] = new int[n];
str = br.readLine().trim();
st = new StringTokenizer(str);
for (int j = 0; j < n; j++) //to take input of array for each test case
{
arr[j] = Integer.parseInt(st.nextToken());
}
for (int rt = 0; rt < n; rt++) //for number of times circular shifting of array is done
{
func1(arr, n); //circularly shifts the array by one position
func2(arr, n, rt); //prints the number of inversion counts
}
if (i != (t - 1))
wr.println();
}
wr.close();
br.close();
}
}
Can someone suggest how to optimize the code so that it takes less time in execution.
I know BufferReader and PrintWriter takes less time as compared to Scanner and System.out.print. I was using scanner and System.out.print earlier but changed it later in hope of getting less time but it didn't help. Also I did it earlier without the use of func1 and func2 and did all the operations in main only. The time in both the cases remains the same.
I am getting the currect output in all the cases so code is correct, I just need help in optimizing it.
The website you are using acquires questions from past programming competitions. I recognize this as a familiar problem
Like most optimization questions, the preferred steps are:
Do less.
Do the same in fewer instructions.
Don't use functions.
Use faster instructions.
In your case, you have an array, and you wish to rotate it a number of times, and then to process it from the rotated position.
Rotating an array is an incredibly expensive operation, because you typically need to copy every element in the array into a new location. What is worse for you is that you are doing it the simplest way, you are rotating the array one step for every step needing rotation.
So, if you have a 100 element array that needs rotated 45 steps, you would then have (3 copies per element swap) 100 * 45 * 3 copies to perform your rotation.
In the above example, a better approach would be to figure out a routine that rotates an array 45 elements at a time. There are a number of ways to do this. The easiest is to double the RAM requirements and just have two arrays
b[x] = a[(mod(x+45), a.length)]
An even faster "do less" would be to never rotate the array, but to perform the calculation in reverse. This is conceptually the function of the desired index in the rotated array to the actual index in the pre-rotated array. This avoids all copying, and the index numbers (by virtue of being heavily manipulated in the math processing unit) will already be stored in the CPU registers, which is the fastest RAM a computer has.
Note that once you have the starting index in the original array, you can then calculate the next index without going through the calculation again.
I might have read this problem a bit wrong; because, it is not written to highlight the problem being solved. However, the core principles above apply, and it will be up to you to apply them to the exact specifics of your programming challenge.
An example of a faster rotate that does less
public static void func1(int arr[], int shift) {
int offset = shift % arr.length;
int [] rotated = new int[arr.length];
// (arr.length - 1) is the last index, walk up till we need to copy from the head of arr
for (int index = 0; index < (arr.length - 1) - offset; index++) {
rotated[index] = arr[index+offset];
}
// copy the end of the array back into the beginning
for ( int index = (arr.length - 1) - offset; index < arr.length; index++ ) {
rotated[index] = (offset - ((arr.length - 1) - index) - 1);
}
System.arraycopy(rotated, 0, arr, 0, arr.length);
}
This copies the array into its rotated position in one pass, instead of doing a pass per index to be rotated.
The first rule of optimisation (having decided it is necessary) is to use a profiler. This counts how many times methods are invoked, and measures the accumulated time within each method, and gives you a report.
It doesn't matter if a method is slow if you only run it a few times. If you run it hundreds of thousands of times, you need to either make it faster, or run it fewer times.
If you're using a mainstream IDE, you already have a profiler. Read its documentation and use it.
The other first rule of optimisation is, if there's already literature about the problem you're trying to solve, read it. Most of us might have invented bubble-sort independently. Fewer of us would have come up with QuickSort, but it's a better solution.
It looks as if you're counting inversions in the array. Your implementation is about as efficient as you can get, given that naive approach.
for(int i=0; i< array.length; i++) {
int n1 = array[i];
for(int j=i+1; j< array.length; j++) {
n2 = array[j];
if(n1 > n2) {
count++;
}
}
}
For an array of length l this will take ( l - 1) + ( l - 2 ) ... 1 -- that's a triangular number, and grows proportionally to the square of l.
So for l=1000 you're doing ~500,000 comparisons. Then since you're repeating the count for all 1000 rotations of the array, that would be 500,000,000 comparisons, which is definitely the sort of number where things start taking a noticeable amount of time.
Googling for inversion count reveals a more sophisticated approach, which is to perform a merge sort, counting inversions as they are encountered.
Otherwise, we need to look for opportunities for huge numbers of loop iterations. A loop inside a loop makes for big numbers. A loop inside a loop inside another loop makes for even bigger numbers.
You have:
for (int i = 0; i < t; i++) {
// stuff removed
for (int rt = 0; rt < n; rt++) {
// snip
func2(arr, n, rt); //prints the number of inversion counts
}
// snip
}
public static void func2(int arr[], int n, int rt) {
// snip
for (int a = 0; a < n; a++) {
for (int b = a; b < n; b++) {
// stuff
}
}
// snip
}
That's four levels of looping. Look at the input values for your slow tests, and work out what n * n * n * t is -- that an indicator of how many times it'll do the work in the inner block.
We don't know what your algorithm is supposed to achieve. But think about whether you're doing the same thing twice in any of these loops.
It looks as if func1() is supposed to rotate an array. Have a look at System.arrayCopy() for moving whole chunks of array at a time. Most CPUs will do this in a single operation.
So I was working on this sorting algorithm in java, and was wondering if anybody has seen anything like this before. Specifically, this algorithm is meant to sort very large lists with a very small range of numbers. If you have seen that or have any suggestions to enhance the algorithm, can you say something about that below? I have the code here:
public static int[] sort(int[] nums)
{
int lowest = Integer.MAX_VALUE;
for (int n : nums)
{
if (n < lowest)
lowest = n;
}
int index = 0;
int down = 0;
while (index < nums.length)
{
for (int i = index; i < nums.length; i++)
{
if (nums[i] == lowest)
{
int temp = nums[i] + down;
nums[i] = nums[index];
nums[index] = temp;
index++;
}
else
nums[i]--;
}
down++;
}
return nums;
}
If I'm not mistaken, that is your standard-issue BubbleSort. It's simple to implement but has poor performance: O(n^2). Notice the two nested loops: as the size of the array increases, the runtime of the algorithm will increase exponentially.
It's named Bubble Sort because the smallest values will "bubble" to the front of the array, one at a time. You can read more about it on Wikipedia.
So the algorithm seems to work but it does a lot of unnecessary work in the process.
Basically you are throwing in the necessity to subtract from a number x times before you add x back and try and swap it where x is the difference between the number and the lowest number in the array. Take [99, 1] for example. With your algorithm you would update the array to [98, 1] in the first for loop iteration and then the next you would make the swap [1, 98] then you have to make 97 more iterations to bring your down variable up to 98 and your array to [1,1] state then you add 98 to it and swap it with itself. Its an interesting technique for sure but its not very efficient.
The best algorithm for any given job really depends on what you know about your data. Look into other sorting algorithms to get a feel for what they do and why they do it. Make sure that you walk through the algorithm you make and try to get rid of unnecessary steps.
To enhance the algorithm first I would get rid of finding the lowest in the set and remove the addition and subtraction steps. If you know that your numbers will all be integers in a given range look into bucket sorting otherwise you can try merge or quicksort algorithms.
So I'm working on this programming challenge online where I'm supposed to write a program that finds the missing term in an arithmetic progression. I solved the problem in two ways: one that used summing all the given terms of the progression and then subtracting that from the sum of the actual progression. My other solution was based on finding the difference of the progression, and then using that difference in a for loop to find the missing term. While my first solution successfully passes all test cases, my second solution fails two out of the 7 test cases. The challenge doesn't allow anyone to see their test cases so I had no idea what was wrong. Can anyone think of cases where my second solution fails to find the missing term of an arithmetic progression? Code for my second solution is below.
import java.io.*;
import java.util.Vector;
public class Solution {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int num = Integer.parseInt(br.readLine());
String[] numbers = br.readLine().split(" ");
Vector<Integer> ap = new Vector<Integer>();
for (String str: numbers){
ap.add(Integer.parseInt(str));
}
int first = ap.get(0);
int last = ap.get(ap.size()-1);
int incr = (last-first)/num;
for(int i = first; i<=last; i+= incr){
if(!ap.contains(i)){
System.out.println(i);
break;
}
}
}
}
Input Format The first line contains an Integer N, which is the number of terms which will be provided as input. This is followed by N consecutive Integers, with a space between each pair of integers. All of these are on one line, and they are in AP (other than the point where an integer is missing).
public class MissingAp
{
public static void main(String args[]){
int arr[] ={10,8,4,2,0,-2,-4,-6,-8,-10,-12};
int difference[]=new int[arr.length-1];
int missingTerm;
for(int i=1;i<arr.length;i++){
difference[i-1] = arr[i]-arr[i-1];
}
for(int j =0;j<arr.length-1;j++){
if(difference[j]!=difference[j+1]){
missingTerm = arr[j]+difference[j+1];
System.out.println("The missing term is: " + missingTerm );
break;
}}}}
This program will help you find missing term of an AP.
Wouldn't this fail if the sequence is decreasing instead of increasing?
If I had the numbers 10, 8, 4, 2, 0, the missing value would be 6.
You find increment of -10/5 = -2 properly.
But then the loop you start from i = 10, decrease by 2... as long asi <= 0. Well immediately i is > 0, so it'd exit the loop before decreasing at all. < only works if increasing.
So it's the i<=last statement that I think is the problem.
So you'd need seem kind of way to adjust the i<=last; statement based upon whether it is a positive or negative increment. I'm thinking it would have to do with absolute value and\or Math.signum, or including separate code section based upon a negative increment (not the fastest way, but reasonable). But I've never done much in Java, and you asked for how it failed. So hopefully there's your answer :-)
Sort the array to ensure that this works for any case.
Arrays.sort(input_array)
A JavaScript based solution for the same:
This has 2 cases:
CASE 1:
The array passed in has just one missing term, and the first and last
terms are not the missing ones. It definitely has a missing term.
In this case, we just need the array and use the basic school formula
sum of n terms = n/2 * (first + last)
function getMissingTerm(terms, n) {
var expectedSum = ((terms.length + 1)/2) * (terms[0] + terms[terms.length - 1]),
actualSum = 0;
for (var i = 0; i < terms.length; ++i) {
actualSum += parseInt(terms[i], 10);
}
return expectedSum - actualSum;
}
CASE 2:
The array passed does not have a missing term in itself
meaning the missing term is either the first or last term
In this case one must pass the length of the terms, n, which is greater than array length
function getMissingTerm(terms, n) {
var smallestDifference = Math.abs(terms[1] - terms[0]),
missingTerm = null;
for (var i = 2, diff; i < terms.length; ++i) {
diff = Math.abs(terms[i] - terms[i - 1]);
if (diff !== smallestDifference) {
missingTerm = diff < smallestDifference ? i : i + 1;
}
}
return (n && terms.length < n) ?
[terms[0] - smallestDifference, terms[n-2] + smallestDifference] : // return possible 2 terms, at the start and end of array
terms[0] + (missingTerm - 1) * smallestDifference; // return the missing term
}
pretty simple question:
Given an array, find all subsets which sum to value k
I am trying to do this in Java and seem to have found a solution which solves it in O(n^2) time. Is this solution a correct O(n^2) implementation?
#Test
public void testFindAllSubsets() {
int[] array = {4,6,1,6,2,1,7};
int k=7;
// here the algorithm starts
for(int i = 0; i < array.length;i++){
// now work backwords
int sum = array[i];
List<Integer> subset = new ArrayList<Integer>();
subset.add(array[i]);
for(int j = array.length -1; j > i && sum < k; j--){
int newSum = sum + array[j];
// if the sum is greater, than ditch this subset
if(newSum <= k){
subset.add(array[j]);
sum = newSum;
}
}
// we won't always find a subset, but if we do print it out
if(sum == k){
System.out.print("{");
System.out.print(subset.get(0));
for(int l = 1; l < subset.size(); l++){
System.out.print(","+subset.get(l));
}
System.out.print("}");
System.out.println();
}
}
}
I have tried it with various examples and have not found any that seem to break it. However, when I have searched online, this does not appear to be the common solution to the problem, and many solution claim this problem is O(2^n).
P.S.
This is not a homework question, I'm a brogrammer with a job trying to work on my Comp Sci fundamentals in Java. Thanks!
No this is not correct.Take this simple example
Your array is 4,6,1,2,3,1 and target sum is 7 then in your logic it
would only find (4,3) (6,1) (1,2,3,1) your code would miss (4,2,1), (4,3).
I would refer to go through wiki
An elegant solution is to simply think of a subset as each member answering the question "Am I in or not?" So essentially each can answer yes/no, so you have 2N subsets(including the empty subset). The most natural way to code this up is to recurse through each element and do one of the following:
Pick it
Skip it
Thus the time complexity is O(2N) simply because you have so many answers possible in the worst case.