I have some problems with recursion and to understand it I'm trying to make up questions for myself and solve them. This particular question has gotten me confused:
consider this as an input in the form of a string:
[[a,b,c],[[d]],[[e,f]],[g],h,i,[[j,[k,l]]]]
the goal is to find the total number of things in the lists and the lists them self.for this example the result would be:12+10 = 22
note that the input is not an array,it is a string.Also instead of a,b,...
anything can be used,like numbers,strings etc.
[12345,0.34,["afv",24]]
This is my idea but I will mention why I cant implement it:
We write a function that starts iterating the string.It should count the total thing between [ and ].whenever the function reaches a [ it will recall itself to iterate through the remaining string.This way it can go deeper into the arrays.
These are my problems:
I don't know whether my idea is correct or not.
If my idea is correct,what is the base case.
How can I make sure that it counts all the things inside regardless of in what are they?(I mean how can I make sure it treats numbers,strings etc the same)
I think the body of the function should look like this(I'm using java here but I don't think the language is very important here):
public static int counter(String a){
int sum = 0;
//some code to iterate the string
//some code to check the conditions and if needed call the method
//some code to add the number of objects and arrays to sum
return sum;
}
If the code should like what I said then how can I fill the body?
Thank you for your time.
Depending how you design your recursive algorithm and size of input, you may run into the common problem of recursive stack overflow, where you have very deep recursion and run out of memory space
This is a different iterative pythonic solution if you do not have to use recursion but you should be able to transpose this to Java.
You want to increment you count for every item that is separated by commas. However, if that element has ']' characters, you know that it is a part of a embedded list. By counting the closing braces and the element, you can get the total.
Updated to handle strings with embedded commas
# Function for removing the chars between apostrophes
def remove(s,c):
while(s.find(c) != -1):
i = s.find(c) # find the first instance of c but ' or " in our case
i2 = s.find(c,i+1) # find the second instance
s = s[0:i]+s[i2+1:] # Remove the string
return s
return s
s = "[['a,b,c'],[1,2,3]]"
s = s[:-1] # remove the last list char
total = 0
s = remove(s,'\'')
s = remove(s,'"')
l = s.split(',')
for el in l:
total+=1
total+= el.count(']')
print(total)
Since you don't care about parsing the actual contents of the lists (for that you would implement a recursive descent parser), you can instead implement a simple state machine.
Here's a very rough, partial implementation in pseudo code just to give you some idea about how you might implement this. Ideally you would have more states to detect syntax errors:
int lists, elements = 0;
state = normal;
foreach (char c in input)
{
switch state
case normal:
if (c == '[')
lists++;
else if (c == ']')
// do nothing
else if (c == ',')
// do nothing (will only count [ and , on elements)
else if (c == '"')
elements++;
state = quoted_element
else
elements++;
state = element;
break;
case quoted_element:
if (c == '"')
state = element;
break;
case element:
if (c == '"' || c == '[')
exception("Syntax error");
else if (c == ",")
elements++;
else if (c == "]")
state = normal;
break;
}
Here's a recursion in JavaScript that might give you some ideas.
function f(s){
function nextIndexafterStr(i){
while (!(s[i] == "\"" && s[i-1] != "\\"))
i++;
return i + 1;
}
function nextIndexafterNum(i){
while (![",", "]"].includes(s[i]))
i++;
return i;
}
// Returns [numArrays, numElements, endIndex]
// Assumes valid input
function g(i, as, es){
// base case
if (s[i] == "]" || i == s.length)
return [as, es, i];
if (s[i] == ",")
return g(i + 1, as, es);
// a list
if (s[i] == "["){
const [aas, ees, endIndex] = g(i + 1, 0, 0);
return g(endIndex + 1, as + 1 + aas, es + ees);
}
// string element
if (s[i] == "\"")
return g(nextIndexafterStr(i + 1), as, es + 1);
// number or variable-name element
return g(nextIndexafterNum(i), as, es + 1);
}
const [as, es, _] = g(0, 0, 0);
return as + es;
}
var a = [12345,0.34,["af\"v",24]];
var b = "[[a,b,c],[[d]],[[e,f]],[g],h,i,[[j,[k,l]]]]";
a = JSON.stringify(a);
console.log(a);
console.log(f(a));
console.log(b);
console.log(f(b));
Related
I had this question on a midterm today and my brain completely melted and I had no clue how to write the pseudocode or even how to approach the problem. Any help would be appreciated.
This problem does not really call for a recursive solution, but if required, then use a divide-and-conquer approach: solve the problem for the left and right half of the array, then take the greatest of the two outcomes.
The recursion's base case occurs when the array has only one value: in that case verify whether it is odd. If so, return it, otherwise return some default value. I'll take minus infinity for that, meaning that if an array has no odd members, that will be the returned value.
Here is an implementation in JavaScript:
function greatestOdd(arr, first=0, last=arr.length-1) {
if (last == first) { // It's a single value
if (arr[first] % 2 == 1) return arr[first]; // Odd
else return -Infinity; // Even
}
let mid = (last + first) >> 1;
let a = greatestOdd(arr, first, mid);
let b = greatestOdd(arr, mid+1, last);
return Math.max(a, b);
}
console.log( greatestOdd([5,4,2,7,6,10]) ); // 7
You could simply traverse the array and get the largest odd number. Recursion is not needed but traversal can be done recursively like:
int findLargest(index, arr)
if ( index == arr.length - 1 )
if ( arr[index] % 2 != 0 ) return arr[index]
return MIN_VALUE
else
return arr[index] % 2 != 0 ? max(arr[index], findLargest(index + 1, arr))
: findLargest(index + 1, arr)
You visit each element once and time complexity is O(n) but this uses O(n) space and can lead to stackoverflow because intermediate results are needed on the stack for the final result.
For example:
max(arr[index], findLargest(index+1, arr)) is evaluated as:
max(arr[index], max(arr[index+1], findLargest(index+2, arr))) which is evaluated as :
max(arr[index], max(arr[index+1], max(arr[index+2], findLargest(index+3, arr))))
and so on...
The tail recursive version to avoid stack overflow:
int findLargestOdd(maxOdd, index, arr)
if ( index == arr.length-1) return maxOdd;
return arr[index+1] % 2 != 0
? return findLargestOdd(max(maxOdd, arr[index+1]), index+1, arr)
: return findLargestOdd(maxOdd, index+1, arr);
Here intermediate results needn't be stored on stack. You carry the result forward as : max(maxOdd, arr[index]) or maxOdd
You could call this function as :
return arr[0] % 2 != 0
? findLargestOdd(arr[0], 0, arr)
: findLargestOdd(MIN_VALUE, 0, arr)
I'm trying to write an algorithm for finding the index of the closest value that is lesser than or equal to the search value in a sorted array. In the example of the array [10, 20, 30], the following search values should output these indexes:
searchValue: 9, index: -1
searchValue: 10, index: 0
searchValue: 28, index: 1
searchValue: 55555, index: 2
I want to use binary search for logarithmic runtime. I have an algorithm in C-esque psuedocode, but it has 3 base cases. Can these 3 base cases be condensed into 1 for a more elegant solution?
int function indexOfClosestLesser(array, searchValue, startIndex, endIndex) {
if (startIndex == endIndex) {
if (searchValue >= array[startIndex]) {
return startIndex;
} else {
return -1;
}
}
// In the simplistic case of searching for 2 in [0, 2], the midIndex
// is always 0 due to int truncation. These checks are to avoid recursing
// infinitely from index 0 to index 1.
if (startIndex == endIndex - 1) {
if (searchValue >= array[endIndex]) {
return endIndex;
} else if (searchValue >= array[startIndex]) {
return startIndex;
} else {
return -1;
}
}
// In normal binary search, this would be the only base case
if (startIndex < endIndex) {
return -1;
}
int midIndex = endIndex / 2 + startIndex / 2;
int midValue = array[midIndex];
if (midValue > searchValue) {
return indexOfClosestLesser(array, searchValue, startIndex, midIndex - 1);
} else if (searchValue >= midValue) {
// Unlike normal binary search, we don't start on midIndex + 1.
// We're not sure whether the midValue can be excluded yet
return indexOfClosestLesser(array, searchValue, midIndex, endIndex);
}
}
Based on your recursive approach, I would suggest the following c++ snippet that reduces the number of different cases a bit:
int search(int *array, int start_idx, int end_idx, int search_val) {
if( start_idx == end_idx )
return array[start_idx] <= search_val ? start_idx : -1;
int mid_idx = start_idx + (end_idx - start_idx) / 2;
if( search_val < array[mid_idx] )
return search( array, start_idx, mid_idx, search_val );
int ret = search( array, mid_idx+1, end_idx, search_val );
return ret == -1 ? mid_idx : ret;
}
Basically it performs a normal binary search. It only differs in the return statement of the last case to fulfill the additional requirement.
Here is a short test program:
#include <iostream>
int main( int argc, char **argv ) {
int array[3] = { 10, 20, 30 };
std::cout << search( array, 0, 2, 9 ) << std::endl;
std::cout << search( array, 0, 2, 10 ) << std::endl;
std::cout << search( array, 0, 2, 28 ) << std::endl;
std::cout << search( array, 0, 2, 55555 ) << std::endl;
return 0;
}
The output is as desired:
-1
0
1
2
Frankly speaking, I find the logic of finding a number greater than a given number a lot easier than the logic needed to find numbers less than or equal to a given number. Obviously, the reason behind that is the extra logic (that forms the edge cases) required to handle the duplicate numbers (of given num) present in the array.
public int justGreater(int[] arr, int val, int s, int e){
// Returns the index of first element greater than val.
// If no such value is present, returns the size of the array.
if (s >= e){
return arr[s] <= N ? s+1 : s;
}
int mid = (s + e) >> 1;
if (arr[mid] < val) return justGreater(arr, val, mid+1, e);
return justGreater(arr, val, s, mid);
}
and then to find the index of the closest value that is lesser than or equal to the search value in a sorted array, just subtract the returned value by 1:
ans = justGreater(arr, val, 0, arr.length-1) - 1;
Trick
The trick here is to search for searchValue + 1 and return the the found index as index - 1 which is left - 1 in the code below
For example if we search for 9 in [10, 20, 30]. The code will look for 10 and return that it's present at 0th index and we return 0-1 which is -1
Similarly if we try to search for 10 in the above example it will search for 10 + 1 and return 1st index and we return 1-1 which is 0
Code
def binary_search(array, searchValue, startIndex=0, endIndex=2 ** 32):
"""
Binary search for the closest value less than or equal to the search value
:param array: The given sorted list
:param searchValue: Value to be found in the array
:param startIndex: Initialized with 0
:param endIndex: Initialized with 2**32
:return: Returns the index closest value less than or equal to the search value
"""
left = max(0, startIndex)
right = min(len(array), endIndex)
while left < right:
mid = (left + right) // 2
if array[mid] < searchValue + 1:
left = mid + 1
else:
right = mid
return left - 1
It can also be done in a single line with the standard library.
import bisect
def standard_binary_search(array, searchVal):
return bisect.bisect_left(array, searchVal + 1) - 1
Testing
Testing the test cases provided by OP
array = [10, 20, 30]
print(binary_search(array, 9))
print(binary_search(array, 10))
print(binary_search(array, 28))
print(binary_search(array, 5555))
Results
-1
0
1
2
I created a linear search to test the binary search.
def linear_search(array, searchVal):
ans = -1
for i, num in enumerate(array):
if num > searchVal:
return ans
ans = i
return ans
And a function to test all the binary search functions above.
Check for correctness
def check_correctness(array, searchVal):
assert binary_search(array, searchVal) == linear_search(array, searchVal)
assert binary_search(array, searchVal) == standard_binary_search(array, searchVal)
return binary_search(array, searchVal)
Driver Function
nums = sorted(
[460, 4557, 1872, 2698, 4411, 1730, 3870, 4941, 77, 7789, 8553, 6011, 9882, 9597, 8060, 1518, 8210, 380, 6822, 9022,
8255, 8977, 2492, 5918, 3710, 4253, 8386, 9660, 2933, 7880, 615, 1439, 9311, 3526, 5674, 1899, 1544, 235, 3369,
519, 8018, 8489, 3093, 2547, 4903, 1836, 2447, 570, 7666, 796, 7149, 9623, 681, 1869, 4381, 2711, 9882, 4348, 4617,
7852, 5897, 4135, 9471, 4202, 6630, 3037, 9694, 9693, 7779, 3041, 3160, 4911, 8022, 7909, 297, 7258, 4379, 3216,
9474, 8876, 6108, 7814, 9484, 2868, 882, 4206, 3986, 3038, 3659, 3287, 2152, 2964, 7057, 7122, 261, 2716, 4845,
3709, 3562, 1928]
)
for num in range(10002):
ans = check_correctness(nums, num)
if ans != -1:
print(num, nums[check_correctness(nums, num)])
The driver function ran without any assert errors. This proves the correctness of the above two functions.
Commented version in typescript. Based on this answer but modified to return less than or equal to.
/**
* Binary Search of a sorted array but returns the closest smaller value if the
* needle is not in the array.
*
* Returns null if the needle is not in the array and no smaller value is in
* the array.
*
* #param haystack the sorted array to search #param needle the need to search
* for in the haystack #param compareFn classical comparison function, return
* -1 if a is less than b, 0 if a is equal to b, and 1 if a is greater than b
*/
export function lessThanOrEqualBinarySearch<T>(
haystack: T[],
needle: T,
compareFn: (a: T, b: T) => number
): T | null {
let lo = 0;
let hi = haystack.length - 1;
let lowestFound: T | null = null;
// iteratively search halves of the array but when we search the larger
// half keep track of the largest value in the smaller half
while (lo <= hi) {
let mid = (hi + lo) >> 1;
let cmp = compareFn(needle, haystack[mid]);
// needle is smaller than middle
// search in the bottom half
if (cmp < 0) {
hi = mid - 1;
continue;
}
// needle is larger than middle
// search in the top half
else if (cmp > 0) {
lo = mid + 1;
lowestFound = haystack[mid];
} else if (cmp === 0) {
return haystack[mid];
}
}
return lowestFound;
}
Here's a PHP version, based on user0815's answer.
Adapted it to take a function, not just an array, and made it more efficient by avoiding evaluation of $mid_idx twice.
function binarySearchLessOrEqual($start_idx, $end_idx, $search_val, $valueFunction)
{
//N.B. If the start index is bigger or equal to the end index, we've reached the end!
if( $start_idx >= $end_idx )
{
return $valueFunction($end_idx) <= $search_val ? $end_idx : -1;
}
$mid_idx = intval($start_idx + ($end_idx - $start_idx) / 2);
if ( $valueFunction($mid_idx) > $search_val ) //If the function is too big, we search in the bottom half
{
return binarySearchLessOrEqual( $start_idx, $mid_idx-1, $search_val, $valueFunction);
}
else //If the function returns less than OR equal, we search in the top half
{
$ret = binarySearchLessOrEqual($mid_idx+1, $end_idx, $search_val, $valueFunction);
//If nothing is suitable, then $mid_idx was actually the best one!
return $ret == -1 ? $mid_idx : $ret;
}
}
Rather than taking an array, it takes a int-indexed function. You could easily adapt it to take an array instead, or simply use it as below:
function indexOfClosestLesser($array, $searchValue)
{
return binarySearchLessOrEqual(
0,
count($array)-1,
$searchValue,
function ($n) use ($array)
{
return $array[$n];
}
);
}
Tested:
$array = [ 10, 20, 30 ];
echo "0: " . indexOfClosestLesser($array, 0) . "<br>"; //-1
echo "5: " . indexOfClosestLesser($array, 5) . "<br>"; //-1
echo "10: " . indexOfClosestLesser($array, 10) . "<br>"; //0
echo "15: " . indexOfClosestLesser($array, 15) . "<br>"; //0
echo "20: " . indexOfClosestLesser($array, 20) . "<br>"; //1
echo "25: " . indexOfClosestLesser($array, 25) . "<br>"; //1
echo "30: " . indexOfClosestLesser($array, 30) . "<br>"; //2
echo "35: " . indexOfClosestLesser($array, 35) . "<br>"; //2
Try using a pair of global variables, then reference those variables inside the COMPARE function for bsearch
In RPGIV we can call c functions.
The compare function with global variables looks like this:
dcl-proc compInvHdr;
dcl-pi compInvHdr int(10);
elmPtr1 pointer value;
elmPtr2 pointer value;
end-pi;
dcl-ds elm1 based(elmPtr1) likeds(invHdr_t);
dcl-ds elm2 based(elmPtr2) likeds(elm1);
dcl-s low int(10) inz(-1);
dcl-s high int(10) inz(1);
dcl-s equal int(10) inz(0);
select;
when elm1.rcd.RECORDNO < elm2.rcd.RECORDNO;
lastHiPtr = elmPtr2;
return low;
when elm1.rcd.RECORDNO > elm2.rcd.RECORDNO;
lastLoPtr = elmPtr2;
return high;
other;
return equal;
endsl;
end-proc;
Remember, that in bsearch the first element is the search key and the second element is the actual storage element in your array/memory, that is why the COMPARE procedure is using elmPtr2;
the call to bsearch looks like this:
// lastLoPtr and LastHiPtr are global variables
// basePtr points to the beginning of the array
lastLoPtr = basePtr;
lastHiPtr = basePtr + ((numRec - 1) * sizRec));
searchKey = 'somevalue';
hitPtr = bsearch(%addr(searchkey)
:basePtr
:numRec
:sizRec
:%PADDR('COMPINVHDR'));
if hitPtr <> *null;
//? not found
hitPtr = lastLoPtr;
else;
//? found
endif;
So if the key is not found then the hitPtr is set to the key of the closest match, effectively archiving a "Less than or Equal key".
If you want the opposite, the next greater key. Then use lastHiPtr to reference the first key greater than the search key.
Note: protect the global variables against race conditions (if applicable).
Wanted to provide a non-binary search way of doing this, in C#. The following finds the closest value to X, without being greater than X, but it can be equal to X. My function also does not need the list to be sorted. It is also theoretically faster than O(n), but only in the event that the exact target number is found, in which case it terminates early and returns the integer.
public static int FindClosest(List<int> numbers, int target)
{
int current = 0;
int difference = Int32.MaxValue;
foreach(int integer in numbers)
{
if(integer == target)
{
return integer;
}
int diff = Math.Abs(target - integer);
if(integer <= target && integer >= current && diff < difference)
{
current = integer;
difference = diff;
}
}
return current;
}
I tested this with the following setup, and it appears to be working flawlessly:
List<int> values = new List<int>() {1,24,32,6,14,9,11,22 };
int target = 21;
int closest = FindClosest(values,target);
Console.WriteLine("Closest: " + closest);
7 years later, I hope to provide some intuition:
If search_val <= arr[mid], we know for the sure that the solution resides in the interval [lo, mid], inclusive. So, we set right=mid (we probably can set right=mid-1 if mid is not included). Note that if search_val < arr[mid], we in fact know that the solution resides in [lo, mid), mid not inclusive. This is because search_val won't fall back on mid and use mid as the closest value <= search value if it is less than arr[mid].
On the other hand, search_val >= arr[mid]. In this case, we know that the solution resides in [mid, hi]. In fact, even if search_val > arr[mid], the solution is still [mid, hi]. This means that we should set left = mid. HOWEVER, in binary search, left is usually always set to mid + 1 to avoid infinite loops. But this means, when the loops at left==right, it is possible we are 1 index over the solution. Thus, we do a check at the very end to return either the left or left-1, that you can see in the other solutions.
Practice Problem: Search a 2D Matrix
Write an efficient algorithm that searches for a value target in an m x n integer matrix matrix. This matrix has the following properties:
Integers in each row are sorted from left to right.
The first integer of each row is greater than the last integer of the
previous row.
The smart solution to this problem is to treat the two-dimensional array as an one-dimensional one and use regular binary search. But I wrote a solution that first locates the correct row. The process of finding the correct row in this problem is basically the same as finding the closest value less than equal to the search value.
Additionally link on binary search: Useful Insights into Binary Search
a non-recursive way using loop, I'm using this in javascript so I'll just post in javascript:
let left = 0
let right = array.length
let mid = 0
while (left < right) {
mid = Math.floor((left + right) / 2)
if (searchValue < array[mid]) {
right = mid
} else {
left = mid + 1
}
}
return left - 1
since general guideline tells us to look at the middle pointer, many fail to see that the actual answer is the left pointer's final value.
In order to find the minimal number of insertions required to convert a given string(s) to palindrome I find the longest common subsequence of the string(lcs_string) and its reverse. Therefore the number of insertions to be made is length(s) - length(lcs_string)
What method should be employed to find the equivalent palindrome string on knowing the number of insertions to be made?
For example :
1) azbzczdzez
Number of insertions required : 5
Palindrome string : azbzcezdzeczbza
Although multiple palindrome strings may exist for the same string but I want to find only one palindrome?
Let S[i, j] represents a sub-string of string S starting from index i and ending at index j (both inclusive) and c[i, j] be the optimal solution for S[i, j].
Obviously, c[i, j] = 0 if i >= j.
In general, we have the recurrence:
To elaborate on VenomFangs answer, there is a simple dynamic programming solution to this one. Note that I'm assuming the only operation allowed here is insertion of characters (no deletion, updates). Let S be a string of n characters. The simple recursion function P for this is:
= P [i+1 .. j-1], if S[i] = S[j]
P[i..j]
= min (P[i..j-1], P[i+1..j]) + 1,
If you'd like more explanation on why this is true, post a comment and i'd be happy to explain (though its pretty easy to see with a little thought). This, by the way, is the exact opposite of the LCS function you use, hence validating that your solution is in fact optimal. Of course its wholly possible I bungled, if so, someone do let me know!
Edit: To account for the palindrome itself, this can be easily done as follows:
As stated above, P[1..n] would give you the number of insertions required to make this string a palindrome. Once the above two-dimensional array is built up, here's how you find the palindrome:
Start with i=1, j=n. Now,
string output = "";
while(i < j)
{
if (P[i][j] == P[i+1][j-1]) //this happens if no insertions were made at this point
{
output = output + S[i];
i++;
j--;
}
else
if (P[i][j] == P[i+1][j]) //
{
output = output + S[i];
i++;
}
else
{
output = S[j] + output;
j--;
}
}
cout<<output<<reverse(output);
//You may have to be careful about odd sized palindromes here,
// I haven't accounted for that, it just needs one simple check
Does that make better reading?
The solution looks to be a dynamic programming solution.
You may be able to find your answer in the following post: How can I compute the number of characters required to turn a string into a palindrome?
PHP Solution of O(n)
function insertNode(&$arr, $idx, $val) {
$arr = array_merge(array_slice($arr, 0, $idx), array($val), array_slice($arr, $idx));
}
function createPalindrome($arr, $s, $e) {
$i = 0;
while(true) {
if($s >= $e) {
break;
} else if($arr[$s] == $arr[$e]) {
$s++; $e--; // shrink the queue from both sides
continue;
} else {
insertNode($arr, $s, $arr[$e]);
$s++;
}
}
echo implode("", $arr);
}
$arr = array('b', 'e', 'a', 'a', 'c', 'd', 'a', 'r', 'e');
echo createPalindrome ( $arr, 0, count ( $arr ) - 1 );
Simple. See below :)
String pattern = "abcdefghgf";
boolean isPalindrome = false;
int i=0,j=pattern.length()-1;
int mismatchCounter = 0;
while(i<=j)
{
//reverse matching
if(pattern.charAt(i)== pattern.charAt(j))
{
i++; j--;
isPalindrome = true;
continue;
}
else if(pattern.charAt(i)!= pattern.charAt(j))
{
i++;
mismatchCounter++;
}
}
System.out.println("The pattern string is :"+pattern);
System.out.println("Minimum number of characters required to make this string a palidnrome : "+mismatchCounter);
I recently came in contact with this interesting problem. You are given a string containing just the characters '(', ')', '{', '}', '[' and ']', for example, "[{()}]", you need to write a function which will check validity of such an input string, function may be like this:
bool isValid(char* s);
these brackets have to close in the correct order, for example "()" and "()[]{}" are all valid but "(]", "([)]" and "{{{{" are not!
I came out with following O(n) time and O(n) space complexity solution, which works fine:
Maintain a stack of characters.
Whenever you find opening braces '(', '{' OR '[' push it on the stack.
Whenever you find closing braces ')', '}' OR ']' , check if top of stack is corresponding opening bracket, if yes, then pop the stack, else break the loop and return false.
Repeat steps 2 - 3 until end of the string.
This works, but can we optimize it for space, may be constant extra space, I understand that time complexity cannot be less than O(n) as we have to look at every character.
So my question is can we solve this problem in O(1) space?
With reference to the excellent answer from Matthieu M., here is an implementation in C# that seems to work beautifully.
/// <summary>
/// Checks to see if brackets are well formed.
/// Passes "Valid parentheses" challenge on www.codeeval.com,
/// which is a programming challenge site much like www.projecteuler.net.
/// </summary>
/// <param name="input">Input string, consisting of nothing but various types of brackets.</param>
/// <returns>True if brackets are well formed, false if not.</returns>
static bool IsWellFormedBrackets(string input)
{
string previous = "";
while (input.Length != previous.Length)
{
previous = input;
input = input
.Replace("()", String.Empty)
.Replace("[]", String.Empty)
.Replace("{}", String.Empty);
}
return (input.Length == 0);
}
Essentially, all it does is remove pairs of brackets until there are none left to remove; if there is anything left the brackets are not well formed.
Examples of well formed brackets:
()[]
{()[]}
Example of malformed brackets:
([)]
{()[}]
Actually, there's a deterministic log-space algorithm due to Ritchie and Springsteel: http://dx.doi.org/10.1016/S0019-9958(72)90205-7 (paywalled, sorry not online). Since we need log bits to index the string, this is space-optimal.
If you're willing to accept one-sided error, then there's an algorithm that uses n polylog(n) time and polylog(n) space: http://www.eccc.uni-trier.de/report/2009/119/
If the input is read-only, I don't think we can do O(1) space. It is a well known fact that any O(1) space decidable language is regular (i.e writeable as a regular expression). The set of strings you have is not a regular language.
Of course, this is about a Turing Machine. I would expect it to be true for fixed word RAM machines too.
Edit: Although simple, this algorithm is actually O(n^2) in terms of character comparisons. To demonstrate it, one can simply generate a string as '(' * n + ')' * n.
I have a simple, though perhaps erroneous idea, that I will submit to your criticisms.
It's a destructive algorithm, which means that if you ever need the string it would not help (since you would need to copy it down).
Otherwise, the algorithm work with a simple index within the current string.
The idea is to remove pairs one after the others:
([{}()])
([()])
([])
()
empty -> OK
It is based on the simple fact that if we have matching pairs, then at least one is of the form () without any pair character in between.
Algorithm:
i := 0
Find a matching pair from i. If none is found, then the string is not valid. If one is found, let i be the index of the first character.
Remove [i:i+1] from the string
If i is at the end of the string, and the string is not empty, it's a failure.
If [i-1:i] is a matching pair, i := i-1 and back to 3.
Else, back to 1.
The algorithm is O(n) in complexity because:
each iteration of the loop removes 2 characters from the string
the step 2., which is linear, is naturally bound (i cannot grow indefinitely)
And it's O(1) in space because only the index is required.
Of course, if you can't afford to destroy the string, then you'll have to copy it, and that's O(n) in space so no real benefit there!
Unless, of course, I am deeply mistaken somewhere... and perhaps someone could use the original idea (there is a pair somewhere) to better effect.
I doubt you'll find a better solution, since even if you use internal functions to regexp or count occurrences, they still have a O(...) cost. I'd say your solution is the best :)
To optimize for space you could do some run-length encoding on your stack, but I doubt it would gain you very much, except in cases like {{{{{{{{{{}}}}}}}}}}.
http://www.sureinterview.com/shwqst/112007
It is natural to solve this problem with a stack.
If only '(' and ')' are used, the stack is not necessary. We just need to maintain a counter for the unmatched left '('. The expression is valid if the counter is always non-negative during the match and is zero at the end.
In general case, although the stack is still necessary, the depth of the stack can be reduced by using a counter for unmatched braces.
This is an working java code where I filter out the brackets from the string expression and then check the well formedness by replacing wellformed braces by nulls
Sample input = (a+{b+c}-[d-e])+[f]-[g] FilterBrackets will output = ({}[])[][] Then I check for wellformedness.
Comments welcome.
public class ParanString {
public static void main(String[] args) {
String s = FilterBrackets("(a+{b+c}-[d-e])[][]");
while ((s.length()!=0) && (s.contains("[]")||s.contains("()")||s.contains("{}")))
{
//System.out.println(s.length());
//System.out.println(s);
s = s.replace("[]", "");
s = s.replace("()", "");
s = s.replace("{}", "");
}
if(s.length()==0)
{
System.out.println("Well Formed");
}
else
{
System.out.println("Not Well Formed");
}
}
public static String FilterBrackets(String str)
{
int len=str.length();
char arr[] = str.toCharArray();
String filter = "";
for (int i = 0; i < len; i++)
{
if ((arr[i]=='(') || (arr[i]==')') || (arr[i]=='[') || (arr[i]==']') || (arr[i]=='{') || (arr[i]=='}'))
{
filter=filter+arr[i];
}
}
return filter;
}
}
The following modification of Sbusidan's answer is O(n2) time complex but O(log n) space simple.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
char opposite(char bracket) {
switch(bracket) {
case '[':
return ']';
case '(':
return ')';
}
}
bool is_balanced(int length, char *s) {
int depth, target_depth, index;
char target_bracket;
if(length % 2 != 0) {
return false;
}
for(target_depth = length/2; target_depth > 0; target_depth--) {
depth=0;
for(index = 0; index < length; index++) {
switch(s[index]) {
case '(':
case '[':
depth++;
if(depth == target_depth) target_bracket = opposite(s[index]);
break;
case ')':
case ']':
if(depth == 0) return false;
if(depth == target_depth && s[index] != target_bracket) return false;
depth--;
break;
}
}
}
}
void main(char* argv[]) {
char input[] = "([)[(])]";
char *balanced = is_balanced(strlen(input), input) ? "balanced" : "imbalanced";
printf("%s is %s.\n", input, balanced);
}
If you can overwrite the input string (not reasonable in the use cases I envision, but what the heck...) you can do it in constant space, though I believe the time requirement goes up to O(n2).
Like this:
string s = input
char c = null
int i=0
do
if s[i] isAOpenChar()
c = s[i]
else if
c = isACloseChar()
if closeMatchesOpen(s[i],c)
erase s[i]
while s[--i] != c ;
erase s[i]
c == null
i = 0; // Not optimal! It would be better to back up until you find an opening character
else
return fail
end if
while (s[++i] != EOS)
if c==null
return pass
else
return fail
The essence of this is to use the early part of the input as the stack.
I know I'm a little late to this party; it's also my very first post on StackOverflow.
But when I looked through the answers, I thought I might be able to come up with a better solution.
So my solution is to use a few pointers.
It doesn't even have to use any RAM storage, as registers can be used for this.
I have not tested the code; it's written it on the fly.
You'll need to fix my typos, and debug it, but I believe you'll get the idea.
Memory usage: Only the CPU registers in most cases.
CPU usage: It depends, but approximately twice the time it takes to read the string.
Modifies memory: No.
b: string beginning, e: string end.
l: left position, r: right position.
c: char, m: match char
if r reaches the end of the string, we have a success.
l goes backwards from r towards b.
Whenever r meets a new start kind, set l = r.
when l reaches b, we're done with the block; jump to beginning of next block.
const char *chk(const char *b, int len) /* option 2: remove int len */
{
char c, m;
const char *l, *r;
e = &b[len]; /* option 2: remove. */
l = b;
r = b;
while(r < e) /* option 2: change to while(1) */
{
c = *r++;
/* option 2: if(0 == c) break; */
if('(' == c || '{' == c || '[' == c)
{
l = r;
}
else if(')' == c || ']' == c || '}' == c)
{
/* find 'previous' starting brace */
m = 0;
while(l > b && '(' != m && '[' != m && '{' != m)
{
m = *--l;
}
/* now check if we have the correct one: */
if(((m & 1) + 1 + m) != c) /* cryptic: convert starting kind to ending kind and match with c */
{
return(r - 1); /* point to error */
}
if(l <= b) /* did we reach the beginning of this block ? */
{
b = r; /* set new beginning to 'head' */
l = b; /* obsolete: make left is in range. */
}
}
}
m = 0;
while(l > b && '(' != m && '[' != m && '{' != m)
{
m = *--l;
}
return(m ? l : NULL); /* NULL-pointer for OK */
}
After thinking about this approach for a while, I realized that it will not work as it is right now.
The problem will be that if you have "[()()]", it'll fail when reaching the ']'.
But instead of deleting the proposed solution, I'll leave it here, as it's actually not impossible to make it work, it does require some modification, though.
/**
*
* #author madhusudan
*/
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new Main().validateBraces("()()()()(((((())))))()()()()()()()()");
// TODO code application logic here
}
/**
* #Use this method to validate braces
*/
public void validateBraces(String teststr)
{
StringBuffer teststr1=new StringBuffer(teststr);
int ind=-1;
for(int i=0;i<teststr1.length();)
{
if(teststr1.length()<1)
break;
char ch=teststr1.charAt(0);
if(isClose(ch))
break;
else if(isOpen(ch))
{
ind=teststr1.indexOf(")", i);
if(ind==-1)
break;
teststr1=teststr1.deleteCharAt(ind).deleteCharAt(i);
}
else if(isClose(ch))
{
teststr1=deleteOpenBraces(teststr1,0,i);
}
}
if(teststr1.length()>0)
{
System.out.println("Invalid");
}else
{
System.out.println("Valid");
}
}
public boolean isOpen(char ch)
{
if("(".equals(Character.toString(ch)))
{
return true;
}else
return false;
}
public boolean isClose(char ch)
{
if(")".equals(Character.toString(ch)))
{
return true;
}else
return false;
}
public StringBuffer deleteOpenBraces(StringBuffer str,int start,int end)
{
char ar[]=str.toString().toCharArray();
for(int i=start;i<end;i++)
{
if("(".equals(ar[i]))
str=str.deleteCharAt(i).deleteCharAt(end);
break;
}
return str;
}
}
Instead of putting braces into the stack, you could use two pointers to check the characters of the string. one start from the beginning of the string and the other start from end of the string. something like
bool isValid(char* s) {
start = find_first_brace(s);
end = find_last_brace(s);
while (start <= end) {
if (!IsPair(start,end)) return false;
// move the pointer forward until reach a brace
start = find_next_brace(start);
// move the pointer backward until reach a brace
end = find_prev_brace(end);
}
return true;
}
Note that there are some corner case not handled.
I think that you can implement an O(n) algorithm. Simply you have to initialise an counter variable for each type: curly, square and normal brackets. After than you should iterate the string and should increase the coresponding counter if the bracket is opened, otherwise to decrease it. If the counter is negative return false. AfterI think that you can implement an O(n) algorithm. Simply you have to initialise an counter variable for each type: curly, square and normal brackets. After than you should iterate the string and should increase the coresponding counter if the bracket is opened, otherwise to decrease it. If the counter is negative return false. After you count all brackets, you should check if all counters are zero. In that case, the string is valid and you should return true.
You could provide the value and check if its a valid one, it would print YES otherwise it would print NO
static void Main(string[] args)
{
string value = "(((([{[(}]}]))))";
List<string> jj = new List<string>();
if (!(value.Length % 2 == 0))
{
Console.WriteLine("NO");
}
else
{
bool isValid = true;
List<string> items = new List<string>();
for (int i = 0; i < value.Length; i++)
{
string item = value.Substring(i, 1);
if (item == "(" || item == "{" || item == "[")
{
items.Add(item);
}
else
{
string openItem = items[items.Count - 1];
if (((item == ")" && openItem == "(")) || (item == "}" && openItem == "{") || (item == "]" && openItem == "["))
{
items.RemoveAt(items.Count - 1);
}
else
{
isValid = false;
break;
}
}
}
if (isValid)
{
Console.WriteLine("Yes");
}
else
{
Console.WriteLine("NO");
}
}
Console.ReadKey();
}
var verify = function(text)
{
var symbolsArray = ['[]', '()', '<>'];
var symbolReg = function(n)
{
var reg = [];
for (var i = 0; i < symbolsArray.length; i++) {
reg.push('\\' + symbolsArray[i][n]);
}
return new RegExp('(' + reg.join('|') + ')','g');
};
// openReg matches '(', '[' and '<' and return true or false
var openReg = symbolReg(0);
// closeReg matches ')', ']' and '>' and return true or false
var closeReg = symbolReg(1);
// nestTest matches openSymbol+anyChar+closeSymbol
// and returns an obj with the match str and it's start index
var nestTest = function(symbols, text)
{
var open = symbols[0]
, close = symbols[1]
, reg = new RegExp('(\\' + open + ')([\\s\\S])*(\\' + close + ')','g')
, test = reg.exec(text);
if (test) return {
start: test.index,
str: test[0]
};
else return false;
};
var recursiveCheck = function(text)
{
var i, nestTests = [], test, symbols;
// nestTest with each symbol
for (i = 0; i < symbolsArray.length; i++)
{
symbols = symbolsArray[i];
test = nestTest(symbols, text);
if (test) nestTests.push(test);
}
// sort tests by start index
nestTests.sort(function(a, b)
{
return a.start - b.start;
});
if (nestTests.length)
{
// build nest data: calculate match end index
for (i = 0; i < nestTests.length; i++)
{
test = nestTests[i];
var end = test.start + ( (test.str) ? test.str.length : 0 );
nestTests[i].end = end;
var last = (nestTests[i + 1]) ? nestTests[i + 1].index : text.length;
nestTests[i].pos = text.substring(end, last);
}
for (i = 0; i < nestTests.length; i++)
{
test = nestTests[i];
// recursive checks what's after the nest
if (test.pos.length && !recursiveCheck(test.pos)) return false;
// recursive checks what's in the nest
if (test.str.length) {
test.str = test.str.substring(1, test.str.length - 1);
return recursiveCheck(test.str);
} else return true;
}
} else {
// if no nests then check for orphan symbols
var closeTest = closeReg.test(text);
var openTest = openReg.test(text);
return !(closeTest || openTest);
}
};
return recursiveCheck(text);
};
Using c# OOPS programming... Small and simple solution
Console.WriteLine("Enter the string");
string str = Console.ReadLine();
int length = str.Length;
if (length % 2 == 0)
{
while (length > 0 && str.Length > 0)
{
for (int i = 0; i < str.Length; i++)
{
if (i + 1 < str.Length)
{
switch (str[i])
{
case '{':
if (str[i + 1] == '}')
str = str.Remove(i, 2);
break;
case '(':
if (str[i + 1] == ')')
str = str.Remove(i, 2);
break;
case '[':
if (str[i + 1] == ']')
str = str.Remove(i, 2);
break;
}
}
}
length--;
}
if(str.Length > 0)
Console.WriteLine("Invalid input");
else
Console.WriteLine("Valid input");
}
else
Console.WriteLine("Invalid input");
Console.ReadKey();
This is my solution to the problem.
O(n) is the complexity of time without complexity of space.
Code in C.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool checkBraket(char *s)
{
int curly = 0, rounded = 0, squre = 0;
int i = 0;
char ch = s[0];
while (ch != '\0')
{
if (ch == '{') curly++;
if (ch == '}') {
if (curly == 0) {
return false;
} else {
curly--; }
}
if (ch == '[') squre++;
if (ch == ']') {
if (squre == 0) {
return false;
} else {
squre--;
}
}
if (ch == '(') rounded++;
if (ch == ')') {
if (rounded == 0) {
return false;
} else {
rounded--;
}
}
i++;
ch = s[i];
}
if (curly == 0 && rounded == 0 && squre == 0){
return true;
}
else {
return false;
}
}
void main()
{
char mystring[] = "{{{{{[(())}}]}}}";
int answer = checkBraket(mystring);
printf("my answer is %d\n", answer);
return;
}
I recently found a contest problem that asks you to compute the minimum number of characters that must be inserted (anywhere) in a string to turn it into a palindrome.
For example, given the string: "abcbd" we can turn it into a palindrome by inserting just two characters: one after "a" and another after "d": "adbcbda".
This seems to be a generalization of a similar problem that asks for the same thing, except characters can only be added at the end - this has a pretty simple solution in O(N) using hash tables.
I have been trying to modify the Levenshtein distance algorithm to solve this problem, but haven't been successful. Any help on how to solve this (it doesn't necessarily have to be efficient, I'm just interested in any DP solution) would be appreciated.
Note: This is just a curiosity. Dav proposed an algorithm which can be modified to DP algorithm to run in O(n^2) time and O(n^2) space easily (and perhaps O(n) with better bookkeeping).
Of course, this 'naive' algorithm might actually come in handy if you decide to change the allowed operations.
Here is a 'naive'ish algorithm, which can probably be made faster with clever bookkeeping.
Given a string, we guess the middle of the resulting palindrome and then try to compute the number of inserts required to make the string a palindrome around that middle.
If the string is of length n, there are 2n+1 possible middles (Each character, between two characters, just before and just after the string).
Suppose we consider a middle which gives us two strings L and R (one to left and one to right).
If we are using inserts, I believe the Longest Common Subsequence algorithm (which is a DP algorithm) can now be used the create a 'super' string which contains both L and reverse of R, see Shortest common supersequence.
Pick the middle which gives you the smallest number inserts.
This is O(n^3) I believe. (Note: I haven't tried proving that it is true).
My C# solution looks for repeated characters in a string and uses them to reduce the number of insertions. In a word like program, I use the 'r' characters as a boundary. Inside of the 'r's, I make that a palindrome (recursively). Outside of the 'r's, I mirror the characters on the left and the right.
Some inputs have more than one shortest output: output can be toutptuot or outuputuo. My solution only selects one of the possibilities.
Some example runs:
radar -> radar, 0 insertions
esystem -> metsystem, 2 insertions
message -> megassagem, 3 insertions
stackexchange -> stegnahckexekchangets, 8 insertions
First I need to check if an input is already a palindrome:
public static bool IsPalindrome(string str)
{
for (int left = 0, right = str.Length - 1; left < right; left++, right--)
{
if (str[left] != str[right])
return false;
}
return true;
}
Then I need to find any repeated characters in the input. There may be more than one. The word message has two most-repeated characters ('e' and 's'):
private static bool TryFindMostRepeatedChar(string str, out List<char> chs)
{
chs = new List<char>();
int maxCount = 1;
var dict = new Dictionary<char, int>();
foreach (var item in str)
{
int temp;
if (dict.TryGetValue(item, out temp))
{
dict[item] = temp + 1;
maxCount = temp + 1;
}
else
dict.Add(item, 1);
}
foreach (var item in dict)
{
if (item.Value == maxCount)
chs.Add(item.Key);
}
return maxCount > 1;
}
My algorithm is here:
public static string MakePalindrome(string str)
{
List<char> repeatedList;
if (string.IsNullOrWhiteSpace(str) || IsPalindrome(str))
{
return str;
}
//If an input has repeated characters,
// use them to reduce the number of insertions
else if (TryFindMostRepeatedChar(str, out repeatedList))
{
string shortestResult = null;
foreach (var ch in repeatedList) //"program" -> { 'r' }
{
//find boundaries
int iLeft = str.IndexOf(ch); // "program" -> 1
int iRight = str.LastIndexOf(ch); // "program" -> 4
//make a palindrome of the inside chars
string inside = str.Substring(iLeft + 1, iRight - iLeft - 1); // "program" -> "og"
string insidePal = MakePalindrome(inside); // "og" -> "ogo"
string right = str.Substring(iRight + 1); // "program" -> "am"
string rightRev = Reverse(right); // "program" -> "ma"
string left = str.Substring(0, iLeft); // "program" -> "p"
string leftRev = Reverse(left); // "p" -> "p"
//Shave off extra chars in rightRev and leftRev
// When input = "message", this loop converts "meegassageem" to "megassagem",
// ("ee" to "e"), as long as the extra 'e' is an inserted char
while (left.Length > 0 && rightRev.Length > 0 &&
left[left.Length - 1] == rightRev[0])
{
rightRev = rightRev.Substring(1);
leftRev = leftRev.Substring(1);
}
//piece together the result
string result = left + rightRev + ch + insidePal + ch + right + leftRev;
//find the shortest result for inputs that have multiple repeated characters
if (shortestResult == null || result.Length < shortestResult.Length)
shortestResult = result;
}
return shortestResult;
}
else
{
//For inputs that have no repeated characters,
// just mirror the characters using the last character as the pivot.
for (int i = str.Length - 2; i >= 0; i--)
{
str += str[i];
}
return str;
}
}
Note that you need a Reverse function:
public static string Reverse(string str)
{
string result = "";
for (int i = str.Length - 1; i >= 0; i--)
{
result += str[i];
}
return result;
}
C# Recursive solution adding to the end of the string:
There are 2 base cases. When length is 1 or 2. Recursive case: If the extremes are equal, then
make palindrome the inner string without the extremes and return that with the extremes.
If the extremes are not equal, then add the first character to the end and make palindrome the
inner string including the previous last character. return that.
public static string ConvertToPalindrome(string str) // By only adding characters at the end
{
if (str.Length == 1) return str; // base case 1
if (str.Length == 2 && str[0] == str[1]) return str; // base case 2
else
{
if (str[0] == str[str.Length - 1]) // keep the extremes and call
return str[0] + ConvertToPalindrome(str.Substring(1, str.Length - 2)) + str[str.Length - 1];
else //Add the first character at the end and call
return str[0] + ConvertToPalindrome(str.Substring(1, str.Length - 1)) + str[0];
}
}