Insert number into ordered arrayList - java

I have an interesting problem on how to insert any number into an ordered ArrayList. Lets say the user enters [12,34,37,60,89]; the method addListElement() should traverse the array to find the index where the new element will go.
The user enters the number 50, the new array should be [12,34,37,50,60,89]. I used a for loop to traverse the ArrayList, but I'm not sure about my if() statement.
public void addListElement() {
System.out.println("Add number to arrayList");
Scanner scan = new Scanner(System.in);
int number = scan.nextInt();
int loc = 0;
for (int i = 0; i < aryList.size(); i++) {
if (number > 0 && i < loc) {
loc++;
}
}
aryList.add(loc, number);
System.out.println(aryList.toString());
}

Try this:
int position = Collections.binarySearch(aryList, number);
aryList.add(position < 0 ? -position - 1 : position, number);
Edit thanks for pointing out the old code crashes if the number is already present

You would want to make use of the List<E>.add(int idx, E element) method. The idea behind inserting the element in order is that, for some array a, element ai, and for some integer n:
ai <= n <= ai+1 , 0 < i < len(a)-1.
// edge case: Size one list, number coming in is smaller.
if(aryList.size() == 1 && aryList.get(0) >= number) {
aryList.add(0, number);
} else {
for(int i = 0; i < aryList.size()-1; i++) {
if(number >= aryList.get(i) && number <= aryList.get(i+1)) {
aryList.add(i, number);
}
}
// number is the largest seen; add it to the end.
aryList.add(number);
}

this should work too. Since the list is already in ascending order, when ever you find the number in list bigger than the current one, insert the new number one index before this number in arrayList..
for (int i = 0; i < aryList.size(); i++) {
if (aryList.get(i)>number) {
break;
}
loc++;
}

Increment the index as long as there are more elements and the number is less than the current element. You will also have to check that i != list.size() when finished for cases when the user gives a number that is larger than any number currently in the list.
while (number >= 0 && number <= list.get(i) && i < list.size()) {
i++;
}
list.add(i, number);

int loc = 0;
int prevNumber = aryList.get(0);
for(int i = 1; i<aryList.size(); i++){
if(number > prevNumber && number <= aryList.get(i)){
return i;
}
prevNumber = aryList.get(i);
}

I suppose your Elements are ordered by an ascendant order
public void insert(int x){
// loop through all elements
for (int i = 0; i < arrayList.size(); i++) {
// if the element you are looking at is smaller than x,
// go to the next element
if (arrayList.get(i) < x) continue;
// if the element equals x, return, because we don't add duplicates
if (arrayList.get(i) == x) return;
// otherwise, we have found the location to add x
arrayList.add(i, x);
return;
}
// we looked through all of the elements, and they were all
// smaller than x, so we add x to the end of the list
arrayList.add(x);
}
If you want to insert duplicates in your ArrayList just remove the line of code
if (arrayList.get(i) == x) return;

Related

Given two sorted lists (or arrays) and a number k, create an algorithm to fetch the least k numbers of the two lists

Need to find the first 3 smallest number in given two sorted array. I supposed that two array should merge into one first and sort it in order to fetch the first 3 smallest number. Can anyone help me with the merge and sort part or provide some advice, any help will appreciate.
This is where i reached now, I only can get the smallest number ( not first 3, just one).
public class MergeandSort {
public static void main(String[] args) {
int[] set1 = {1,2,6,9,18};
int[] set2 = {2,3,7,10,21,30};
int smallest = set1[0];
int smallests = set2[0];
for(int i=0; i < set1.length; i++){
if(set1[i] < smallest)
smallest = set1[i];
}
for(int k=0; k < set2.length; k++){
if(set2[k] < smallests)
smallests = set2[k];
}
System.out.println("Smallest Number in Set 1 is : " + smallest);
System.out.println("Smallest Number in Set 2 is : " + smallests);
}
}
The arrays are already sorted, so you don't have to iterate over the entire arrays to find the 3 smallest numbers.
You just have to start iterating over both arrays at the same time (i.e. in the same loop).
In each iteration you compare the current two elements of the two arrays (starting at the 2 elements at the 0 index) and take the smaller of them
Then you advance the index of the array from which you took the smallest number.
Once you reach 3 elements (after 3 iterations), you break out of the loop.
Here's some pseudo code to get you started:
int i = 0;
int j = 0;
int c = 0;
int[] lowest3 = new int[3];
while (true) {
find the smaller of set1[i] and set2[j] and put it in lowest3[c]
if set1[i] is smaller, increment i
otherwise increment j
increment c
if (c==3) // you are done
break;
}
the lowest3 array now contains the 3 lowest numbers of both arrays
Of course you can swap 3 with any k. You just have to make sure that i is always smaller than set1.length and j is always smaller than set2.length.
If the arrays are already sorted, just implement the merging technique of merge sort with the limitation in while condition that it should run only k times (in this case 3), but dont forget to check that size of sets are less than k or not!
int k = 0,i = 0,j = 0;
while (k<3 && k<set1.length && k<set2.length )
{
if (set1[i] <= set2[j])
{
final_set[k] = set1[i];
i++;
}
else
{
final_set[k] = set2[j];
j++;
}
k++;
}
while (k<3 && k<set1.length) {
final_set[k]=set1[i];
k++;
i++;
}
while (k<3 && k<set2.length) {
final_set[k]=set1[j];
k++;
j++;
}
public class MergeandSort {
public static void main(String[] args) {
int[] set1 = {1,2,6,9,18};
int[] set2 = {2,3,7,10,21,30};
int[] sorted = new int[k];
int smallest = set1[0];
int smallests = set2[0];
int i = 0, j = 0, c = 0;
while(i < set1.length && j < set2.length && c < k){
if (set1[i] < set2[j])
sorted[c++] = arr1[i++];
else
sorted[c++] = arr2[j++];
while (i < set1.length && c < k)
sorted[c++] = arr1[i++];
while (j < set2.length && c < k)
sorted[c++] = arr2[j++];
System.out.println(sorted);
}
}
where k is the count of sorted numbers you want
That would not work as:
Array1 = {1,3,5}
Array2 = {2,3,4}
Correct solution: {1,2,3}
Output of your solution: {1,3,4}

I want to find the 10 first Amicable Pair with only use of arrays, loops and conditions but I'm very new to java and programming in general

I think I know how to enter the sum of division into cell on the array but stuck on how to compare between the arrays and print the 10 pairs.
My code so far:
public static void main(String[] args) {
int sum1=0,sum2=0;
int[] arr1=new int[67000];
int[] arr2=new int[67000];
for(int i =0;i<=10;i++){
for(int j =1;j<arr1.length;j++){
for(int k =0;k<j;k++){
if(j%k==0){
sum1+=k;
}
}arr1[j]=sum1;
}
for(int j =1;j<arr2.length;j++){
for(int k =0;k<j;k++){
if(j%k==0){
sum2+=k;
}
}arr2[j]=sum2;
}
}
}
You are calculating the same values in both the arrays. Just create the array once.
for (int j = 2; j < arr.length; j++) {
int sum = 0;
for (int k = 1; k < j; k++) {
if (j % k == 0) {
sum += k;
}
}
arr[j] = sum;
}
Now, here, arr[n] is the sum of the proper divisors of a number n.
We can compare the pairs by looping through arr as:
int cnt = 0, first = 2;
while(cnt < 10) {
int second = arr[first];
if (second >= arr.length) {
continue;
}
if (second > first) {
if (first == arr[second]) {
System.out.printf("%d %d\n", first, second);
cnt++;
}
}
first++;
if (first >= arr.length) {
break;
}
}
The first check is to avoid overrunning the array index, the second > first check is to make sure we only look forward and not rediscover a pair twice.
And then the main check is first == arr[second] which is what amicable numbers are. What it's saying is that if the sum of divisors of the second number which in fact is the sum of divisors of the first number is the first number itself, then the numbers are amicable pairs.
Side Note:
The program could probably be written in other better ways.
For example when finding the sum, looping up to the square root of the number in question is enough as the divisors mirror each other.

I am stuck on figuring out how to end the recursion loops as soon as the list number(s) is found

I am writing a program that, using an array list of given integers (listOfNumbers), will find if any combination of sums of these numbers will add up to another given integer (CompareTo). This program uses recursion. I am stuck on figuring out how to end the recursion loops as soon as the list number(s) is found. Thanks.
int sum = 0;
for(int i = listOfNumbers.size() - 1; i > -1; i--)
{
int backup = listOfNumbers.get(i);
listOfNumbers.remove(i);
for(int k = 0; k < listOfNumbers.size(); k ++)
{
sum += listOfNumbers.get(k);
}
if(sum == compareTo)
{
//IF THIS IS TRUE KILL ALL RECURSION
return listOfNumbers;
}
sum = 0;
answer(listOfNumbers, compareTo); //CREATE NEW RECURSION LOOP
listOfNumbers.add(i, backup);
}
//IF NO COMBINATION OF ARRAY LIST NUMBERS WILL
//ADD TO = COMPARETO, RETURN ORIGINAL LIST
return listOfNumbers;
Try to compare first, and then add or remove numbers in the list. If you remove numbers before the recursive call, in subsequent returns the condition isn't meet.
int sum = 0;
for(int i = listOfNumbers.size() - 1; i > -1; i--)
{
if(sum == compareTo)
{
//IF THIS IS TRUE KILL ALL RECURSION
return listOfNumbers;
}
else
{
int backup = listOfNumbers.get(i);
listOfNumbers.remove(i);
for(int k = 0; k < listOfNumbers.size(); k ++)
{
sum += listOfNumbers.get(k);
}
sum = 0;
answer(listOfNumbers, compareTo); //CREATE NEW RECURSION LOOP
listOfNumbers.add(i, backup);
}
}
//IF NO COMBINATION OF ARRAY LIST NUMBERS WILL
//ADD TO = COMPARETO, RETURN ORIGINAL LIST
return listOfNumbers;
In fact, I would put the obvious case (sum == compareTo) in the very top of everything, and then do the rest of the stuff.
for(int k = 0; k < listOfNumbers.size(); k ++)
{
sum += listOfNumbers.get(k);
}
if(sum == compareTo)
{
//IF THIS IS TRUE KILL ALL RECURSION
return listOfNumbers;
}
// DO THE REST OF OPERATIONS HERE....

how to find the sum of two elements in an array closest to zero

How to find two elements from an array whose sum is closest to zero but not zero(note: -1 is closest to zero than +2).I tried this...
int a[]=new int[n];
int b[]=new int[2];
int prev=0;
for(int i=0;i<n;a[i++]=in.nextInt());
for(int i=0;i<a.length;i++){
for(int j=i+1;j<a.length;j++){
int sum=a[i]+a[j];
if(prev==0)
prev=sum;
if(sum > 0){
if(sum < prev ){
prev=sum;
b[0]=a[i];
b[1]=a[j];
}
}
else if(sum < 0){
if(-sum < prev){
prev=sum;
b[0]=a[i];
b[1]=a[j];
}
}
}
}
Sop(b[0]+" "+b[1]);
I have a few remarks, you are using 3 for loops, which can be improved to just 2 nested for loops (the outer loop for selecting the current element and the inner loop to compare with the other elements).
Also you have multiple if tests to check if the sum is now closer to zero then the previous sum. However these if tests can be reduced to just one if test, by taking the absolute value of the sum instead of testing on sum > 0 and sum < 0, which is fine for the readability.
This is what i came up with :
int array[] = new int[5];
array[0] = -3; array[1] = -2; array[2] = -1; array[3] = 1; array[4] = 2; // Fill array
int idx[] = new int[2]; // Will store the result (index of the two elements that need to be added)
double lowest_sum = Double.POSITIVE_INFINITY; // Of type double to be able to use infinity
for(int i = 0; i < array.length; i++) {
// Outer loop --> Uses a current (array[i]) from left to right
int current = array[i];
for(int j = i+1; j < array.length; j++) {
// Inner loop --> Check all elements we didn't used as current till now
int compare_with = array[j];
if((Math.abs(current + compare_with) < lowest_sum) && ((current + compare_with) != 0)) {
// We found two elements whose sum is closer to zero
lowest_sum = Math.abs(current + compare_with);
idx[0] = i; // Index of the first element to add
idx[1] = j; // Index of second element to add
}
}
}
int res_idx1 = idx[0];
int res_idx2 = idx[1];
System.out.println("The first element to add is : " + array[res_idx1] + "\nThe second element to add is : " + array[res_idx2]);
Input : array = [-3, -2, -1, 1, 2] , Output : The first element to add is : -3,
The second element to add is : 2
Note that this code will print a solution and not all solutions (if multiple solutions exists). It should be fairly trivial to edit the code such that it returns all solutions.
you can try:
int a[]=new int[n];
int b[]=new int[2];
int prev=0;
for(int i=0;i<n;a[i++]=in.nextInt());
for(int i=0;i<a.length;i++){
for(int j=i+1;j<a.length;j++){
int sum=a[i]+a[j];
if(prev==0)
prev=sum;
if(Math.abs(sum)>0 && Math.abs(sum)<Math.abs(prev)){
prev=sum;
b[0]=a[i];
b[1]=a[j];
}
}
}
Sop(b[0]+" "+b[1]);
This problem can be solved in O(N*log(N)). The most expensive operation in this case will be sorting your array. If your domain allows you to use non-comparative sorts, such as counting sort then you'll be able to reduce time complexity of the whole solution to linear time.
The idea is that in sorted array, you can iterate elements in ascending and descending order in parallel and thus find all pairs with minimal/maximal sum in linear time. The only disadvantage of such approach in application to your task is that you need to find minimal absolute value of the sum, that means finding minimum among positive sums and maximum among negative sums. This will require two linear passes.
My solution is below. It is verified on randomized data against the bruteforce O(N^2) solution.
// note: mutates argument!
static Solution solve(int a[]) {
Arrays.sort(a);
int i = 0;
int j = a.length - 1;
// -1 indicates uninitialized min value
int minI = -1;
int minJ = -1;
int min = 0;
// finding maximal sum among negative sums
while (i < j) {
int cur = a[i] + a[j];
if (cur != 0 && (minI == -1 || Math.abs(cur) < Math.abs(min))) {
min = cur;
minI = i;
minJ = j;
}
// if current sum is below zero, increase it
// by trying the next, larger element
if (cur < 0) {
i++;
} else { // sum is already non-negative, move to the next element
j --;
}
}
i = 0;
j = a.length - 1;
// finding minimal sum among positive sums
while (i < j) {
int cur = a[i] + a[j];
if (cur != 0 && (minI == -1 || Math.abs(cur) < Math.abs(min))) {
min = cur;
minI = i;
minJ = j;
}
if (cur > 0) {
j--;
} else {
i ++;
}
}
if (minI >=0) {
return new Solution(minI, minJ, min);
//System.out.printf("a[%d]=%d, a[%d]=%d, sum=%d", minI, minJ, a[minI], a[minJ], min);
} else {
return null;
//System.out.println("No solution");
}
}
I just realized that sorting messes the indices, so minI and minJ will not correspond to the indices in the original non-sorted array. The fix is simple — original array should be converted to the array of pairs (value, original_index) before sort. Though I will not implement this fix in my example snippet, as it will further affect readability.

Sudoku Checker 2d array Java

So im having a bit of problem with my code.. It's suppose to cross check rows and columns for same integers.
this is what i have so far.. but when i run it, it only seems to check the first integer only. (for example the first line of the sudoku board reads. 1 2 2 2 2 2 2 2 2 2) it wont detect the obvious multiple 2's but if i change the input to 1 1 2 2 2 2 2 2 2 the error will come up of multiple 1's in this case. the multiple any suggestions to tweak my loops to make it go through the columns?
public static void validate(final int[][] sudokuBoard) {
int width = sudokuBoard[0].length;
int depth = sudokuBoard.length;
for (int i = 0; i < width; i++) {
int j = i;
int reference = sudokuBoard[i][j];
while (true) {
if ((j >= width) || (j >= depth)) {
break;
}
else if (i == j){
// do nothing
}
else if (j < width) {
int current = sudokuBoard[i][j];
if (current == reference) {
System.out.print("Invalid entry found (width)" + "\n");
System.out.print(current + "\n");
// invalid entry found do something
}
} else if (j < depth) {
// note reversed indexes
int current = sudokuBoard[j][i];
if (current == reference) {
System.out.print("Invalid entry found (depth)" + "\n");
System.out.print(current + "\n");
// invalid entry found do something
}
}
j++;
}
Your code is more complex than it should be. Why put everything in one single function when you could split in several different functions?
public static void Validate(final int[][] sudokuBoard)
{
int width = sudokuBoard[0].length;
int depth = sudokuBoard.length;
for(int i = 0; i < width; i++)
if(!IsValidRow(sudokuBoard, i, width))
{
//Do something - The row has repetitions
}
for(int j = 0; j < height; j++)
if(!IsValidColumn(sudokuBoard, j, width))
{
//Do something - The columns has repetitions
}
}
static bool IsValidRow(int[][] sudokuBoard, int referenceRow, int width)
{
//Compare each value in the row to each other
for(int i = 0; i < width; i++)
{
for(int j = i + 1; j < width; j++)
{
if(sudokuBoard[referenceRow][i] == sudokuBoard[referenceRow][j])
return false
}
}
return true;
}
static bool IsValidColumn(int[][] sudokuBoard, int referenceColumn, int height)
{
//Compare each value in the column to each other
for(int i = 0; i < height; i++)
{
for(int j = i + 1; j < height; j++)
{
if(sudokuBoard[i][referenceColumn] == sudokuBoard[j][referenceColumn])
return false
}
}
return true;
}
That way, your code is much more easily maintainable/readable. This code above hasn't been tested, but it should be about right.
I suggest debugging this code step by step to really understand what's going on, if that's not clear for you.
Given the constraints of sudoku (a row of n cells must contain the numbers 1-n only) you don't need an order n^2 search (per row or column), you can do it order n by keeping a bit array indicating which numbers you've seen. Here's the pseudo-code for checking rows, do the same for columns:
for i in 0 to depth-1 // rows
boolean seen[] = new seen[width];
for j in 0 to width-1 // columns
if seen[board[i][j]-1] == true
duplicate number
else
seen[board[i][j]-1] = true
I would break the functionality into smaller boolean checks. This way, you can validate row by row, column by column, and square by square. For instance
private boolean isValidRow(int[] row) {
// Code here to check for valid row (ie, check for duplicate numbers)
}
private boolean isValidColumn(int[] column) {
// Code here to check for valid column
}
private boolean isValidSquare(int[][] square) {
// Code here to check for valid square
}
Note that rows and columns only need to be passed a 1 dimensional array. Squares are a 2 dimensional array as you need to check a 3x3 area. You can also treat these methods as static as their functionality is independent of the Sudoku board instance.
Edit: A suggestion on row/column/square validation is to use a HashSet. Sets can only have 1 element of a certain value, so you can add elements and look for a failure. For example:
HashSet<Integer> hs = new HashSet<Integer>();
for(int i = 0; i < 9; i++) {
if(!hs.add(integerArray[i])) // HashSet.add returns 'false' if the add fails
// (ie, if the element exists)
return false;
}
return true;

Categories