# Data strutsit ja alko

Flowcharts are visual diagrams that represent an algorithm using various shapes and arrowsto describe the steps involved. On the other hand, pseudocode is a text-based representationof an algorithm that uses a high-level programming language-like syntax. Both have their own benefits, and it depends on the person’s preference and the problem athand to choose which one to use. For example, flowcharts are more visually appealing andeasier to understand for non-programmers, while pseudocode is more concise and easier totranslate into actual code. | Write pseudocode for an algorithm that converts a decimal number to its binary representation: function DECtoBIN(number):, string = ”, while number is not 0:, Divide number by 2 and append the remainder to string (it’seither 0 or 1), reverse string and return it. | When solving an algorithmic problem, the approach should be to: break down the problem into smaller sub-problems (if the problem is complex), understand the inputs and outputs, identify the edge cases and constraints, and then design an algorithm that solves the problem efficiently. The steps involved in algorithmic design are as follows: 1. Problem definition, 2. Input and Output specification, 3. Analysis and design(Choice of datatypes, Designing the required steps and the order of them, Flowchart / pseudocode (or whatsoever notes) telling what the algorithm does), 4. Implementation and testing(In this step, you actually choose the programming language and run your code, Testing for correctness (driver code) and efficiency (time it)), 5. Optimization and Refinement(Analysing the worst-case complexity / time complexity by e.g. counting the n.o.operations taken from the initial state of the algorithm until the final state of thealgorithm, Optimization refers to the algorithm types: in-depth first (recursion), backtracking,dynamic programming, heuristics, divide-and-conquer etc. You can try to finddifferent approaches, if the current algorithm seems too slow in its context | Time complexity analysis involves determining the amount of time an algorithm takes to runin the worst-case scenario as a function of the size of the input data. The big O notation isused to describe the time complexity of an algorithm, and it provides an upper bound on thenumber of operations the algorithm takes to run as the size of the input data grows. Thedifference between best-case, average-case, and worst-case analysis is that best-caseanalysis is the fastest time the algorithm can run given a specific input, average-case analysisis the average time the algorithm will take given a random input, and worst-case analysis isthe longest time the algorithm can take given a specific input. | To design an algorithm to solve a problem, you need to understand the problem definition,input and output specifications, and any constraints or edge cases. Then, you can startdesigning an algorithm that solves the problem efficiently. To analyze its time complexity,you need to determine the number of operations the algorithm takes as the size of the inputdata grows and use the big O notation to describe its time complexity. | What is the difference between experimental and theoretical efficiency?: To test the efficiency of algorithms, you can write code that implements the algorithm andrun it on various inputs of increasing size. You can measure the running time of the algorithmand use it to determine the time complexity of the algorithm. Additionally, you can use built-in Python libraries and functions such as the timeit module to accurately measure therunning time of the algorithm | Asymptotic complexity refers to the behavior of an algorithm as the size of the inputgrows towards infinity. It’s used to describe the performance of an algorithm in terms of howfast it grows relative to the size of the input. Asymptotic complexity provides a way to compare the efficiency of algorithms independentof specific hardware and implementation details, and it’s a key tool for analyzing anddesigning algorithms. | Iteration and recursion are two different ways of solving a problem in computer science.Iteration involves using a loop to repeatedly perform a set of actions until a certain conditionis met. Recursion, on the other hand, involves solving a problem by breaking it down intosmaller sub-problems and using a function to call itself with the smaller sub-problems until abase case is reached. | A recursion tree is a visual representation of a recursive algorithm that shows therecursive calls and the intermediate results at each level. The algorithmic complexity of arecursive algorithm can be understood by analyzing the recursion tree, as it gives an idea ofhow many branches the algorithm generates and how the size of the sub-problemsdecreases as the recursion progresses. | Dynamic programming and memoization are optimization techniques used to reducethe number of branches in a recursion tree and improve the performance of a recursivealgorithm. Dynamic programming involves using a table to store intermediate results, whilememoization involves caching the results of expensive function calls and reusing them whenthe same inputs occur again. Both techniques allow a recursive algorithm to avoid redundantwork and achieve better performance. | Sorting: sort a list or tuple in ascending or descending order. Example: a = [3, 2, 1]; a.sort(); print(a) | Searching: find an element in a list or tuple. Example: a = [1, 2, 3]; print(2 in a) | Binary Search: search for an element in a sorted list or tuple. Example: a = [1, 2, 3]; print(binary_search(a, 2)) | Hashing: map a key to a specific value in a dictionary. Example: a = {‘key1’: ‘value1’}; print(a[‘key1’]) | Dynamic Programming: solve a complex problem by breaking it down into subproblems and storing the results for reuse. Example: print(fibonacci(10)) | Greedy Algorithm: make the locally optimal choice at each stage with the hope of finding a global optimum. Example: print(max_value(a)) | Backtracking: try out different solutions incrementally and undoing the solutions that do not lead to a correct solution. Example: print(permute(a)) | Divide and Conquer: break down a problem into subproblems that are easier to solve and then combine the solutions to get the final solution. Example: print(merge_sort(a))