Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
Just checking that this shuffling algorithm is suitable. Or maybe there could be improvements?
public static void shuffleArray(Object[] arr, Random rnd){
int lastIndex = arr.length - 1;
for (int i=0; i<=lastIndex; i++){
int k = rnd.nextInt(lastIndex+1);
Object a = arr[i];
Object b = arr[k];
arr[i] = b;
arr[k] = a;
}
}
Your random number should be chosen in the range i..lastIndex+1 rather than the range 0..lastIndex+1. Google for Fisher-Yates shuffle for an explanation.
You could also save one assignment during the swap by copying directly from one array location to the other without an intermediary: x = arr[i], arr[i] = arr[k], arr[k] = x.
If by suitable you are saying uniformly distributed, then no, it is not. Considering the fact that for each iteration, with each of the possible configurations, you generate N possible next configurations with equal probability. In the end, you have N ^ N equal possibilities, while there's just N! permutations, and the former in the normal case cannot be divided by the latter, thus impossible to be uniformly distributed.
In fact, I think Jeff Attwood has a explanation here:
Coding Horror - The danger of naivete
I need this to shuffle an array of char(s)
You can adapt the shuffle code like this for primitives
public static void shuffle(char[] chars, Random rnd) {
int size = chars.length;
for (int i = size; i > 1; i--) {
int idx = rnd.nextInt(i);
char tmp = chars[idx];
chars[idx] = chars[i-1];
chars[i-1] = tmp;
}
}
You could just do
Collections.shuffle(Arrays.asList(array), random);
Or you could look at this code. It is slightly more efficient to use one temporary variable and reduce the size of the random as you go. See Collections.shuffle for how to do this.
public static void shuffle(List<?> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
public static void swap(List<?> list, int i, int j) {
final List l = list;
l.set(i, l.set(j, l.get(i)));
}
Note: you are doing (lastIndex+1) but lastIndex is arr.length - 1 so really this is just arr.length
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Kindly help me with the underlying program as I am stuck. I'm a newbie programmer.
import java.util.*;
public class Source
{
static int maxProduct(int arr[]) {
int n = arr.length ;
if (n < 2)
{
System.out.println("NA");
return Integer.MIN_VALUE;
}
int a = arr[0];
int b = arr[1];
for(int i = 0; i<n; i++) {
for (int j = i+1; j<n; j++) {
if (arr[i]*arr[j] > arr[0]*arr[1]) {
a = arr[i];
b = arr[j];
}
}
}
return maxProduct;
}
}
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
int size = s.nextInt();
int[] arr = new int[size];
for(int i = 0; i < size; i++) {
arr[i] = s.nextInt();
}
int answer = maxProduct(arr);
System.out.print(answer);
}
}
You should change
if (arr[i]*arr[j] > arr[0]*arr[1])
to
if (arr[i]*arr[j] > a * b)
Since arr[0]*arr[1] is just the original max product, so you shouldn't be comparing against it.
Also note that your solution is not as efficient as it can be, since you are using a nested loop, which requires O(n^2) running time.
You can achieve linear (O(n)) running time if you use the fact that the max product is either the product of the two highest positive values or the product of the two lowest negative values. This means that if you find these 4 numbers, which can be done with a single loop, you'll find the max product.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I was trying to attempt a insertion algorithm question. However, I had the following question.
I wanted to nderstand why most solutions online use a nested while loop instead of a nested for loop? I thought it might have to do something with time complexity, however, both have a O(n^2) complexity.
Below I have attached the two different solutions
public class InsertionSort {
// MY method
/*Function to sort array using insertion sort*/
// void sort(int arr[])
// {
// int n = arr.length;
// for (int i = 1; i < n; ++i) {
// if(arr[i] < arr[i-1]){
// for(int j = 0; j < i; j++){
// if(arr[i] < arr[j]){
// int temp = arr[j];
// arr[j] = arr[i];
// arr[i] = temp;
// }
// }
// }
// }
// }
// Online Solution
void sort(int arr[])
{
int n = arr.length;
for (int i = 1; i < n; ++i) {
int key = arr[i];
int j = i - 1;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
Usually, when developing algorithms, you choose a loop based on this:
If the number of iterations is known, use a for-loop.
If the number of iterations is not known, use a while-loop.
In Java, and other languages, you can implement the same thing using both loops. It doesn't matter if the number of iterations is known. However, it makes sense, it's more readable/logical:
... for a known starting value to a known limit do ...
... while a condition is true do ...
In pseudocode, which is a way to describe an algorithm independently of implementation-details, it's often done just like that (or similar):
for i = 0 to n do
...
while condition do
...
When you look at sort, you can see two loops: the outer for-loop and the inner while-loop.
The outer loop is a for-loop because i and n are known. Value n is known because it's given by the size of the array, which is a constant in this algorithm.
The inner loop is a while-loop because it's not known when the condition will fail, as it depends on an array-access. You don't know the values; if you would, then you could sort the array by hardcoding some swaps.
I am currently trying to make a Quicksort in java. The only problem is that I just can't make it stable (so that the order of reccurring elements is still the same). My code so far:
Update: Thank you for all your answers but sadly I 'm not allowed to use any libraries like java.util for LinkedLists etc.
public void quickSortStable(Integer[] data) {
int IndexZero = 0;
int IndexLength = data.length-1;
sortQuicksortArray(data, IndexZero, IndexLength);
}
public int createQuicksortPartition(Integer[] data, int IndexZero, int IndexLength){
int pivot = data[IndexLength];
int i = (IndexZero-1);
for (int j=IndexZero; j<IndexLength; j++)
{
if (data[j] < pivot)
{
i++;
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
int temp = data[i+1];
data[i+1] = data[IndexLength];
data[IndexLength] = temp;
return i+1;
}
public void sortQuicksortArray(Integer[] data, int IndexZero, int IndexLength){
if (IndexZero < IndexLength)
{
int partition = createQuicksortPartition(data, IndexZero, IndexLength);
sortQuicksortArray(data, IndexZero, partition-1);
sortQuicksortArray(data, partition+1, IndexLength);
}
}
The quicksort algorithm is not stable by nature.
There are already some good answers on quora.
In short, each partition is not stable, because quick sort may swap the outer elements before the middle elements.
for example,
// original
4(a) 4(b) 3 2(a) 2(b)
^ ^
// after first partition
2(b) 4(b) 3 2(a) 4(a)
^ ^
// after second partition
2(b) 2(a) 3 4(b) 4(a)
Since the partition is not stable, the overall algorithm cannot be stable.
You can make the quicksort sorting stable when you save the elements which are smaller or bigger than the pivot in two temporary lists (or one array) and add them back to the original input array when you have separated the values. The pseudo algorithm looks like this:
public int createQuicksortPartition(Integer[] data, int startIndex, int endIndex){
List<Integer> lower = new ArrayList<Integer>();
List<Integer> higher = new ArrayList<Integer>();
Integer pivot = data[endIndex];
for (int i=startIndex; i<endIndex; i++) {
if (data[i] < pivot) {
lower.add(data[i]);
} else {
higher.add(data[i]);
}
// readd them to the input array
for (int i=0; i<lower.size(); i++) {
data[startIndex+i] = lower.get(i);
}
data[startIndex+lower.size()] = pivot;
for (int i=0; i<higher.size(); i++) {
data[startIndex+lower.size()+i] = higher.get(i);
}
return startIndex+lower.size();
}
(untested pseudo code)
This obviously need O(n) additional space to have a copy of the data to sort. You also have to take extra care for the pivot element and the "higher" elements, which are equal to that pivot. These have to added before the pivot element to ensure that the sorting is stable, because the pivot element was the last element from the input array. In this case the ordering should be:
Elements smaller than the pivot
Elements equal the pivot
The pivot itself
Elements greater than the pivot
You can solve this by using three lists for smaller, equal and greater values and add them back to the input array accordingly.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Assume we have a list of integers, for example:
L = [13,13,4,13,4,2]
I want to find the set of all palindromes, where each palindrome is a sub-list of L containing contiguous integers. For the above list that would be:
S = {[13], [4], [2], [13,13], [13,4,13], [4,13,4]}
Because the inverse of L would be L' = [2,4,13,4,13,13], and every element of S appears in L' in the correct order.
How can I find the set of all palindromes in general? My naive approach would be to check if each element of the power set of L appears in L', but this is inefficient and I am sure that there is a better solution.
I think my solution is pretty similar to solution from MC Emperor, but I focused on not creating temporary objects like lists.
I select sub-arrays of given array using left and right indices and check it for palindrome.
public static Set<List<Integer>> findAllPalindromes(int[] arr) {
Set<List<Integer>> res = new LinkedHashSet<>();
for (int length = 1; length < arr.length; length++)
for (int left = 0, right = left + length - 1; right < arr.length; left++, right++)
if (isPalindrome(arr, left, right))
res.add(sublist(arr, left, right));
return res;
}
This method check is given sub-array palindrome or not:
private static boolean isPalindrome(int[] arr, int left, int right) {
for (; left < right; left++, right--)
if (arr[left] != arr[right])
return false;
return true;
}
This method create separate list for given sub-array:
private static List<Integer> sublist(int[] arr, int left, int right) {
List<Integer> res = new ArrayList<>(right - left);
for (; left <= right; left++)
res.add(arr[left]);
return res;
}
You need two steps to do that.
First, you'll need to find all sublists within the list:
List<Integer> input = Arrays.asList(13, 13, 4, 13, 4, 2);
List<List<Integer>> subLists = new ArrayList<>();
for (int subListSize = 1; subListSize < input.size(); subListSize++) {
for (int startIndex = 0; startIndex < input.size() - subListSize + 1; startIndex++) {
List<Integer> subList = input.subList(startIndex, startIndex + subListSize);
subLists.add(subList);
}
}
// Also test the whole list:
subLists.add(input);
Then you need to check for each element if the list is a palindrome. To test if a list is a palindrome, element n must be compared to element listSize - 1 - n.
We only need to check half of the elements.
static boolean isPalindrome(List<Integer> subList) {
for (int i = 0; i < subList.size() / 2; i++) {
if (!Objects.equals(subList.get(i), subList.get(subList.size() - 1 - i))) {
return false;
}
}
return true;
}
If you want to remove duplicates, then you can put the elements into a Set.
This question already has answers here:
sorting integers in order lowest to highest java
(7 answers)
Closed 8 years ago.
I have been looking for a while for a way to sort an arraylist without using collections.sort as my own logic is flawed and I have been having a lot of trouble.
I need to sort it in a way that I can use a method I created that basically does what collections.swap does in order to completely sort an arraylist.
Here is my code:
public static void mySort(ArrayList<Double> sort){
int min = 0;
int i;
int j = 0;
for(i = 0; i < sort.size() - 1; i++) {
min = i;
mySwap(sort, j ,min);
for(j = 0; j < sort.size() -1;j++){
if(j < min ){
min = j;
}
}
}
}
public static void mySwap(ArrayList<Double> a, int x, int y){
double temp = a.get(x);
a.set(x,a.get(y));
a.set(y,temp);
}
I have been having a lot of trouble of with this. Sorry if it is a question is that harming the community.
I assume you want the following algorithm: find min in the rest of the array, swap it with current element starting with first, reconsider rest to be array starting of increased +1 index.
You should update your code like this:
public static void swap(List<Integer> sort, int i, int j) {
int tmp = sort.get(i);
sort.set(i, sort.get(j));
sort.set(j, tmp);
}
public static void doSort(List<Integer> sort) {
int min;
for (int i = 0; i < sort.size(); ++i) {
//find minimum in the rest of array
min = i;
for (int j = i + 1; j < sort.size(); ++j) {
if (sort.get(j) < sort.get(min)) {
min = j;
}
}
//do swap
swap(sort, i, min);
}
}
You have a bug with finding minimum and then swapping items. Please note that the code can be improved in many ways (I tried to maintain your let's say way of coding as possible), such as swapping integer references in swap(), doing BubbleSort like another answer suggests (same algorithm but simpler implementation), using O(n * log(n)) complexity algorithm, and so on.