diff --git a/array/README.md b/array/README.md index 9a5190d..11fd6d5 100644 --- a/array/README.md +++ b/array/README.md @@ -76,7 +76,7 @@ func main() { Accessing an element within an array using an index has O(1) time complexity. This means that regardless of the size of the array, read and write operations for a given element can be performed in constant time. -While arrays are useful for certain tasks, searching an unsorted array can be a time-consuming O(n) operation. Since the target item could be located anywhere in the array, every element must be checked until the item is found. Due to this limitation, alternative data structures such as trees and hash tables are often more suitable for search operations. +While arrays are useful for certain tasks, searching an unsorted array can be a time-consuming O(n) operation. Since the target item could be located anywhere in the array, every element must be checked until the item is found. Due to this limitation, alternative data structures such as [linked-lists](../linkedlist/), [trees](../tree/) and [hash tables](../hashtable/) are often more suitable for search operations. Addition and deletion operations are O(n) operations in Arrays. Removing an element can create an empty slot that must be eliminated by shifting the remaining items. Similarly, adding items to an array may require shifting existing items to create space for the added item. These inefficiencies can make alternative data structures, such as [trees](../tree) or [hash tables](../hashtable), more suitable for managing operations involving additions and deletions. diff --git a/linkedlist/README.md b/linkedlist/README.md index 902f86d..f250db7 100644 --- a/linkedlist/README.md +++ b/linkedlist/README.md @@ -1,6 +1,6 @@ # Linked List -Linked lists are a collection of nodes, each capable of storing at least one data element and linked to the next node via a reference. One of the key advantages of linked lists over [arrays](../array) is their dynamic size, which allows for items to be added or removed without necessitating the resizing or shifting of other elements. +Linked lists are a collection of nodes, each capable of storing at least one data element and linked to the next node via a reference. One of the key advantages of linked lists over [arrays](../array) has traditionally been seen their dynamic size, which allows for items to be added or removed without necessitating the resizing or shifting of other elements. As shown in [queues](../queue/) with benchmarks this is different in Go due to clever slice sizing techniques used. In practice you can use slices in Go most of the time without a significant performance penalty. Two types of linked lists exist: singly linked lists, in which each node is linked only to the next node, and doubly linked lists, in which each node is connected to both the next and previous nodes. diff --git a/stack/README.md b/stack/README.md index df9a5fe..be0f343 100644 --- a/stack/README.md +++ b/stack/README.md @@ -4,6 +4,24 @@ Stacks are data structures that operate on the Last-In-First-Out (LIFO) principl One way to visualize stacks is to think of a backpack where items are placed and later removed in reverse order, with the last item added to the bag being the first item removed. +The following diagram shows the state of a stack of size 5 when numbers 1 to 4 are pushed to the stack and 4 numbers are popped from the stack. The outcome is reversion of the inserted numbers. + +```ASCII +[Figure 1] Push 1,2,3,4 to a stack and then pop 4 times. + +┌───┐┌───┐┌───┐┌───┐┌───┐ ┌───┐┌───┐┌───┐┌───┐ +│ ││ ││ ││ ││ │ │ ││ ││ ││ │ +├───┤├───┤├───┤├───┤├───┤ ├───┤├───┤├───┤├───┤ +│ ││ ││ ││ ││ 4 │ │ ││ ││ ││ │ +├───┤├───┤├───┤├───┤├───┤ ├───┤├───┤├───┤├───┤ +│ ││ ││ ││ 3 ││ 3 │ │ 3 ││ ││ ││ │ +├───┤├───┤├───┤├───┤├───┤ ├───┤├───┤├───┤├───┤ +│ ││ ││ 2 ││ 2 ││ 2 │ │ 2 ││ 2 ││ ││ │ +├───┤├───┤├───┤├───┤├───┤ ├───┤├───┤├───┤├───┤ +│ ││ 1 ││ 1 ││ 1 ││ 1 │ │ 1 ││ 1 ││ 1 ││ │ +└───┘└───┘└───┘└───┘└───┘ └───┘└───┘└───┘└───┘ +``` + ## Implementation In Go, stacks can be implemented using doubly [linked lists](../linkedlist/) or [arrays and slices](../array/). Here is a linked list implementation: @@ -75,13 +93,13 @@ func pop() (int, error) { Push and pop operations in stacks are considered O(1) operations, making them highly efficient. Additionally, many machines have built-in stack instruction sets, further increasing their performance. Stacks' unique efficiency and usefulness have solidified their place as one of the most fundamental data structures, second only to [arrays](../array). -Resizing the slice and item shifting maybe necessary in the slice implementation, hence traditionally this implementation is seen as O(n). As shown in the complexity of [queue](../queue/README.md) because of the intelligent ways Go resizes the slices this is not a problem and the slice implementation of both stack and queue will perform better than the linked list implementation. +Resizing the slice and item shifting maybe necessary in the slice implementation, hence traditionally this implementation is seen as O(n). As shown in the complexity of [queue](../queue/README.md) because of the intelligent ways Go resizes the slices this is not a problem and the slice implementation of both stack and queue in Go will perform better than the linked list implementation. ## Application Stacks are helpful when LIFO operations are desired. Many [graph](../graph) problems are solved with stacks. -During process execution, a portion of memory known as the "stack" is reserved to hold stack frames. Whenever a function is called, relevant data such as parameters, local variables, and return values are stored within a frame to be accessed after the function has been completed. When an excessive number of function calls or an infinite recursive function are made, the computer's ability to store all of this information is exceeded. This results in the well-known stack overflow error. +During process execution in operating systems, memory is divided into "stack" and "heap". The stack portion of the memory is used whenever a function is called. Relevant data such as parameters, local variables, and return values are stored within a frame in a stack to be popped after the function has been completed. When an excessive number of function calls or an infinite recursive function are made, the computer's ability to store all of this information is exceeded. This results in the well-known stack overflow error. ## Rehearsal diff --git a/stack/balancing_symbols_test.go b/stack/balancing_symbols_test.go index 2566971..ef25593 100644 --- a/stack/balancing_symbols_test.go +++ b/stack/balancing_symbols_test.go @@ -8,6 +8,8 @@ TestIsExpressionBalanced tests solution(s) with the following signature and prob func IsExpressionBalanced(s string) bool Given a set of symbols including []{}(), determine if the input is is balanced or not. + +For example {{(}} is not balanced because there is no closing `)` while {{()}} is balanced. */ func TestIsExpressionBalanced(t *testing.T) { tests := []struct { diff --git a/stack/basic_calculator_test.go b/stack/basic_calculator_test.go index 938f1a9..041e0f9 100644 --- a/stack/basic_calculator_test.go +++ b/stack/basic_calculator_test.go @@ -4,10 +4,13 @@ import "testing" /* TestBasicCalculator tests solution(s) with the following signature and problem description: + func BasicCalculator(input string) (float64, error) Given an expression containing integers, parentheses and the four basic arithmetic operations -like 1*2+3+4*5 calculate the expression into a numerical value like 25. +{*,/,+,-} starting from the highest priority to lowest. + +For example given 1*2+3+4*5 return 25 because (4*5) + (1*2) + 3 = 25. */ func TestBasicCalculator(t *testing.T) { tests := []struct { diff --git a/stack/evaluate_postfix_test.go b/stack/evaluate_postfix_test.go index bc900e2..84e23e9 100644 --- a/stack/evaluate_postfix_test.go +++ b/stack/evaluate_postfix_test.go @@ -7,7 +7,16 @@ TestEvaluatePostfix tests solution(s) with the following signature and problem d func EvaluatePostfixExpression(expression []string) (float64, error) -Given a postfix expression like 1 2 3 + *, calculate the expression e.g. 5. +Given a postfix expression calculate its the value. + +The postfix expression is a list of strings where each string is either an operator like +arithmetic symbols or an operand that are numbers. + +To evaluate the postfix expression, we start scanning the expression from left to right. +If the current element is an operator we apply the operand to the last two operands we read +we then remove the operator and replace the two operands with the results of the operation. + +For example given 1 2 3 + *, return 5 because 1 * (2 + 3) = 5. */ func TestEvaluatePostfix(t *testing.T) { tests := []struct { diff --git a/stack/infix_to_postfix_test.go b/stack/infix_to_postfix_test.go index 8a298a1..5e852ef 100644 --- a/stack/infix_to_postfix_test.go +++ b/stack/infix_to_postfix_test.go @@ -10,8 +10,13 @@ TestInfixToPostfix tests solution(s) with the following signature and problem de func InfixToPostfix(infix []string) []string -Given an infix expression e.g. 1*2+3+4*5, convert it to a postfix expression -like 1 2 * 3 + 4 5 * supporting the four basic arithmetic operations and parentheses. +Given an infix expression convert it to a postfix expression supporting the four basic arithmetic +operations and parentheses. + +Infix expression is how humans typically write arithmetic expressions like 1*2+3+4*5 which +is equivalent of (1*2) + 3 + (4*5). + +For example given 1*2+3+4*5, return 1 2 * 3 + 4 5 * which both evaluate to 25. */ func TestInfixToPostfix(t *testing.T) { tests := []struct { diff --git a/stack/longest_valid_parentheses_test.go b/stack/longest_valid_parentheses_test.go index ae587e3..68872d3 100644 --- a/stack/longest_valid_parentheses_test.go +++ b/stack/longest_valid_parentheses_test.go @@ -9,6 +9,8 @@ TestLongestValidParentheses tests solution(s) with the following signature and p Given a string containing parentheses, find the length of the longest valid (well-formed) parentheses substring. + +For example given "(()", return 2 because the longest valid parentheses substring is "()". */ func TestLongestValidParentheses(t *testing.T) { tests := []struct { diff --git a/stack/max_stack_test.go b/stack/max_stack_test.go index dc28c59..dcc540d 100644 --- a/stack/max_stack_test.go +++ b/stack/max_stack_test.go @@ -12,6 +12,8 @@ TestMaxStack tests solution(s) with the following signature and problem descript func (maxStack *MaxStack) Max() int Implement a stack that can return the max of element it contains. + +For example if we push {2,4,5} to the stack, max should return 5. */ func TestMaxStack(t *testing.T) { tests := []struct {