Formal Language: check language with one stack and one queue - data-structures

Write a pseudo code of method isL(w) which checks if the string w is an element of L using only 1 stack and 1 queue
L = {a^n⋅b^n⋅c^m⋅d^m | n≥1, m≥1} U {a^n⋅b^m⋅c^m⋅d^n | n≥1, m≥1}
(a^n is n-th power of a)
You can suppose that stack and queue is already implemented and use them with the variable stack and queue.
My code answering only half of this question is:
isL(w) {
for (each char ch in w) {
if (ch == 'a' || ch == 'c') {
stack.push( ch );
}
else if (ch == 'b' || ch == 'd') {
queue.enqueue( ch );
}
else return false; // no other letter than a,b,c,d
}
while (!queue.isEmpty()) {
if (stack.pop() == 'c' && queue.dequeue() == 'b')
continue;
else if (stack.pop() == 'a' && queue.dequeue() == 'd')
continue;
else
return false;
}
return true;
}
Though I targeted latter subset, it's still wrong for the latter too.
How do I implement the full answer that also checks the former subset?

isL(w) {
if (w[0] != 'a') return false
stack.push('a')
for ch in w{
if (!stack.isEmpty()) {
if (ch == 'a') stack.push(ch)
else if (ch == 'b') stack.pop()
else return false
}
else {
if (ch == 'c') queue.push(ch)
else if (!queue.isEmpty() && ch == 'd') queue.dequeue()
else return false
}
}
return true
}

Related

Combine different sort in Go

How can I combine sorters in Go? For example first I need sort by number of comments but if number of comments is null I need sort alphabetically.
This is what I have tried.
func sortArticles(articles []*Article) []*Article {
topArticlesSlice := make([]*Article, 0)
topArticlesSlice = append(topArticlesSlice, articles[:]...)
sort.SliceStable(topArticlesSlice, func(i, j int) bool {
var sortedByNumComments, areNumCommentsEquals, sortedByName bool
if topArticlesSlice[i].NumComments != nil && topArticlesSlice[j].NumComments != nil {
areNumCommentsEquals = *topArticlesSlice[i].NumComments == *topArticlesSlice[j].NumComments
sortedByNumComments = *topArticlesSlice[i].NumComments > *topArticlesSlice[j].NumComments
}
if areNumCommentsEquals {
if topArticlesSlice[i].Title != nil && topArticlesSlice[j].Title != nil {
sortedByName = *topArticlesSlice[i].Title == *topArticlesSlice[j].Title
return sortedByName
} else if topArticlesSlice[i].StoryTitle != nil && topArticlesSlice[j].StoryTitle != nil {
sortedByName = *topArticlesSlice[i].StoryTitle == *topArticlesSlice[j].StoryTitle
return sortedByName
}
return false
}
return sortedByNumComments
})
return topArticlesSlice
}
My structs (https://go.dev/play/p/27j-sFKaG2M)
type ArticleResponse struct {
Page int `json:"page"`
PerPage int `json:"per_page"`
Total int `json:"total"`
TotalPages int `json:"total_pages"`
Articles []*Article `json:"data"`
}
type Article struct {
Title *string `json:"title"`
URL *string `json:"url"`
Author string `json:"author"`
NumComments *int `json:"num_comments"`
StoryID interface{} `json:"story_id"`
StoryTitle *string `json:"story_title"`
StoryURL *string `json:"story_url"`
ParentID *int `json:"parent_id"`
CreatedAt int `json:"created_at"`
}
Your compare function is far too complex. You need to refactor it into simpler more straightforward bits.
And, you haven't defined what your Article type looks like, so, for the purposes of example, I'm going to define it thus:
type Article struct {
NumComments *int
Title *string
}
Your basic ask is that you want to sort, first by the number of comments, and then (if the number of comments is nil) alphabetically by title, correct?
From your original code, it would appear that
NumComments is a pointer to int (*int), and
Title is a pointer to string (*string)
That means that each comparison has four cases that have to be dealt with:
X
Y
Action
non-nil
non-nil
Compare x and y (according to their underlying type)
non-nil
nil
How does nil compare with non-nil? (implementation detail)
nil
non-nil
How does nil compare with non-nil? (implementation detail)
nil
nil
two nils compare equal for the purposes of collation
For the purposes of this exercise, I'm going to declare that nil collates high with respect to non-nil (but nil collating low with respect to non-nil is equally valid. An implementation choice).
Comparing 2 *int values is easy:
func compareIntPtr(x *int, y *int) int {
var cc int
switch {
case x != nil && y != nil: cc = sign(*x - *y)
case x == nil && y == nil: cc = 0
case x == nil && y != nil: cc = +1
case x != nil && y == nil: cc = -1
}
return cc
}
func sign(n int) int {
var sign int
switch {
case n < 0: sign = -1
case n > 0: sign = +1
default: sign = 0
}
return sign
}
As is comparing two *string values:
import "strings"
.
.
.
func compareStringPtr(x *string, y *string) int {
var cc int
switch {
case x != nil && y != nil: cc = strings.Compare(*x, *y)
case x == nil && y == nil: cc = 0
case x == nil && y != nil: cc = +1
case x != nil && y == nil: cc = -1
}
return cc
}
Once you have those primitives, the comparer function for the sort is even simpler:
func sortArticles(articles []*Article) []*Article {
topArticlesSlice := make([]*Article, 0)
topArticlesSlice = append(topArticlesSlice, articles[:]...)
sort.SliceStable(topArticlesSlice, func(i, j int) bool {
x := *topArticlesSlice[i]
y := *topArticlesSlice[j]
// compare numbers of comments
cc := compareIntPtr(x.NumComments, y.NumComments)
// if equal, compare the titles
if cc == 0 {
cc = compareStringPtr(x.Title, y.Title)
}
// return `true` if `x` collates less than `y`, otherwise `false`
return cc < 0
})
return topArticlesSlice
}
package main
import (
"fmt"
"sort"
)
type Article struct {
Title string
NumComments int
}
func main() {
a1 := Article{"Dog", 3}
a2 := Article{"Tiger", 0}
a3 := Article{"Cat", 4}
a4 := Article{"Fish", 0}
a5 := Article{"Whale", 8}
articles := []Article{a1, a2, a3, a4, a5}
sort.Slice(articles, func(i, j int) bool {
if articles[i].NumComments == 0 && articles[j].NumComments == 0 {
return articles[i].Title < articles[j].Title
} else {
return articles[i].NumComments < articles[j].NumComments
}
})
fmt.Printf("articles: %v\n", articles)
}
Some of the type definitions are missing in your post. I have taken a simple strut example. I think this is what you may be looking for?
Assuming I'm understanding your requirement correctly you can use something like the following:
func sortArticles(articles []*Article) []*Article {
topArticlesSlice := append([]*Article{}, articles[:]...)
sort.SliceStable(topArticlesSlice, func(i, j int) bool {
if topArticlesSlice[i].NumComments != nil && topArticlesSlice[j].NumComments != nil &&
*topArticlesSlice[i].NumComments != *topArticlesSlice[j].NumComments {
return *topArticlesSlice[i].NumComments < *topArticlesSlice[j].NumComments
}
if topArticlesSlice[i].Title != nil && topArticlesSlice[j].Title != nil &&
*topArticlesSlice[i].Title != *topArticlesSlice[j].Title {
return *topArticlesSlice[i].Title < *topArticlesSlice[j].Title
} else if topArticlesSlice[i].StoryTitle != nil && topArticlesSlice[j].StoryTitle != nil {
return *topArticlesSlice[i].StoryTitle < *topArticlesSlice[j].StoryTitle
}
return false
})
return topArticlesSlice
}
Try this in the playground.

What would be the time complexity of Search Range problem solution DnC

I would appreciate some help in figuring out the time complexity of the solution for Search Range problem from leetcode which involves recursion and DnC algorithm.
I am not sure whether it is O(N) or O(NlogN) and why?
func searchRange(nums []int, target int) []int {
if (len(nums) == 0) {
return []int{-1, -1}
}
return helper(nums, target, 0, len(nums) - 1)
}
func helper(nums []int, target, start, end int) []int {
res := []int {-1, -1}
if (nums[start] > target || nums[end] < target || start > end || (start == end && nums[start] != target)) {
return res
}
if (start == end) {
res[0] = start
res[1] = end
return res
}
mid := (start + end) / 2
res1 := helper(nums, target, start, mid)
res2 := helper(nums, target, mid + 1, end)
if (res1[0] == -1) {
return res2
}
if (res2[0] == -1) {
return res1
}
res[0] = res1[0]
res[1] = res2[1]
return res
}

build Calculator with recursive and stack , always got wrong result with parentheses ‘()’,what`s wrong

leetcode-244
Given a string s representing an expression, implement a basic calculator to evaluate it.
s consists of digits, '+', '-', '(', ')', and ' '
I build the calculator with recursive and stack. However, always got wrong result with parentheses ‘()’
what`s wrong with my code in helper func
func calculate(s string) int {
if len(s) == 0 {
return 0
}
return helper(s)
}
func helper(s string) int {
stack := make([]int, 0)
num := 0
sign := '+'
for len(s) > 0 {
c := s[0]
s = s[1:]
fmt.Println("======出栈======", string(c))
if c == '(' {
num = helper(s)
}
if (!isdigit(c) && c != ' ') || len(s) == 0 {
switch sign {
case '-':
// fmt.Println("======减法=======", sign)
stack = append(stack, -num)
case '+':
stack = append(stack, num)
case '*':
pre := stack[len(stack)-1] // top
stack = stack[:len(stack)-1] // pop
stack = append(stack, num*pre)
case '/':
pre := stack[len(stack)-1]
stack = stack[:len(stack)-1]
stack = append(stack, num/pre)
}
if c == ')' {
break
}
sign, _ = utf8.DecodeRune([]byte{c})
// fmt.Println(sign, c)
num = 0
}
if isdigit(c) {
num = num*10 + int(c-'0')
}
}
fmt.Println(stack)
return sum(stack)
}
func main() {
// wrong case as follows
// fmt.Println(calculate("1+(4+5+2) - 3"))
// fmt.Println(calculate("(1+(4+5+2)-3)+(6+8)"))
// fmt.Println(calculate(" ( 5*(4-2)+1-6)/5*2 "))
fmt.Println(calculate(" (12-1) + 12 "))
}
func sum(stack []int) int {
res := 0
for i := 0; i < len(stack); i++ {
res += stack[i]
}
return res
}
func isdigit(char byte) bool {
// char >= 48 && char <= 57
return char >= '0' && char <= '9'
}
Issue is appearing like you are not keeping the reference of operator before (.
For e.g.
2-(2+2)
So, it appearing that you have calculated (2+2) correctly but have not push "-4" is stack.

Non-concurrent O(1) space solution for Leaf-Similar Trees Leetcode Problem

I am trying to solve Leaf-Similar Trees problem on leetcode.com with O(1) space without concurrency/goroutines.
Iterative solution needs a stack for storing nodes, and a recursive one needs memory for function calls.
However, with the help of the Morris Traversal algorithm, I was able to traverse each tree with O(1) memory (which was tricky btw, as it is non-trivial to detect leafs with this algorithm).
Now I have a problem of how to traverse both trees and compare that 1) they have the same number of leafs and 2) in the same order.
The obvious way is to store both sequences of leafs in arrays/slices and then compare those. However, it ruins the O(1) memory. I can also store the first tree sequence in an array, and yield the values from the second tree one by one, comparing them to the values in an array, but it still violates O(1).
So I cheated by using goroutines to send the values from both Morris traversals, effectively creating no intermediate arrays and achieving O(1) space.
Now I am trying to make this solution more generic by not using goroutines or any other concurrency techniques. It must be a sequential solution.
Alternatively, I have suspicion that it is not possible to make this work without concurrency, please confirm if it is true.
Here is my solution:
func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool {
getLeafs := func(node *TreeNode, ch chan int) {
var pre *TreeNode // predecessor of the current node
curr := node
for curr != nil {
if curr.Left == nil {
if curr.Right == nil {
ch <- curr.Val
}
curr = curr.Right
continue
}
// curr.Right != nil
pre = curr.Left
for pre.Right != nil && pre.Right != curr {
pre = pre.Right
}
if pre.Right == nil {
pre.Right = curr
curr = curr.Left
continue
}
// pre.Right == curr
pre.Right = nil
if pre.Left == nil { // tricky! not using curr, but pre
ch <- pre.Val
}
curr = curr.Right
}
close(ch)
}
ch1 := make(chan int)
ch2 := make(chan int)
go getLeafs(root1, ch1)
go getLeafs(root2, ch2)
similar := true
for {
val1, ok1 := <-ch1
val2, ok2 := <-ch2
if val1 != val2 || ok1 != ok2 {
similar = false
}
if ok1 == false && ok2 == false {
break
}
}
return similar
}
I think it can work without concurrency, and still fit within your criteria. It's not pretty but it seems to work...
func leafSimilarNoConcurrency(root1 *TreeNode, root2 *TreeNode) bool {
if root1 == root2 {
return true
}
getLeafs := func(curr *TreeNode, pre *TreeNode) (int, *TreeNode, *TreeNode, bool) {
for curr != nil {
if curr.Left == nil {
if curr.Right == nil {
//ch <- curr.Val
return curr.Val, curr.Right, pre, true
}
curr = curr.Right
continue
}
// curr.Right != nil
pre = curr.Left
for pre.Right != nil && pre.Right != curr {
pre = pre.Right
}
if pre.Right == nil {
pre.Right = curr
curr = curr.Left
continue
}
// pre.Right == curr
pre.Right = nil
if pre.Left == nil { // tricky! not using curr, but pre
// ch <- pre.Val
return pre.Val, curr.Right, pre, true
}
curr = curr.Right
}
return 0, nil, nil, false
}
var val1, val2 int
var pre1, pre2 *TreeNode
var ok1, ok2 bool
curr1, curr2 := root1, root2
similar := true
for {
val1, curr1, pre1, ok1 = getLeafs(curr1, pre1)
val2, curr2, pre2, ok2 = getLeafs(curr2, pre2)
if val1 != val2 || ok1 != ok2 {
similar = false
}
if ok1 == false && ok2 == false {
break
}
}
return similar
}
Performing a little benchmarking, it may even be faster (at least for the example1 test case)...
goos: windows
goarch: amd64
BenchmarkLeafSimilar-4 244850 5509 ns/op 192 B/op 2 allocs/op
BenchmarkLeafSimilarNoConcurrency-4 13185218 92.9 ns/op 0 B/op 0 allocs/op
PASS
ok _/d_/Build/morristree 2.893s
I've put together an example which uses the deprecated testing.Main in the playground here, to demonstrate that it works the same for the 5 examples.
https://play.golang.org/p/hIk4zM3qpsT

LeetCode question Path Sum II: Recursive solution bug

I have submitted the below solution for the question in golang and it fails for the base case. I am not able to figure out why it is failing.
var answer[][]int
func hasPathSum(root *TreeNode, sum int, path []int){
if root == nil {
return
}
newPath := append(path, root.Val)
sum = sum - root.Val
if root.Left == nil && root.Right == nil && sum == 0 {
answer = append(answer, newPath)
fmt.Println(answer)
return
}
if root.Left != nil {
hasPathSum(root.Left, sum, newPath)
}
if root.Right != nil {
hasPathSum(root.Right, sum, newPath)
}
}
func pathSum(root *TreeNode, sum int) [][]int {
var path []int
answer = [][]int{}
hasPathSum(root, sum, path)
return answer
}
And when I avoid declaring newPath it passes the base check. Like this:
var answer[][]int
func hasPathSum(root *TreeNode, sum int, path []int){
if root == nil {
return
}
sum = sum - root.Val
if root.Left == nil && root.Right == nil && sum == 0 {
answer = append(answer, append(path, root.Val))
fmt.Println(answer)
return
}
if root.Left != nil {
hasPathSum(root.Left, sum, append(path, root.Val))
}
if root.Right != nil {
hasPathSum(root.Right, sum, append(path, root.Val))
}
}
func pathSum(root *TreeNode, sum int) [][]int {
var path []int
answer = [][]int{}
hasPathSum(root, sum, path)
return answer
}
I am not able to figure out what is the difference between the two solutions. Both solutions are the same from the recursion point of view. Furthermore, a similar solution in C++ passes all the checks.
The problem occurs because slices refer to an underlying array, and append does not re-allocate a new array if there's space. See https://blog.golang.org/slices-intro
That means when you append(path, root.Val), the new slice will sometimes share the backing array with path. That can be a problem, for example:
if root.Left != nil {
hasPathSum(root.Left, sum, append(path, root.Val))
}
if root.Right != nil {
hasPathSum(root.Right, sum, append(path, root.Val))
}
Here, both branches may be using the same backing array. That's a problem, because when executing the first hasPathSum it may add a slice to answer, but the underlying array of that slice may still be used in the second call to hasPathSum, which will change its contents.
Both versions of the code have the same problem, but because the second is less likely to cause problems because if append(path, root.Val) needs to reallocate, then you get two different copies in the two branches of hasPathSum. This means the bug will happen at a lower frequency.
I'm not sure about fmt.Println(answer), you'd probably just need to return answer.
This'll pass:
func pathSum(root *TreeNode, sum int) [][]int {
var paths [][]int
if root == nil {
return paths
}
if root.Left == nil && root.Right == nil {
if sum == root.Val {
return append(paths, []int{ root.Val })
}
return paths
}
for _, path := range pathSum(root.Left, sum - root.Val) {
paths = append(paths, append([]int{ root.Val}, path... ))
}
for _, path := range pathSum(root.Right, sum - root.Val) {
paths = append(paths, append([]int{ root.Val}, path... ))
}
return paths
}
Here is LeetCode's Java solution with comments:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
private void recurseTree(TreeNode node, int remainingSum, List<Integer> pathNodes, List<List<Integer>> pathsList) {
if (node == null) {
return;
}
// Add the current node to the path's list
pathNodes.add(node.val);
// Check if the current node is a leaf and also, if it
// equals our remaining sum. If it does, we add the path to
// our list of paths
if (remainingSum == node.val && node.left == null && node.right == null) {
pathsList.add(new ArrayList<>(pathNodes));
} else {
// Else, we will recurse on the left and the right children
this.recurseTree(node.left, remainingSum - node.val, pathNodes, pathsList);
this.recurseTree(node.right, remainingSum - node.val, pathNodes, pathsList);
}
// We need to pop the node once we are done processing ALL of it's
// subtrees.
pathNodes.remove(pathNodes.size() - 1);
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> pathsList = new ArrayList<List<Integer>>();
List<Integer> pathNodes = new ArrayList<Integer>();
this.recurseTree(root, sum, pathNodes, pathsList);
return pathsList;
}
}
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time/space complexity analysis1, 2 in there.

Resources