Perfect square or not? - algorithm

This is a code to check if a number is perfect square or not. Why does it work ?
static bool IsSquare(int n)
{
int i = 1;
for (; ; )
{
if (n < 0)
return false;
if (n == 0)
return true;
n -= i;
i += 2;
}
}

Because all perfect squares are sums of consecutive odd numbers:
1 = 1
4 = 1 + 3
9 = 1 + 3 + 5
16 = 1 + 3 + 5 + 7
and so on. Your program attempts to subtract consecutive odd numbers from n, and see if it drops to zero or goes negative.
You can make an informal proof of this by drawing squares with sides of {1,2,3,4,...} and observe that constructing a square k+1 from square k requires adding 2k+1 unit squares.

Related

Maximum sum of 1 to n numbers where the sum should never be equal to given integer k

how to find the maximum sum of the numbers starting from 1 to n but at any time the current sum should never be equal to a given number k.
This is what I have done but its not correct all the time.
static int maxMoney(int n, long k) {
int currentSum = 0;
for(int i = 1; i <= n; i++){
currentSum += i;
if(currentSum == k){
currentSum -= 1;
continue;
}
}
return currentSum;
}
constraints
1<= n <= 2 * 10^9
1<= k <= 4*10^15
So if n = 3 and k = 3;
and if we add 1 + 2 we get 3, we reject 1 and start at 2 and do 2+3 to get 5.
We can also do 1+3 and we get the value 4 in this case but since we want maximum we choose 5 over 4 and hence 5 is the answer in this case.
Assume first you can just sum all numbers: sum = 1+2+...+n, which can be calculated as sum = n(n+1)/2.
Then check if there is an i between 1 and n, such that 1+2+...+i = k. If not, then the previously calculated sum is the solution.
If there is such i, then reject 1, and return sum - 1.
Determine whether such i exists by solving the following equation:
k = i(i+1)/2
This quadratic equation has this positive solution:
i = (sqrt(1+8k) - 1) / 2
If this i is an integer number, and it is within the interval 1...n, then we have indeed found such an i. Otherwise, we can conclude that k will never be equal to 1+2+...+i for any i in the interval 1...n.
So here is a little JavaScript function that implements this:
function getSum(n, k) {
var sum, i;
sum = n*(n+1)/2;
i = (Math.sqrt(1+8*k) - 1) / 2;
if (i === Math.floor(i) && i <= n)
sum--;
return sum;
}
// Sample call
console.log(getSum(3, 3)); // = 5

Minimize total area using K rectangles in less than O(N^4)

Given an increasing sequence of N numbers (up to T), we can use at most K rectangles (placed starting at position 0) such as for the i-th value v in the sequence, exists a rectangle in positions [v, T) with height at least i + 1.
Total area of rectangles should be the minimum that satisfies what mentioned above.
Example: given the sequence [0, 3, 4], T = 5 and K = 2 we can use:
a rectangle from 0 to 2 with height 1 (thus having an area of 3)
a rectangle from 3 to 4 with height 3 (thus having an area of 6).
Using at most 2 rectangles, we cannot get a total area smaller than 9.
This problem can be solved using DP.
int dp[MAXK+1][MAXN][MAXN];
int sequence[MAXN];
int filldp(int cur_idx, int cur_value, int cur_K) {
int res = dp[cur_K][cur_idx][cur_value];
if (res != -1) return res;
res = INF;
if (cur_idx == N - 1 && cur_value >= N)
res = min(res, (T - seq[cur_idx]) * cur_value);
else {
if (cur_idx < N - 1 && cur_value >= cur_idx + 1) {
int cur_cost = (seq[cur_idx + 1] - seq[cur_idx]) * cur_value;
res = min(res, cur_cost + filldp(cur_idx + 1, cur_value, cur_K);
}
// Try every possible height for a rectangle
if (cur_K < K)
for (int new_value = cur_value + 1; cur_value <= N; new_value++)
res = min(res, filldp(cur_idx, new_value, cur_K + 1));
}
dp[cur_K][cur_idx][cur_value] = res;
return res;
}
Unsurprisingly, this DP approach is not really fast probably due to the for cycle. However, as far as I can understand, this code should not do more than MAXK * MAXN * MAXN significative calls (i.e., not more that every cell in dp). MAXK and MAXN are both 200, so dp has 8 millions of cells, which is not too much.
Am I missing anything?
UPDATE: As pointed out by Saeed Amiri (thank you!), the code makes N^2*K significative calls, but each one is O(N). The whole algorithm is then O(N^3*K) = O(N^4).
Can we do better?

Algorithm to compute minimum number of visible buildings?

I have been trying to formulate an algorithm to solve a problem. In this problem, we have a photo containing some buildings. The photo is divided into n vertical regions (called pieces) and the height of a building in each piece is given.
One building may span several consecutive pieces, but each piece can only contain one visible building, or no buildings at all. We are required to find the minimum number of buildings.
e.g.
given ,
3 ( no of pieces)
1 2 3 ( heights) ans = 3
3
1 2 1 ans = 2
6
1 2 3 1 2 3 ans = 5 ( a figure wud help show the overlap.).
Though I feel like I get it, I am unable to get a solid algorithm for it. Any ideas?
You can find the lowest number from the given array and account for all occurances of this number. This will split the array into multiple subarrays and now you need to recursively solve the problem for each of them.
In the example:
1 2 3 1 2 3 (total = 0)
Smallest number is 1:
x 2 3 x 2 3 (total = 1)
Now you have 2 subarrays.
Solve for the first one - the smallest number is 2:
x 3 (total = 2)
Finally you have a single element: total = 3
Solving the other subarray makes it 5.
Here is some code in C#:
int Solve(int[] ar, int start, int end){
//base for the recursion -> the subarray has single element
if(end-start == 1) return 1;
//base for the recursion -> the subarray is empty
if(end-start < 1) return 0;
//find min
int m = int.MaxValue;
for(int i = start; i < end; i++)
if (ar[i] < m) m = ar[i];
int total = 1;
//find the subarrays and their contribution recursively
int subStart = start;
for(int subEnd = start; subEnd < end; subEnd++){
if(ar[subEnd] == m) {
total += Solve(ar, subStart, subEnd);
subStart = subEnd + 1;
}
}
total += Solve(ar, subStart, ar.Length);
return total;
}

Cycle Detection Algorithm

Say I have a function f:
f(0) = 0
f(i) = (i - 1) % 4
f(0..12):
0 0 1 2 3 0 1 2 3 0 1 2 3
I want to find the cycle start and the cycle length, which are 1 and 4, respectively.
The tortoise and hare algorithm works with iterated functions, but I don't have an iterated function.
Are there other algorithms that work with non-iterated functions or can the tortoise and hare algorithm be modified for this?
Edit:
Using Jason S's answer, I managed to come up with this, which seems to be working:
public static Tuple<int, int> ModifiedTortoiseHare(Func<int, int> f, int x0 = 0, int checks = 4)
{
for (; ; x0++)
{
int lam = 0, tortoise, hare;
do
{
lam++;
tortoise = f(x0 + lam);
hare = f(x0 + 2 * lam);
} while (tortoise != hare);
int mu = -1;
do
{
mu++;
tortoise = f(x0 + mu);
hare = f(x0 + mu + lam);
} while (tortoise != hare);
if (mu != 0) continue;
bool correct = true;
int lamCheckMax = lam * checks;
for (int x = 0; x < lamCheckMax; x++)
{
if (f(x0 + x + mu) != f(x0 + x + mu + lam))
{
correct = false;
if (mu != 0) x0 += mu - 1;
break;
}
}
if (correct) return Tuple.Create(x0 + mu, lam);
}
}
If the function is a "black box", and you have the ability to find f(x) for any individual x (whether valid for real numbers or only integers), but you don't know anything else, there is no general way to find a cycle start and length. For example, consider the function
f(k) = (k - 1) % 4 + g(k)
g(k) = max(0, k-1000000)
then f(k) looks like it repeats every 4 integers, but then when you get to k = 1000000, then the pattern stops.
If the function has a finite range, and you can test for all integers, the tortoise/hare algorithm (= Floyd's cycle-finding algorithm) can be used to help.
Instead of iterating function evaluation, calculate f(k0 + k) and f(k0 + 2*k) until they match, at which point the suspected period is k, and you just need to repeat through all values to verify that the cycle continues.
Your question appears to be an equivalent problem as "How should I find repeated word sequences?" which has a number of answers.
for the fn you have given since its dividing by 4 the length is four and since there is no value added to it 0 is actually the start of the cycle and not 1.you can actually observe this if you do implement it using a graph as has been pointed out.
Since these are fn values you could use a linked list instead, and on every value the fn returns, add it to the list if its not already there, else u can have a cycle.assuming that there is only 1 cycle..

Calculate the sum of elements in a matrix efficiently

In an interview I was asked if I was given an n*m matrix how to calculate the sum of the values in a given sub-matrix (defined by top-left, bottom-right coordinates).
I was told I could pre-process the matrix.
I was told the matrix could be massive and so could the sub-matrix so the algo had to be efficient. I stumbled a bit and wasn't told the best answer.
Anyone have a good answer?
This is what Summed Area Tables are for. http://en.wikipedia.org/wiki/Summed_area_table
Your "preprocessing" step is to build a new matrix of the same size, where each entry is the sum of the sub-matrix to the upper-left of that entry. Any arbitrary sub-matrix sum can be calculated by looking up and mixing only 4 entries in the SAT.
EDIT: Here's an example.
For the initial matrix
0 1 4
2 3 2
1 2 7
The SAT is
0 1 5
2 6 12
3 9 22
The SAT is obtained using S(x,y) = a(x,y) + S(x-1,y) + S(x,y-1) - S(x-1,y-1),
where S is the SAT matrix and a is the initial matrix .
If you want the sum of the lower-right 2x2 sub-matrix, the answer would be 22 + 0 - 3 - 5 = 14. Which is obviously the same as 3 + 2 + 2 + 7. Regardless of the size of the matrix, the sum of a sub matrix can be found in 4 lookups and 3 arithmetic ops. Building the SAT is O(n), similarly requiring only 4 lookups and 3 math ops per cell.
You can do it by Dynamic programming. Create matrix dp with size n*m.
And for each i, j where
1 <= i <= n , 1 <= j <= m
dp[i][j] will be :
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + values[i][j]
And for each query we have lx, rx, ly, ry where lx and rx are top-left coordinates, ly and ry bottom-right coordinates of sub-matrix.
1 ≤ lxi ≤ rx ≤ n, 1 ≤ ly ≤ ry ≤ m
sum = dp[rx][ry] - dp[lx - 1][ry] - dp[rx][ly - 1] + dp[lx-1][ly - 1]
Look at picture to understand how algorithm works.
OD = dp[rx][ry], OB = dp[lx - 1][ry], OC = dp[rx][ly - 1], OA = dp[lx - 1][ly - 1]
Create a new matrix where entry (i,j) is the sum of elements in the original matrix that have lower or equal i and j. Then, to find the sum of the elements in the submatrix, you can just use a constant number of basic operations using the corners of the submatrix of your sum matrix.
In particular, find the corners top_left, bottom_left, top_right and bottom_right of your sum matrix, where the first three are just outside the submatrix and bottom_right is just inside. Then, your sum will be
bottom_right + top_left - bottom_left - bottom_right
Below is a sample implementation in C using Summed Area Tables concept as explained in one of the answers above.
Python implementation for the same can be found at below link -
http://www.ardendertat.com/2011/09/20/programming-interview-questions-2-matrix-region-sum/
#include<stdio.h>
int pre[3][3];
int arr[3][3] = {
{0,1,4},
{2,3,2},
{1,2,7}
};
void preprocess()
{
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
if(i>0 && j>0)
{
pre[i][j] = arr[i][j] + pre[i-1][j] + pre[i][j-1] - pre[i-1][j-1];
}
else if(i>0 && j==0)
{
pre[i][j] = arr[i][j] + pre[i-1][j];
}
else if(j>0 && i==0)
{
pre[i][j] = arr[i][j] + pre[i][j-1];
}
else
{
pre[i][j] = arr[i][j];
}
}
}
}
int subsum(int x1, int y1, int x2, int y2)
{
preprocess();
int ans = pre[x2][y2] - pre[x1-1][y2] - pre[x2][y1-1] + pre[x1-1][y1-1];
return ans;
}
int main()
{
printf("%d\n",subsum(1,1,2,2));
return 0;
}
This should work. You always have to go through each element in the submatrix to do the addition and this is the simplest way.
*note that the following code may not compile but it's right in pseudocode
struct Coords{
int x,y;
}
int SumSubMatrix(Coords topleft, Coords bottomright, int** matrix){
int localsum = 0;
for( int i = topleft.x; i <= bottomright.x; i++ ){
for(int j = topleft.y; j <= bottomright.y; j++){
localsum += matrix[i][j];
}
}
return localsum;
}
Edit: An alternative pre-processing method is to create another matrix from the original containing the row or column sums. Here's an example:
Original:
0 1 4
2 3 2
1 2 7
Row Matrix:
0 1 5
2 5 7
1 3 10
Column Matrix:
0 1 4
2 4 6
3 6 13
Now, just take the endpoint x values and subtract the start point values, like so (for rows based):
for( int i = topleft.y; i >= bottomright.y; i++ ){
localsum += matrix2[bottomright.x][i] - matrix2[topleft.x][i];
}
Now, it's either O( n ) or O( m )

Resources