longest subsequence with alternate signs - algorithm

Given an array of +ve and -ve integers. Write an algorithm to find longest subsequence with alternate signs.
If 0 is there in array, it can be considered as both +ve and -Ve.
Exampls : Array : 5,-9,4,0,-1,5,-5,3,0,2
Longest subsequence : [0,-1,5,-5,3,0,2] size: 7
I wrote one function, it's working fine , but is there any other better way?
void f (int A[],int N){
int fIndex = 0;
int eIndex = 0;
int maxCount =0;
int curCount =0;
int start =0;
for(int i=1;i<N;++i){
if(A[i] > 0 && A[i-1]>=0){
if(i>=2 && A[i-2] < 0){
fIndex = i;
curCount =0;
}
}
if(A[i] < 0 && A[i-1] <=0){
if(i>=2 && A[i-2] > 0){
fIndex = i;
curCount =0;
}
}
if((A[i] > 0 && A[i-1] <= 0) || (A[i] <0 && A[i-1]>=0)){
curCount++;
if(curCount > maxCount){
maxCount = curCount;
}
start = fIndex;
eIndex = i;
}else if(A[i] == 0){
if(A[i-1]> 0){
A[i] = -1;
}
curCount++;
if(curCount > maxCount){
maxCount = curCount;
}
eIndex = i;
}
}
return maxCount+1;
}

There are only two possibilities for alternation like -+-+... or +-+-.... so we can just use two counters and reset them when a number comes we don't like:
int max = 0;
int[] l = {0, 0};
for (int i = 0; i < N; i++) {
if (a[i] == 0) {
l[0]++;
l[1]++;
continue;
}
int s = ((i % 2 == 0 && a[i] < 0) || (i % 2 == 1 && a[i] > 0)) ? 0 : 1;
l[1-s]++;
if (l[s] > max)
max = l[s];
l[s] = 0;
}
return max >= l[0] && max >= l[1] ? max : (l[0] >= l[1] ? l[0] : l[1]);

Related

Finding longest sequence of '1's in a binary array by replacing any one '0' with '1'

I have an array which is constituted of only 0s and 1s. Task is to find index of a 0, replacing which with a 1 results in the longest possible sequence of ones for the given array.
Solution has to work within O(n) time and O(1) space.
Eg:
Array - 011101101001
Answer - 4 ( that produces 011111101001)
My Approach gives me a result better than O(n2) but times out on long string inputs.
int findIndex(int[] a){
int maxlength = 0; int maxIndex= -1;
int n=a.length;
int i=0;
while(true){
if( a[i] == 0 ){
int leftLenght=0;
int j=i-1;
//finding count of 1s to left of this zero
while(j>=0){
if(a[j]!=1){
break;
}
leftLenght++;
j--;
}
int rightLenght=0;
j=i+1;
// finding count of 1s to right of this zero
while(j<n){
if(a[j]!=1){
break;
}
rightLenght++;
j++;
}
if(maxlength < leftLenght+rightLenght + 1){
maxlength = leftLenght+rightLenght + 1;
maxIndex = i;
}
}
if(i == n-1){
break;
}
i++;
}
return maxIndex;
}
The approach is simple, you just need to maintain two numbers while iterating through the array, the current count of the continuous block of one, and the last continuous block of one, which separated by zero.
Note: this solution assumes that there will be at least one zero in the array, otherwise, it will return -1
int cal(int[]data){
int last = 0;
int cur = 0;
int max = 0;
int start = -1;
int index = -1;
for(int i = 0; i < data.length; i++){
if(data[i] == 0){
if(max < 1 + last + cur){
max = 1 + last + cur;
if(start != -1){
index = start;
}else{
index = i;
}
}
last = cur;
start = i;
cur = 0;
}else{
cur++;
}
}
if(cur != 0 && start != -1){
if(max < 1 + last + cur){
return start;
}
}
return index;
}
O(n) time, O(1) space
Live demo: https://ideone.com/1hjS25
I believe the problem can we solved by just maintaining a variable which stores the last trails of 1's that we saw before reaching a '0'.
int last_trail = 0;
int cur_trail = 0;
int last_seen = -1;
int ans = 0, maxVal = 0;
for(int i = 0; i < a.size(); i++) {
if(a[i] == '0') {
if(cur_trail + last_trail + 1 > maxVal) {
maxVal = cur_trail + last_trail + 1;
ans = last_seen;
}
last_trail = cur_trail;
cur_trail = 0;
last_seen = i;
} else {
cur_trail++;
}
}
if(cur_trail + last_trail + 1 > maxVal && last_seen > -1) {
maxVal = cur_trail + last_trail + 1;
ans = last_seen;
}
This can be solved by a technique that is known as two pointers. Most two-pointers use O(1) space and O(n) time.
Code : https://www.ideone.com/N8bznU
#include <iostream>
#include <string>
using namespace std;
int findOptimal(string &s) {
s += '0'; // add a sentinel 0
int best_zero = -1;
int prev_zero = -1;
int zeros_in_interval = 0;
int start = 0;
int best_answer = -1;
for(int i = 0; i < (int)s.length(); ++i) {
if(s[i] == '1') continue;
else if(s[i] == '0' and zeros_in_interval == 0) {
zeros_in_interval++;
prev_zero = i;
}
else if(s[i] == '0' and zeros_in_interval == 1) {
int curr_answer = i - start; // [start, i) only contains one 0
cout << "tried this : [" << s.substr(start, i - start) << "]\n";
if(curr_answer > best_answer) {
best_answer = curr_answer;
best_zero = prev_zero;
}
start = prev_zero + 1;
prev_zero = i;
}
}
cout << "Answer = " << best_zero << endl;
return best_zero;
}
int main() {
string input = "011101101001";
findOptimal(input);
return 0;
}
This is an implementation in C++. The output looks like this:
tried this : [0111]
tried this : [111011]
tried this : [1101]
tried this : [10]
tried this : [01]
Answer = 4

Maximal Square with 0 inside

The question Maximal Square in https://leetcode.com/problems/maximal-square/description/ is easy to solve by DP. But how to solve the following up question:
Similar as Maximal Square question, but allows 0's inside a square, "inside" means the border of the square must be all 1.
For example, given the following matrix:
1 0 1 0 0
1 0 1 1 1
1 1 1 0 1
1 0 1 1 1
Return 9.
Update: Because the 3*3 matrix in the right bottom corner matches the requirement, the border must be all 1, and there can be 0 inside the square.
I thought up a O(n^3) algorithm: take maze[i][j] as the right bottom corner of the square if maze[i][j] == 1, enumerate the edge length of the square. If edge length is 3, consider whether maze[i - 2][j - 2], maze[i][j - 2], maze[i - 2][j], maze[i][j] forms a square with the numbers in each edge are all 1.
Is there any better algorithm?
Your problem can be solved in O (n * m) time and space complexity, where n is total rows and m is total columns in matrix. You may look at the code below where I have commented out to make it understandable.
Please, let me know if you have any doubt.
#include <bits/stdc++.h>
using namespace std;
void precalRowSum(vector< vector<int> >& grid, vector< vector<int> >&rowSum, int n, int m) {
// contiguous sum upto jth position in ith row
for (int i = 0; i < n; ++i) {
int sum = 0;
for (int j = 0; j < m; ++j) {
if (grid[i][j] == 1) {
sum++;
} else {
sum = 0;
}
rowSum[i][j] = sum;
}
}
}
void precalColSum(vector< vector<int> >& grid, vector< vector<int> >&colSum, int n, int m) {
// contiguous sum upto ith position in jth column
for (int j = 0; j < m; ++j) {
int sum = 0;
for (int i = 0; i < n; ++i) {
if (grid[i][j] == 1) {
sum++;
} else {
sum = 0;
}
colSum[i][j] = sum;
}
}
}
int solve(vector< vector<int> >& grid, int n, int m) {
vector< vector<int> >rowSum(n, vector<int>(m, 0));
vector< vector<int> >colSum(n, vector<int>(m, 0));
// calculate rowwise sum for 1
precalRowSum(grid, rowSum, n, m);
// calculate colwise sum for 1
precalColSum(grid, colSum, n, m);
vector< vector<int> >zerosHeight(n, vector<int>(m, 0));
int ans = 0;
for (int i = 0; i < (n - 1); ++i) {
for (int j = 0; j < m; ++j) {
zerosHeight[i][j] = ( grid[i][j] == 0 );
if (grid[i][j] == 0 && i > 0) {
zerosHeight[i][j] += zerosHeight[i - 1][j];
}
}
if (i == 0) continue;
// perform calculation on ith row
for (int j = 1; j < m; ) {
int height = zerosHeight[i][j];
if (!height) {
j++;
continue;
}
int cnt = 0;
while (j < m && height == zerosHeight[i][j]) {
j++;
cnt++;
}
if ( j == m) break;
if (cnt == height && (i - cnt) >= 0 ) {
// zeros are valid, now check validity for boundries
// Check validity of upper boundray, lower boundary, left boundary, right boundary respectively
if (rowSum[i - cnt][j] >= (cnt + 2) && rowSum[i + 1][j] >= (cnt + 2) &&
colSum[i + 1][j - cnt - 1] >= (cnt + 2) && colSum[i + 1][j] >= (cnt + 2) ){
ans = max(ans, (cnt + 2) * (cnt + 2) );
}
}
}
}
return ans;
}
int main() {
int n, m;
cin>>n>>m;
vector< vector<int> >grid;
for (int i = 0; i < n; ++i) {
vector<int>tmp;
for (int j = 0; j < m; ++j) {
int x;
cin>>x;
tmp.push_back(x);
}
grid.push_back(tmp);
}
cout<<endl;
cout<< solve(grid, n, m) <<endl;
return 0;
}

Find zeroes to be flipped so that number of consecutive 1’s is maximized

Find zeroes to be flipped so that number of consecutive 1’s is maximized.
Input: arr[] = {1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1}
m = 2
Output: 5 7
We are allowed to flip maximum 2 zeroes. If we flip
arr[5] and arr[7], we get 8 consecutive 1's which is
maximum possible under given constraints .
Now if we were to find just the maximum number of 1's that is possible, is it possible to solve using dynamic programming approach?
This problem can be solved in linear time O(N) and linear space O(N). Its not full fledged dynamic programming, but its similar to that as it uses precomputation.
Data Structures Used:
1.left: It is an integer array, of same length as given array. It is precomputed such that for every position i:
left[i] = Number of consecutive 1's to the left position i
2.right: It is an integer array, of same length as given array. It is precomputed such that for every position i:
right[i] = Number of consecutive 1's to the right position i
These can be computed in single traversal of the array.Assuming arr is the original array, following pseudocode does the job:
Pseudocode for populating left array
left()
{
int count = 0;
for(int i = 0;i < arr length; ++i)
{
if(i == 0)
{
left[i] = 0;
if(arr[i] == 1)
count++;
continue;
}
else
{
left[i] = count;
if(arr[i] == 1)
count++;
else count = 0;
}
}
}
Pseudocode for populating right array
right()
{
int count = 0;
for(int i = arr length - 1;i >= 0; --i)
{
if(i == arr length - 1)
{
right[i] = 0;
if(arr[i] == 1)
count++;
continue;
}
else
{
right[i] = count;
if(arr[i] == 1)
count++;
else count = 0;
}
}
}
Now the only thing we have to do is :check all pair of positions i and j (i < j) such that arr[i] = 0 and arr[j] = 0 and for no position between i and j arr[i] should be 0 and Keep track of the pair for which we get maximum value of the following:
left[i] + right[j] + right[l]
You could also use left[i] + right[j] + left[r].
left[i] tells the number of consecutive 1's to the left of position i and right[j] tells the number of consecutive 1's to the right of position j and the number of consecutive 1's between i and j can be counted be left[r] OR right[l], and therefore, we have two candidate expressions.
This can also be done in single traversal, using following pseudocode:
max_One()
{
max = 0;
l = -1, r = -1;
for(int i = 0;i < arr length; ++i)
{
if(arr[i] == 0)
{
if(l == -1)
l = i;
else
{
r = i;
if(left[l] + right[r] + right[l] > max)
{
max = left[l] + right[r] + right[l];
left_pos = l;
right_pos = r;
}
l = r;
}
}
}
}
You should use sliding window concept here - use start and end vars to store index of range. Whenever you encounter a 0, increment the counter of zeros received. Include it in current length.. If zeros encounter equals m+1, increment start till you encounter 0.
public static int[] zerosToFlip(int[] input, int m) {
if (m == 0) return new int[0];
int[] indices = new int[m];
int beginIndex = 0;
int endIndex = 0;
int maxBeginIndex=0;
int maxEndIndex=0;
int zerosIncluded = input[0] == 0 ? 1 : 0;
for (int i = 1; i < input.length; i++) {
if (input[i] == 0) {
if (zerosIncluded == m) {
if (endIndex - beginIndex > maxEndIndex - maxBeginIndex){
maxBeginIndex = beginIndex;
maxEndIndex = endIndex;
}
while (input[beginIndex] != 0) beginIndex++;
beginIndex++;
} else {
zerosIncluded++;
}
}
endIndex++;
}
if (endIndex - beginIndex > maxEndIndex - maxBeginIndex){
maxBeginIndex = beginIndex;
maxEndIndex = endIndex;
}
int j = 0;
for (int i = maxBeginIndex; i <= maxEndIndex; i++) {
if (input[i] == 0) {
indices[j] = i;
++j;
}
}
return indices;
}

How to generate n^r variations of an array (i.e. variations with repetition of nCk)

my question is based from topcoder's recent SRM (628 500 point question), i'm trying to solve the string parsing question by brute force since the number of solutions cannot exceed 5^5 and I'm very close. My question is how would I go about generating not only n! permutations but n^r permutations in c#. Using an adaptation of Knuth's lexicographical permutation algorithm my solution works but not for cases when the answer (the winning permutation) has repeated characters.
input example: "X{}]X{X{}]X]"
public string ifPossible(string expression)
{
char[] c = new char[6] { '(', ')', '{', '}', '[', ']' };
StringBuilder sb = new StringBuilder(expression);
int j = 0;
special(sb);
while (my_next_permutation(c) && sb.ToString().Contains('X'))
{
for(int i = 0; i < sb.Length;i++)
{
if (sb[i] == 'X')
sb[i] = c[j++];
}
special(sb);
if (sb.Length > 0)
{
sb.Clear();
sb.Append(expression);
special(sb);
j = 0;
}
else
{
break;
}
}
if (sb.Length > 0)
return "impossible";
return "possible";
}
void special(StringBuilder sb)
{
while (sb.ToString().Contains("()") || sb.ToString().Contains("[]") || sb.ToString().Contains("{}"))
{
while (sb.ToString().Contains("()"))
sb.Replace("()", "");
while (sb.ToString().Contains("[]"))
sb.Replace("[]", "");
while (sb.ToString().Contains("{}"))
sb.Replace("{}", "");
}
}
public Boolean my_next_permutation(char[] a)
{
int N = a.Length, i = N - 2;
for (; i >= 0; i--)
if (a[i] < a[i + 1])
break;
if (i < 0) return false;
for (int j = N - 1; j >= i; j--)
{
if (a[j] > a[i])
{
var temp = a[i];
a[i] = a[j];
a[j] = temp;
break;
}
}
for (int j = i + 1; j < (N + i + 1) / 2; j++)
{
var temp = a[j];
a[j] = a[N + i - j];
a[N + i - j] = temp;
}
return true;
}
I could have used the array idea as gmch and jrh suggested but I
ended up using this:
IEnumerable<string> GetPermutations(char[] list, int? resultSize = null, bool withRepetition = false)
{
List<string> l = new List<string>();
char[] result = new char[resultSize.HasValue ? resultSize.Value : list.Length];
var indices = new int[result.Length];
for (int i = 0; i < indices.Length; i++)
indices[i] = withRepetition ? -1 : indices.Length - i - 2;
int curIndex = 0;
while (curIndex != -1)
{
indices[curIndex]++;
if (indices[curIndex] == list.Length)
{
indices[curIndex] = withRepetition ? -1 : curIndex - 1;
curIndex--;
}
else
{
result[curIndex] = list[indices[curIndex]];
if (curIndex < indices.Length - 1)
curIndex++;
else
yield return new string(result);
}
}
}
I got the idea from this page http://noldorin.com/programming/CombinatoricsUtilities.cs.txt
All credit given to Alex Regueiro.

Count null diagonals in a matrix

I'm trying to create a program that counts the number of null diagonals in a square matrix, but I can't seem to find the correct way of making my index run correctly through the matrix. Here's the incorrect code I've got so far:
# include<stdio.h>
# define MAX 100
int DiagonNull (int n, int A[MAX][MAX]) {
int i, j, count, null;
banda = 0;
for(i = n - 1; i >= 0; i--){
count = 0;
for(j = 0; j <= n && j < i - 1; j++){
if (A[i][j] == 0)
count++;
}
if (count == n - i) /* n - i = number of elements in diagonal */
null++;
else
i = - 1;
}
return null;
}
int main () {
int n, A[MAX][MAX], i, j, null;
printf ("Enter value of n to create a square matrix A of order n: ");
scanf ("%d", &n);
printf ("Enter the elements of matrix A: ");
for (i = 0; i < n; i++){
for (j = 0; j < n; j++){
scanf("%d", &A[i][j]);
}
}
null = DiagonNull (n, A);
printf ("Matrix has null %d diagonals", null);
return 0;
}

Resources