I have to partition a 2d array (the size is given by the user) into sub-arrays given an input number by the user. The code i Wrote works well for most of the instances by there are some that I need some help with.
I do this by taking the square root of the input number. So for example:
If the user inserts [10, 10, 9] it means that this is a 10 * 10 array with 9 sub-arrays. Taking the square root of 9 works fine because it gives 3.
If the user inserts [8, 6, 6] it takes the square root of 6 and rounds it up for the longest side (which gives 3) and rounds it down for the shortest (which is 2). So 3 * 2 = 6. It also works fine.
Then there is a situation like 8. The square root of 8 gives 3 and 2. So the array is partitioned into 6 sub-arrays. Is there another way to find a better partitioning for numbers like 8, 14? Or is there a way to find the optimal distribution for such numbers (e.g. 2 * 4 = 8, 2 * 7 = 14)?
You can calculate them a bit different way:
int x = Math.round(Math.sqrt(n));
int y = Math.round(1. * n / x);
Thus you'll receive:
n = 8 => x = 3, y = 3
n = 14 => x = 4, y = 4
What you need to do is find the two nearest factors to the square root. Try this code:
long n = 14;
long y = 0;
long x = Math.round(Math.sqrt(n));
while(true){
if (n % x == 0) {
y = n/x;
break;
}
else {
x--;
}
}
You might also like to put in some error checking to cope with input errors. e.g. n<1.
Related
I need a fast way to find maximum value when intervals are overlapping, unlike finding the point where got overlap the most, there is "order". I would have int[][] data that 2 values in int[], where the first number is the center, the second number is the radius, the closer to the center, the larger the value at that point is going to be. For example, if I am given data like:
int[][] data = new int[][]{
{1, 1},
{3, 3},
{2, 4}};
Then on a number line, this is how it's going to looks like:
x axis: -2 -1 0 1 2 3 4 5 6 7
1 1: 1 2 1
3 3: 1 2 3 4 3 2 1
2 4: 1 2 3 4 5 4 3 2 1
So for the value of my point to be as large as possible, I need to pick the point x = 2, which gives a total value of 1 + 3 + 5 = 9, the largest possible value. It there a way to do it fast? Like time complexity of O(n) or O(nlogn)
This can be done with a simple O(n log n) algorithm.
Consider the value function v(x), and then consider its discrete derivative dv(x)=v(x)-v(x-1). Suppose you only have one interval, say {3,3}. dv(x) is 0 from -infinity to -1, then 1 from 0 to 3, then -1 from 4 to 6, then 0 from 7 to infinity. That is, the derivative changes by 1 "just after" -1, by -2 just after 3, and by 1 just after 6.
For n intervals, there are 3*n derivative changes (some of which may occur at the same point). So find the list of all derivative changes (x,change), sort them by their x, and then just iterate through the set.
Behold:
intervals = [(1,1), (3,3), (2,4)]
events = []
for mid, width in intervals:
before_start = mid - width - 1
at_end = mid + width
events += [(before_start, 1), (mid, -2), (at_end, 1)]
events.sort()
prev_x = -1000
v = 0
dv = 0
best_v = -1000
best_x = None
for x, change in events:
dx = x - prev_x
v += dv * dx
if v > best_v:
best_v = v
best_x = x
dv += change
prev_x = x
print best_x, best_v
And also the java code:
TreeMap<Integer, Integer> ts = new TreeMap<Integer, Integer>();
for(int i = 0;i<cows.size();i++) {
int index = cows.get(i)[0] - cows.get(i)[1];
if(ts.containsKey(index)) {
ts.replace(index, ts.get(index) + 1);
}else {
ts.put(index, 1);
}
index = cows.get(i)[0] + 1;
if(ts.containsKey(index)) {
ts.replace(index, ts.get(index) - 2);
}else {
ts.put(index, -2);
}
index = cows.get(i)[0] + cows.get(i)[1] + 2;
if(ts.containsKey(index)) {
ts.replace(index, ts.get(index) + 1);
}else {
ts.put(index, 1);
}
}
int value = 0;
int best = 0;
int change = 0;
int indexBefore = -100000000;
while(ts.size() > 1) {
int index = ts.firstKey();
value += (ts.get(index) - indexBefore) * change;
best = Math.max(value, best);
change += ts.get(index);
ts.remove(index);
}
where cows is the data
Hmmm, a general O(n log n) or better would be tricky, probably solvable via linear programming, but that can get rather complex.
After a bit of wrangling, I think this can be solved via line intersections and summation of function (represented by line segment intersections). Basically, think of each as a triangle on top of a line. If the inputs are (C,R) The triangle is centered on C and has a radius of R. The points on the line are C-R (value 0), C (value R) and C+R (value 0). Each line segment of the triangle represents a value.
Consider any 2 such "triangles", the max value occurs in one of 2 places:
The peak of one of the triangle
The intersection point of the triangles or the point where the two triangles overall. Multiple triangles just mean more possible intersection points, sadly the number of possible intersections grows quadratically, so O(N log N) or better may be impossible with this method (unless some good optimizations are found), unless the number of intersections is O(N) or less.
To find all the intersection points, we can just use a standard algorithm for that, but we need to modify things in one specific way. We need to add a line that extends from each peak high enough so it would be higher than any line, so basically from (C,C) to (C,Max_R). We then run the algorithm, output sensitive intersection finding algorithms are O(N log N + k) where k is the number of intersections. Sadly this can be as high as O(N^2) (consider the case (1,100), (2,100),(3,100)... and so on to (50,100). Every line would intersect with every other line. Once you have the O(N + K) intersections. At every intersection, you can calculate the the value by summing the of all points within the queue. The running sum can be kept as a cached value so it only changes O(K) times, though that might not be posible, in which case it would O(N*K) instead. Making it it potentially O(N^3) (in the worst case for K) instead :(. Though that seems reasonable. For each intersection you need to sum up to O(N) lines to get the value for that point, though in practice, it would likely be better performance.
There are optimizations that could be done considering that you aim for the max and not just to find intersections. There are likely intersections not worth pursuing, however, I could also see a situation where it is so close you can't cut it down. Reminds me of convex hull. In many cases you can easily reduce 90% of the data, but there are cases where you see the worst case results (every point or almost every point is a hull point). For example, in practice there are certainly causes where you can be sure that the sum is going to be less than the current known max value.
Another optimization might be building an interval tree.
This question already has answers here:
Int division: Why is the result of 1/3 == 0?
(19 answers)
Closed 4 years ago.
Why is the output of this program 1 1 2 2 3 3 instead of 1 1 2 2 3 1
class Scratch {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 3 };
for (int i = 0; i < 6; i++)
System.out.print(a[i / 2] + " ");
}
}
When you divide 3/2 it equals 1.5, which I thought Java only took the first value of an integer number. What's going on?
You are dividing the index not the value. To get the result you're looking for, you should take the division outside the square brackets:
System.out.print(a[i] / 2 + " ");
// Here --------------^
The last iteration of the loop will be when i = 5. 5/2 = 2. a[2] = 3.
Because the last number of your loop is 5.
Then 5/2 = 2.5 which java turns into 2.
If you see your array, it came up that in the position 2, the number printed is 3.
I think the mistake you're making is that you're thinking of the values stored in the array being divided by 2, not the index. Or really moreso, you're letting the fact that the value 3 is not what you would expect the last value in the array would be, affect your perception of what the array look-up should yield. It's important to keep those separate.
Your code is looking up (0, 1, 2, 3, 4, 5) all divided by two which is (0, 0, 1, 1, 2, 2) with integer division. That is, a[5 / 2] = a[2] = 3.
i / 2 is an integer division which will effectively take the floor of the produced value by discarding the fractional part.
This results in a[0/2=0], a[1/2=0], a[2/2=1], a[3/2=1], a[4/2=2], a[5/2=2] array element access in your code.
This question already has answers here:
How to add two numbers of any length in java?
(8 answers)
Closed 5 years ago.
Today I had an interview and the interviewer asked to make a program for addition of two numbers, I get shocked how can he give a simple question but the question is different
the length of two number can be anything (10,20,30 or even 1000 etc.)
if you convert it to int,double,long double if the number is greater than their range than the answer can be wrong.
Please help me for the question.
You can always take the two numbers in arrays (i.e. arrays have digits of the numbers as elements) and add them as we add manually i.e. start from one's digit and store the carry if it's present then do the same for ten's digit, then hundred's digit and so on.
Say you want to add 123 and 329.
X = 123, X[] = [1,2,3]
Y = 329, Y[] = [3,2,9]
You start with one's digit (the rightmost or last element) and add the elements of both X and Y arrays and add carry to it (initially set to 0). If the addition comes out to be greater than 10, set carry = sum / 10 (since we are adding each element, this carry shall always be either 0 or 1) and the addition to add [i] = sum % 10. Repeat till all the elements of smaller array are over. Then add the carry to remaining elements of larger array continuing the above logic.
carry = 0
Step 1 : 3 + 9 + carry (0) = 5, carry => 12 / 10 = 1, add => 12 % 10 = 2
Step 2 : 2 + 2 + carry (2) = 6, carry => 6 / 10 = 0, add => 6 % 10 = 6
Step 3 : 3 + 1 + carry (0) = 4, carry => 4 / 10 = 0, add => 4 % 10 = 4
Ans = 462
Obviously the array storing sum may have one digit extra so take care of that as well.
1 - 1
2 - 2,3
3 - 4,5,6
4 - 7,8,9,10
Given any number from 4 to 6 ,I need the output as 3.
Given any number from 7 to 10 ,I need the output as 4.
I need the fastest solution for the above problem to solve an algorithm.
What I could think of is a brute force algorithm :
Given 7:
n-square + n = 7*2 = 14
1 + 1 = 2 < 14
4 + 2 = 6 < 14
9 + 3 = 12 < 14
16+ 4 = 20 >=14 --> So 4
Is there any better approach to arrive at the solution ? OR My approach to the algorithm itself is flawed ?
Brief explanation of the algo :
A,B,C
After every iteration every element becomes increased by one.
A,A,B,B,C,C
Given 3, C will be returned.
Given 4 or 5, A will be returned.
Given 6 or 7, B will be returned.
Given 8 or 9, C will be returned.
Given 10 or 11 or 12, A will be returned.
Given 13 or 14 or 15, B will be returned.
How the solution to the mathematical problem will help solve the algo :
Total number of elements = 3
Given number = 13 (Output to be B)
Divide and Ceiling = Ceil (13/3) = 5 [So 13 falls under when every element has become * 3] (From Mathematical problem : If given number is 5, 3 is to be used)
Starting index of when every element has become * 3 [IS_EQUAL_TO = ] 3 * 3(summation of previous iteration => 1 + 2) + 1 = 10
To Find the index = Ceil(13-10+1/3 (this 3,comes from the mathematical problem) ) = Ceil (4/3) = 2nd index = B
Given number of rows N, the size of the triangle is N(N+1)/2. You are essentially trying to find the least integer N such that N(N+1)/2 >= M, with M given. If you have a function to compute square roots, you can solve this equation in constant time.
N(N+1)/2 >= M, multiply both sides with 2,
N²+N >= 2M, complete the square, take the square root, blablabla
N >= sqrt(2M+1/4)-1/2
Therefore the answer is N = ceil(sqrt(2*M + .25) - .5)
int firstPosition(int x, int [] a) {
int lower = 0;
int upper = a.length;
while (lower != upper) {
int mid = (lower + upper) / 2;
**if (x <= a[mid]) {** // the line I don't understand
upper = mid;
} else {
lower = mid + 1;
}
return (lower);
}
If a = {4, 4, 5, 5, 6, 7, 8, 9, 9, 9} what will the algorithm return for the following choices of x?
i) x = 3
ii) x = 4
iii) x = 5
iv) x = 9
v) x = 11
I have tried stepping through this program, for example x = 3, a.length returns 10, so upper is always equal to 10.
while ( 3 ! = 0 ) { // execute line
int mid = lower + upper / 2 - which is (0 + 10)/2 = 5
if ( x <= a[mid]) // I assume that means if 3 is less than or equal to 5? 5 then replace mid with 5 and then...
lower = mid + 1 // 5+1 = 6, return 6 as lower?
This is a basic binary search algorithm, implemented iteratively instead of recursively.
The line you don't understand checks to see if x (the search value) might lie in the lower half or upper half of the array. This works because the array is sorted. We can divide any sorted array into two halves, and look at the value in the middle to determine which half the value we're looking for might be in.
Say that the array looks like this:
+---+---+---+---+---+----+
| 1 | 3 | 5 | 7 | 9 | 11 |
+---+---+---+---+---+----+
^ ^
| |
lower upper
and we're trying to figure out which slot the number 9 is in. Since the array is sorted, we can immediately discard half of the array.
How?
Look at the value in the "center" of the array: it's 5, and 9 is larger than 5, so we know that 9 must be in the upper half of the array. Algorithmically speaking, this would be the else case of the if statement in your code.
So we repeat the same process, but only looking at the upper half of the array this time:
+---+---+---+---+---+----+
| 1 | 3 | 5 | 7 | 9 | 11 |
+---+---+---+---+---+----+
^ ^
| |
lower upper
Looks to me like a binary search algorithm. The choice of x makes sure that the array part that needs to be searched is halved each iteration. Read more about it here
This is a modification of a binary search.
Since the data is ordered, to determine if you can throw away the "upper" or "lower" half of a range of data, look at the middle element. When it is bigger than the number you're looking for, you can safely throw away the numbers past it (by reducing the range). When it is smaller than the number you are looking for, you can safely throw away the numbers before it (by reducing the range).
The key here is that if it is the number you are looking for, you need to crawl back towards the beginning of the range until you detect that the "next" number is not actually the "first" of that possibly repeated value.