I just started with java and while was doing an exercise about permutations (the exercise asked to create a permutation of N elements using an array a[] meeting the requirement that no a[i] is equal to i.) I've created the following code. While testing it, I realized that it entered in a infinite loop sometimes when N = 6 specifically.
Any thoughts on where is the problem?
public class GoodPerm {
public static void main(String arg[]) {
int n = Integer.parseInt(arg[0]);
int[] guests = new int[n];
for (int i = 0; i < n; i++) {
guests[i] = i;
}
for (int i = 0; i < n; i++) {
int r = i + (int) (Math.random() * (n - i));
int q = guests[r];
guests[r] = guests[i];
guests[i] = q;
if(guests[i] == i){
i --;
}
}
for(int q : guests){
System.out.println(q);
}
}
}
Maybe the code enters in a inf-loop in another values, but I didn't found any others.
This code can always enter an inf-loop. As I understand the code, you try to do some random switches to achieve your needed result. But if the last element of your array has never been switched, it won't be possible to switch it to any "later/higher" position (because there are no more). In the "last" iteration of your second for-loop (so i + 1 == n holds at the beginning) r will always evaluate to i thus no real switch happens. If the last element is still in place, you gonna repeat this forever.
Related
I have an atomic integer array of size 10. I am using this array to organize numbers 1-10 sent in by threads. This 1-10 will eventually be able to change to be a range of numbers larger than 10 and the list is to contain the 10 greatest numbers in that range. I can see the numbers going into the loops and recognizing that they are greater than a number currently there. However, there is never more than 2 numbers in the array when it is printed out. I have tried to trace my code in debug mode, however, it looks as if it is working as intended to me. I feel like there may be a simple error to my logic? I am completely sure all values are entering in the function as I have triple checked this. I start at the end of the array which should contain the highest value and then swap downwards once the slot has been determined. I would appreciate the assistance. This is just a simple experiment I am doing in order to grasp the basics before I try to tackle a homework assignment.
Here an example of my code:
public class testing{
static AtomicIntegerArray maxList = new AtomicIntegerArray(10);
final static int n = 10;
static void setMax(int value)
{
for(int i = 9; i >= 0; i--)
{
if(value > maxList.get(i))
{
int temp = maxList.get(i);
maxList.set(i,value);
if(i == 0)
{
maxList.set(i, value);
}
else
{ for(int j = i-1; j > 0; j--)
{
maxList.set(j, temp);
temp = maxList.get(j-1);
}
}
break;
}
}
public static void main(String[] args)
{
for (int i = 0; i < n; i++)
{
setMax(i);
}
}
}
Here is an example of how it is being called:
Brooke, there is a small bug in your 'j' loop. You had saved the state of a variable (temp), however your logic in the j loop lost the state. This new logic preserves the state of the previous element in the list.
Try this:
for (int j = i - 1; j >= 0; j--) {
int t2 = maxList.get(j);
maxList.set(j, temp);
temp = t2;
}
This problem is from https://www.hackerrank.com/ and link to it is https://www.hackerrank.com/challenges/java-list/problem .
In the below code while loop is running twice as according to question we need to enter Q, Q times an operation to perform in the Array Declared. For this, i am running twice the loop so that I can get the desired result.
import java.util.*;
public class javaList {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int i, x;
ArrayList L = new ArrayList(N);
for (i = 0; i < N; i++) {
L.add(sc.nextInt());
}
int Q = sc.nextInt();
i = 0;
// for normal running i have multiplied Q by 2 so that i can get the results
while (i < Q * 2) {
System.out.println("Loop: " + i);
String s = sc.nextLine();
int sz = L.size();
// code for checking insert
if (s.equals("Insert")) {
x = sc.nextInt();
int y = sc.nextInt();
//if the position i am looking exists then just replace
// i need to insert at index x of array L but array.size() gives one more than the last index
if ((sz - 1) >= x) {
L.add(x, y);
}
//if the position i am looking does not exist then create
else {
for (int j = sz; j <= x; j++) {
//add number to desired place
if (j == x)
L.add(y);
//in between the two endings of array and insertion adding default value 0
else
L.add(0);
}
}
//checking code for Delete
} else if (s.equals("Delete")) {
x = sc.nextInt();
//if the desired location exists then only replace
if ((sz - 1) >= x) {
L.remove(x);
}
}
i++;
}
for (i = 0; i < L.size(); i++) {
System.out.print(L.get(i) + " ");
}
}
}
I want to Know why the loop is running twice in a single run.
So, from discussion in the comments, you've stated that your question is:
if Q = 2 then it should ask operations Insert or Delete 4 times as of my code. But it asks only 2 times. Simply that is my problem
First, you may not fully understand your own program flow. Before the while loop, you need to enter three sets of values, a value for N, values for L, and a value for Q.
Once you enter your while loop, you will be prompted for a value for s (which it seems you intend to be either "Insert" or "Delete"). However, the first time around, it will get an empty string and s will be "\n". Why? Because for N, L, and Q, the user will enter values as follows:
[value] [ENTER]
The return key is itself a value. So, in the input buffer (assuming Q = 2), is "2\n". When your code runs to get s String s = sc.nextLine(); it will see the next line symbol and skip prompting user for input.
Because s is not "Insert" or "Delete", it will skip those the first time around. You will then be prompted to enter a value for "s" after the start next loop.
To help you realize what's going on, I suggest adding statements everywhere you ask users to enter a value, like System.out.println("Enter a value for Q:");
This will help you keep track of program flow.
Your code is waaay to complicated. Try this:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<Integer> list = new ArrayList<>();
for (int i = 0, n = scanner.nextInt(); i < n; i++) {
list.add(scanner.nextInt());
}
for (int i = 0, n = scanner.nextInt(); i < n; i++) {
if (scanner.next().equals("Insert")) {
list.add(scanner.nextInt(), scanner.nextInt());
} else {
list.remove(scanner.nextInt());
}
}
String result = list.stream()
.map(String::valueOf)
.collect(Collectors.joining(" "));
System.out.println(result);
}
I want to add numbers in sorted way before entering vector. But the result is not right and I am confused where the problem is ? Output is shown below.
I want to sort using some algorithm without any inbuilt methods.
import java.util.Vector;
public class Test {
public static void main(String ar[]){
//Numbers to enter in vector
int[] number = {5,2,98,3,10,1};
Vector<Integer> v = new Vector<Integer>();
v.add(number[0]);
for(int i=1;i<number.length;i++){
for(int j=v.size();j>0;j--){
System.out.println("Entered: "+number[i]);
if(number[i] <= v.get(j-1)){
v.add(j-1,number[i]);
break;
}else{
v.add(j,number[i]);
break;
}
}
}
for(int s:v)
System.out.print(s + " ");
}
}
OUTPUT:
Entered: 2
Entered: 98
Entered: 3
Entered: 10
Entered: 1
2 5 3 10 1 98
You have a second (inner) for loop based on the variable j, but that "loop" will only execute exactly one time. Both conditions inside the j loop cause the loop to exit (break;).
When you're adding each number, the only possibilities are last or next to last.
Your inner for loop doesn't actually loop.
Regardless of the condition number[i] <= v.get(j-1),
the loop will exit after one step.
What you want to do is,
iterate from the beginning of the vector,
and when you find an element that's bigger than the one you want to insert,
then insert it, and break out of the loop.
This is opposite of what you did so far, which is iterating from the end of the vector.
If the end of the loop is reached without inserting anything,
then append the value.
The program badly needs some other improvements too:
If you don't need the vector to be thread-safe, then you don't need Vector. Use ArrayList instead.
The special treatment for the first number is unnecessary.
The outer loop can be written in a more natural way using the for-each idiom.
No need to loop to print the elements, the toString implementation of Vector is already easy to read.
The variable names are very poor and can be easily improved.
The indentation is inconsistent, making the code very hard to read.
With the problem fixed and the suggestions applied:
List<Integer> list = new ArrayList<>();
for (int current : numbers) {
boolean inserted = false;
for (int j = 0; j < list.size(); j++) {
if (current <= list.get(j)) {
list.add(j, current);
inserted = true;
break;
}
}
if (!inserted) {
list.add(current);
}
}
System.out.println(list);
Last but not least, instead of searching for the insertion point by iterating over the list,
you could achieve much better performance using binary search,
especially for larger sets of values.
Another simple solution would be:
import java.util.Vector;
public class Test {
public static void main(String ar[]){
//Numbers to enter in vector
int[] number = {5,2,98,3,10,1};
Vector<Integer> v = new Vector<Integer>();
v.add(number[0]);
for(int i=1, j;i<number.length;i++){ //j declared here for better scope
for(j=v.size();j>0 && v.get(j-1)>number[i] ;j--); //<-- some changes here,
v.add(j,number[i]); //<-- and here
}
}
for(int s:v)
System.out.print(s + " ");
}
}
The inner for loop is simply used to find the right index for an element to be inserted.
Your inner loop seems to not looping more than one time. That's why the key is not being inserted into right place.
A more concise solution would be
public class Test {
public static void main(String ar[]){
//Numbers to enter in vector
int[] number = {5,2,98,3,10,1};
Vector<Integer> v = new Vector<Integer>();
v.setSize(number.length);
v[0] = number[0];
for(int i=1, vSize = 1; i < number.length; i++, vSize++){
int j = 0, k = 0;
for(j = 0; j < vSize; j++) {
if(v[j] < number[i]) {
break;
}
for(k = vSize; k > j; k--) {
v[k] = v[k -1];
}
v[k] = number[i];
}
for(int s:v)
System.out.print(s + " ");
}
}
I am required to take an array of size x (which contains numbers starting at x and then descending down to 1), and then, with a new array of size y (which may or may not be the same size as x), print out random numbers from array x into array y. I wrote the program and it runs fine, but for some reason in the list of random numbers outputted, the number 0 will show up. Does anybody know why this is happening? Here is my code:
import java.util.Random;
public class Prog1A
{
public static void main(String[] args)
{
System.out.println("Program 1A, Christopher Moussa, masc1574");
Random randGen = new Random();
int[] arr_1 = new int[8];
for (int i = arr_1.length - 1; i >= 0; i--)
{
arr_1[i] = arr_1[i];
}
int[] arr_2 = new int[6];
for (int i = 1; i <= arr_2.length; i++)
{
System.out.print(randGen.nextInt(arr_1.length) + " ");
}
}
}
Any feedback will be greatly appreciated, thank you.
Well you aren't doing anything with this loop. You're essentially assigning a variable to itself right throughout the array. Also, I dislike the way you wrote your loop condition, but my preference isn't the issue here.
for (int i = arr_1.length - 1; i >= 0; i--)
{
arr_1[i] = arr_1[i]; //This code does nothing
}
Then you create arr_2[] but you never assign anything to the variables.
I went ahead and edited your code, and I'll explain a few things.
import java.util.Random;
public class Prog1A
{
public static void main(String[] args)
{
Random randGen = new Random();
int[] arr_1 = new int[8];
int[] arr_2 = new int[6];
System.out.println("Program 1A, Christopher Moussa, masc1574");
//Assigns a random number to each member of arr_1
for (int i = 0; i < arr_1.length; ++i)
{
arr_1[i] = randGen.nextInt(arr_1.length);
}
//Copies arr_1 values to arr_2
for (int i = 0; i < arr_2.length; ++i) //Counting up [0 to 5]
{
arr_2[i] = arr_1[i];
}
for (int i = 0; i < arr_2.length; ++i)
{
System.out.print(arr_2[i] + " ");
}
}
}
Always (if possible) declare all variables at the start of a function/class/program. It keeps code a lot cleaner and helps you to identify possible errors that may occur.
Keep your loop parameters consistent. Start from 0 and go up always, or start from the last value and go down. It eliminates the possibility of an error again. I prefer starting from 0 always but it is up to you, as long as it is clean and it works.
Unless you initialize an array, it is going to be empty. If you try to print from it you'll most likely see zeros.
Just add one to your result, The length of your array is 8. With your current code your are returning a random number between 0 and 7. The nextInt method will never return the upper limit of the integer value supplied. You can test this out yourself by exchanging the arr_1.length for a different number like 10 for example and then remove the + 1. You will notice that it will only return the number 9 at the most and 0 will be the lowest number returned.
System.out.print((randGen.nextInt(arr_1.length) + 1) + " ");
Problem
Given a string s and m queries. For each query delete the K-th occurrence of a character x.
For example:
abcdbcaab
5
2 a
1 c
1 d
3 b
2 a
Ans abbc
My approach
I am using BIT tree for update operation.
Code:
for (int i = 0; i < ss.length(); i++) {
char cc = ss.charAt(i);
freq[cc-97] += 1;
if (max < freq[cc-97]) max = freq[cc-97];
dp[cc-97][freq[cc-97]] = i; // Counting the Frequency
}
BIT = new int[27][ss.length()+1];
int[] ans = new int[ss.length()];
int q = in.nextInt();
for (int i = 0; i < q; i++) {
int rmv = in.nextInt();
char c = in.next().charAt(0);
int rr = rmv + value(rmv, BIT[c-97]); // Calculating the original Index Value
ans[dp[c-97][rr]] = Integer.MAX_VALUE;
update(rmv, 1, BIT[c-97], max); // Updating it
}
for (int i = 0; i < ss.length(); i++) {
if (ans[i] != Integer.MAX_VALUE) System.out.print(ss.charAt(i));
}
Time Complexity is O(M log N) where N is length of string ss.
Question
My solution gives me Time Limit Exceeded Error. How can I improve it?
public static void update(int i , int value , int[] arr , int xx){
while(i <= xx){
arr[i ]+= value;
i += (i&-i);
}
}
public static int value(int i , int[] arr){
int ans = 0;
while(i > 0){
ans += arr[i];
i -= (i &- i);
}
return ans ;
}
There are key operations not shown, and odds are that one of them (quite likely the update method) has a different cost than you think. Furthermore your stated complexity is guaranteed to be wrong because at some point you have to scan the string which is at minimum O(N).
But anyways the obviously right strategy here is to go through the queries, separate them by character, and then go through the queries in reverse order to figure out the initial positions of the characters to be suppressed. Then run through the string once, emitting characters only when it fits. This solution, if implemented well, should be doable in O(N + M log(M)).
The challenge is how to represent the deletions efficiently. I'm thinking of some sort of tree of relative offsets so that if you find that the first deletion was 3 a you can efficiently insert it into your tree and move every later deletion after that one. This is where the log(M) bit will be.