{"id":19640955,"url":"https://github.com/williamkoller/introduction-analysis-algorithms-big-o","last_synced_at":"2026-05-12T21:07:15.270Z","repository":{"id":217920634,"uuid":"745134089","full_name":"williamkoller/introduction-analysis-algorithms-big-o","owner":"williamkoller","description":"Introdução à análise de Algoritmo e Big-O","archived":false,"fork":false,"pushed_at":"2024-05-02T17:50:46.000Z","size":1184,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-30T08:02:18.669Z","etag":null,"topics":["algorithms","big-o-notation","big-o-performance","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/williamkoller.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2024-01-18T17:54:14.000Z","updated_at":"2024-05-02T17:50:49.000Z","dependencies_parsed_at":"2024-01-24T12:04:34.177Z","dependency_job_id":null,"html_url":"https://github.com/williamkoller/introduction-analysis-algorithms-big-o","commit_stats":{"total_commits":25,"total_committers":1,"mean_commits":25.0,"dds":0.0,"last_synced_commit":"57438e172db588fdf956311bbcc191d78f387bbd"},"previous_names":["williamkoller/introduction-analysis-algorithms-big-o"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/williamkoller/introduction-analysis-algorithms-big-o","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamkoller%2Fintroduction-analysis-algorithms-big-o","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamkoller%2Fintroduction-analysis-algorithms-big-o/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamkoller%2Fintroduction-analysis-algorithms-big-o/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamkoller%2Fintroduction-analysis-algorithms-big-o/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/williamkoller","download_url":"https://codeload.github.com/williamkoller/introduction-analysis-algorithms-big-o/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamkoller%2Fintroduction-analysis-algorithms-big-o/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32956935,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-12T09:19:52.626Z","status":"ssl_error","status_checked_at":"2026-05-12T09:17:33.438Z","response_time":102,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","big-o-notation","big-o-performance","python"],"created_at":"2024-11-11T14:07:19.576Z","updated_at":"2026-05-12T21:07:15.253Z","avatar_url":"https://github.com/williamkoller.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introdução à análise de Algoritmo e Big-O\n\n\u003cimg src=\"/imgs/big-o.png\" alt=\"book\" title=\"book\" height=\"104\" width=\"96\" align=\"right\"/\u003e\n\n\u003ch3\u003e1 - Por que eh importante saber Big-O?\u003c/h3\u003e\n\nSaber Big-O é importante porque permite determinar a complexidade de um algoritmo em relação ao tamanho da entrada. Isso ajuda a identificar algoritmos eficientes e escaláveis para lidar com grandes quantidades de dados e muitas requisições simultâneas. Empresas como Google, Amazon e Microsoft frequentemente fazem perguntas sobre complexidade de algoritmos durante o processo de seleção de candidatos\n\n\u003ch3\u003e2 - Vamos falar sobre desempenho?\u003c/h3\u003e\n\nO desempenho de um algoritmo é fundamental para a eficiência e escalabilidade de uma solução. Compreender como medir e melhorar o desempenho é essencial para criar soluções eficientes e escaláveis. Além disso, muitas empresas valorizam o conhecimento desses conceitos durante o processo de seleção dos candidatos.\n\n\u003cimg src=\"/imgs//pensando-codigo.png\" alt=\"pensando-codigo\" title=\"pensando-codigo\" align=\"center\" /\u003e\n\n\u003ch3\u003e3 - Vamos falar sobre desempenho, do jeito certo?\u003c/h3\u003e\n\nMedir o desempenho de um algoritmo requer técnicas adequadas para obter resultados precisos. É importante evitar armadilhas comuns, como medir o tempo de execução em um ambiente não controlado ou medir apenas um caso específico em vez de uma amostra representativa de entradas.\n\n\u003ch3\u003e4 - Vamos falar sobre complexidade linear?\u003c/h3\u003e\n\nA complexidade linear descreve um algoritmo cujo tempo de execução aumenta linearmente com o tamanho da entrada. Isso significa que o tempo de execução é proporcional ao número de elementos na entrada.\n\nExemplo codigo linear: \n\n```python\ndef sum_array_complexity(arr):\n    total = 0\n    for i in arr:\n        total += i\n    return total\n```\n\n```python\ndef linear_search(array, target):\n    for i in range(len(array)):\n        if array[i] == target:\n            return i\n    return -1\n```\n\n\u003cimg src=\"/imgs/linear.png\" alt=\"complexidade-linear\" title=\"complexidade-linear\" align=\"center\" /\u003e\n\n\u003ch3\u003e5 - Vamos falar sobre complexidade constante?\u003c/h3\u003e\n\nA complexidade constante descreve um algoritmo cujo tempo de execução não varia com o tamanho da entrada. Isso significa que o tempo de execução é constante, independentemente do número de elementos na entrada.\n\nExamplo codigo constante:\n\n```python\ndef sum_first_two(arr):\n    if len(arr) \u003e= 2:\n        return arr[0] + arr[1]\n    else:\n        return None\n```\n\n\u003cimg src=\"/imgs/constante.png\" alt=\"complexidade-constante\" title=\"complexidade-constante\" align=\"center\" /\u003e\n\n\u003ch3\u003e6 - Vamos falar sobre complexidade logarítmica?\u003c/h3\u003e\n\nA complexidade logarítmica descreve um algoritmo cujo tempo de execução aumenta logaritmicamente com o tamanho da entrada. Isso significa que o tempo de execução é proporcional ao logaritmo do número de elementos na entrada.\n\nExemplo codigo logaritmico:\n\n```python\ndef logarithm(arr, target):\n    low = 0\n    high = len(arr) - 1\n    while low \u003c= high:\n        mid = (low+high) // 2\n        if arr[mid] == target:\n            return mid\n        elif arr[mid] \u003c target:\n            low = mid + 1\n        else:\n            high = mid - 1\n    return -1\n```\n\n\n```python\ndef euclidean_search(a, b):\n    while b:\n        a, b = b, a % b\n    return a\n```\n\n\u003cimg src=\"/imgs/logaritma.png\" alt=\"complexidade-logaritmica\" title=\"complexidade-logaritmica\" align=\"center\" /\u003e\n\n\u003ch3\u003e7 - Vamos falar sobre complexidade quadratica?\u003c/h3\u003e\n\nA complexidade quadrática descreve um algoritmo cujo tempo de execução aumenta quadraticamente com o tamanho da entrada. Isso significa que o tempo de execução é proporcional ao quadrado do número de elementos na entrada.\n\nExemplo codigo quadratica:\n\n```python\ndef sum_square_matrix(matrix):\n    n = len(matrix)\n    total = 0\n    for i in range(n):\n        for j in range(n):\n            total += matrix[i][j]\n    return total\n```\n\n```python\ndef pair_sum(arr, target):\n    pairs = []\n    for i in range(len(arr)):\n        for j in range(i+1, len(arr)):\n            if arr[i] + arr[j] == target:\n                pairs.append((arr[i], arr[j]))\n    return pairs\n```\n\n\u003cimg src=\"/imgs/quadratica.png\" alt=\"complexidade-quadratica\" title=\"complexidade-quadratica\" align=\"center\" /\u003e\n\n\n\u003ch3\u003e8 - Vamos falar sobre complexidade cubica?\u003c/h3\u003e\n\nA complexidade cúbica descreve um algoritmo cujo tempo de execução aumenta cúbicamente com o tamanho da entrada. Isso significa que o tempo de execução é proporcional ao cubo do número de elementos na entrada.\n\nExemplo codigo cubica:\n\n```python\ndef multiply_matrices(A, B):\n    n = len(A)\n    C = [[0 for _ in range(n)] for _ in range(n)]\n    for i in range(n):\n        for j in range(n):\n            for k in range(n):\n                C[i][j] += A[i][k] * B[k][j]\n    return C\n```\n\n\u003cimg src=\"/imgs/cubica.png\" alt=\"complexidade-cubica\" title=\"complexidade-cubica\" align=\"center\" /\u003e\n\n\u003ch3\u003e9 - Vamos falar sobre complexidade exponencial?\u003c/h3\u003e\n\nA complexidade exponencial descreve um algoritmo cujo tempo de execução aumenta exponencialmente com o tamanho da entrada. Isso significa que o tempo de execução é proporcional a uma constante elevada à potência do número de elementos na entrada.\n\nExemplo codigo exponencial:\n\n```python\ndef fibonacci(n):\n    if n \u003c= 1:\n        return n\n    else:\n        return fibonacci(n - 1) + fibonacci(n - 2)\n```\n\n```python\ndef cubic_complexity_algorithm(n):\n    result = 0\n    for i in range(n):\n        for j in range(n):\n            for k in range(n):\n                result += 1\n    return result\n```\n\n\u003cimg src=\"/imgs/exponencial.png\" alt=\"complexidade-exponencial\" title=\"complexidade-exponencial\" align=\"center\" /\u003e\n\n\u003ch3\u003e10 - Vamos falar sobre complexidade fatorial?\u003c/h3\u003e\n\nA complexidade fatorial descreve um algoritmo cujo tempo de execução aumenta fatorialmente com o tamanho da entrada. Isso significa que o tempo de execução é proporcional ao fatorial do número de elementos na entrada.\n\n```python\ndef permutations(arr):\n    if len(arr) == 0:\n        return [[]]\n    else:\n        total = []\n        for i in range(len(arr)):\n            remaining_elements = arr[:i] + arr[i+1:]\n            sub_permutations = permutations(remaining_elements)\n            for permutation in sub_permutations:\n                total.append([arr[i]] + permutation)\n        return total\n```\n\n\u003cimg src=\"/imgs/fatorial.png\" alt=\"complexidade-fatorial\" title=\"complexidade-fatorial\" align=\"center\" /\u003e\n\n\u003ch3\u003e11 - Vamos comecar a falar sobre Big-O?\u003c/h3\u003e\n\nBig-O é uma notação matemática que descreve o comportamento de tempo de execução de um algoritmo em relação ao tamanho da entrada. Isso permite comparar algoritmos independentemente do hardware ou linguagem de programação usada para implementá-los.\n\nExemplo codigo Big-O - O(n):\n\n```python\ndef sum_array(arr):\n    total = 0\n    for i in arr:\n        total += i\n    return total\n```\n\n\u003cimg src=\"/imgs/big-o-linear.png\" alt=\"complexidade-big-o\" title=\"complexidade-big-o\" align=\"center\" /\u003e\n\nExemplo codigo Big-O - O(1):\n\n```python\ndef sum_first_two(arr):\n    if len(arr) \u003e= 2:\n        return arr[0] + arr[1]\n    else:\n        return None\n```\n\n\u003cimg src=\"/imgs/big-o-constante.png\" alt=\"complexidade-big-o\" title=\"complexidade-big-o\" align=\"center\" /\u003e\n\nExemplo codigo Big-O - O(log n):\n\n```python\ndef binary_search(arr, target):\n    low = 0\n    high = len(arr) - 1\n    while low \u003c= high:\n        mid = (low+high) // 2\n        if arr[mid] == target:\n            return mid\n        elif arr[mid] \u003c target:\n            low = mid + 1\n        else:\n            high = mid - 1\n    return -1\n```\n\n\u003cimg src=\"/imgs/big-o-logaritmica.png\" alt=\"complexidade-big-o\" title=\"complexidade-big-o\" align=\"center\" /\u003e\n\nExemplo codigo Big-O - O(n^2):\n\n```python\ndef sum_square_matrix(matrix):\n    n = len(matrix)\n    total = 0\n    for i in range(n):\n        for j in range(n):\n            total += matrix[i][j]\n    return total\n```\n\n\u003cimg src=\"/imgs/big-o-quadratica.png\" alt=\"complexidade-big-o\" title=\"complexidade-big-o\" align=\"center\" /\u003e\n\nExemplo codigo Big-O - O(n^3):\n\n```python\ndef multiply_matrices(A, B):\n    n = len(A)\n    C = [[0 for _ in range(n)] for _ in range(n)]\n    for i in range(n):\n        for j in range(n):\n            for k in range(n):\n                C[i][j] += A[i][k] * B[k][j]\n    return C\n```\n\n\u003cimg src=\"/imgs/big-o-cubica.png\" alt=\"complexidade-big-o\" title=\"complexidade-big-o\" align=\"center\" /\u003e\n\nExemplo codigo Big-O - O(2^n):\n\n```python\ndef fibonacci(n):\n    if n \u003c= 1:\n        return n\n    else:\n        return fibonacci(n - 1) + fibonacci(n - 2)\n```\n\n\u003cimg src=\"/imgs/big-o-exponencial.png\" alt=\"complexidade-big-o\" title=\"complexidade-big-o\" align=\"center\" /\u003e\n\nExemplo codigo Big-O - O(n!):\n\n```python\ndef permutations(arr):\n    if len(arr) == 0:\n        return [[]]\n    else:\n        total = []\n        for i in range(len(arr)):\n            remaining_elements = arr[:i] + arr[i+1:]\n            sub_permutations = permutations(remaining_elements)\n            for permutation in sub_permutations:\n                total.append([arr[i]] + permutation)\n        return total\n```\n\n\u003cimg src=\"/imgs/big-o-fatorial.png\" alt=\"complexidade-big-o\" title=\"complexidade-big-o\" align=\"center\" /\u003e\n\n\u003ch3\u003e12 - Vamos falar sobre P e NP?\u003c/h3\u003e\n\nP e NP são classes de problemas em teoria da computação. Problemas em P podem ser resolvidos em tempo polinomial, enquanto problemas em NP podem ser verificados em tempo polinomial. A questão P = NP é uma das perguntas mais importantes em ciência da computação.\n\nExemplo codigo O(n^2) P:\n\n```python\ndef is_valid_solution(board):\n    # verify that each row, column, and 3x3 square contains the numbers 1-9\n    for row in range(9):\n        used_nums = set()\n        for col in range(9):\n            num = board[row][col]\n            if num in used_nums:\n                return False\n            if num != 0:\n                used_nums.add(num)\n\n    # verify that each column contains the numbers 1-9\n    for col in range(9):\n        used_nums = set()\n        for row in range(9):\n            num = board[row][col]\n            if num in used_nums:\n                return False\n            if num != 0:\n                used_nums.add(num)\n\n    # verify that each 3x3 square contains the numbers 1-9\n    for i in range(3):\n        for j in range(3):\n            used_nums = set()\n            for row in range(3):\n                for col in range(3):\n                    num = board[3*i + row][3*j + col]\n                    if num in used_nums:\n                        return False\n                    if num != 0:\n                        used_nums.add(num)\n    return True\n```\n\n\u003ch3\u003e13 - Vamos falar sobre complexidade assintotica?\u003c/h3\u003e\n\nA complexidade assintótica descreve o comportamento do algoritmo quando a entrada aumenta para um tamanho infinito. Ela é representada por Big-O e é uma forma de descrever a complexidade de um algoritmo sem se preocupar com constantes e termos de baixa ordem.\n\nComplexidade assintotica eh descrita por Big-O\n\nExemplo codigo O(n):\n\n```python\ndef find_min_max(arr):\n  n = len(arr)\n  min_val = max_val = arr[0]\n  for i in range(1, n):\n    if arr[i] \u003c min_val:\n      min_val = arr[i]\n    if arr[i] \u003e max_val:\n      max_val = arr[i]\n  return min_val, max_val\n```\n\n```python\ndef best_min_max(arr):\n  n = len(arr)\n  min_val = arr[0]\n  for i in range(1, n):\n    if arr[i] \u003c min_val:\n      min_val = arr[i]\n\n  for i in range(1, n):\n    if arr[i] \u003e min_val:\n      max_val = arr[i]\n\n  return min_val, max_val\n```\n\n```python\ndef find_min(arr):\n  n = len(arr)\n  min_val = arr[0]\n  for i in range(1, n):\n    if arr[i] \u003c min_val:\n      min_val = arr[i]\n  return min_val\n\ndef find_max(arr):\n  n = len(arr)\n  max_val = arr[0]\n  for i in range(1, n):\n    if arr[i] \u003e max_val:\n      max_val = arr[i]\n  return max_val\n\ndef find_min_max_best(arr):\n  return find_min(arr), find_max(arr)\n```\n\n\u003cimg src=\"/imgs/assintotica.png\" alt=\"complexidade-assintotica\" title=\"complexidade-assintotica\" align=\"center\" /\u003e\n\n\u003ch3\u003e14 - Vamos falar sobre escalabilidade?\u003c/h3\u003e\n\nA escalabilidade descreve a capacidade de um sistema de lidar com um aumento na carga de trabalho. Isso pode ser medido em termos de desempenho, tempo de resposta ou tempo de execução. A escalabilidade é importante para garantir que um sistema possa lidar com um aumento na carga de trabalho sem degradar o desempenho.\n\nDuas perspectivas de escalabilidade:\n\n1. Requisicoes com \"entradas maiores\"\n\n2. Mais requisicoes\n\n\u003cimg src=\"/imgs/escalabilidade.png\" alt=\"escalabilidade\" title=\"escalabilidade\" align=\"center\" /\u003e\n\nEventualmente uma saida \"boa o suficiente\", produzida em um tempo menor eh preferivel a saida \"perfeita\", produzida em mais tempo.\n\n\u003cimg src=\"/imgs/escalabilidade-2.png\" alt=\"escalabilidade-2\" title=\"escalabilidade-2\" align=\"center\" /\u003e\n\nExemplo codigo O(n):\n\n```python\ndef insert_sorted(arr, n):\n  i = len(arr) - 1\n  arr.append(n)\n  while i \u003e= 0 and arr[i] \u003e n:\n    arr[i + 1] = arr[i]\n    i -= 1\n  arr[i + 1] = n\n  return arr\n```\n\nA insercao em uma AVL acontece em O(log n)\n\nBancos de dados utilizam uma estrutura de dados chamada B-tree para indices.\n\n\u003ch3\u003e15 - Como determinar a complexidade de um algoritmo?\u003c/h3\u003e\n\nExistem várias técnicas para determinar a complexidade de um algoritmo, incluindo análise de tempo, análise de espaço e análise assintótica. A análise assintótica, representada por Big-O, é uma forma de descrever a complexidade de um algoritmo sem se preocupar com constantes e termos de baixa ordem. Ela é a técnica mais comum e útil para determinar a complexidade de um algoritmo.\n\nQual eh o impacto do auemnto de carga de trabalho no tempo de execucao do meu codigo?\n\nComo determinar a complexidade da busca de \"maior valor\"?\n\n```python\ndef find_max(numbers):\n  max_number = numbers[0]\n  for number in numbers:\n    if number \u003e max_number:\n      max_number = number\n  return max_number\n```\n\n\u003cimg src=\"/imgs/complexidade-algoritmo.png\" alt=\"complexidade-algoritmo\" title=\"complexidade-algoritmo\" align=\"center\" /\u003e\n\n\u003cimg src=\"/imgs/complexidade-algoritmo-2.png\" alt=\"complexidade-algoritmo-2\" title=\"complexidade-algoritmo-2\" align=\"center\" /\u003e\n\n\u003cimg src=\"/imgs/complexidade-algoritmo-3.png\" alt=\"complexidade-algoritmo-3\" title=\"complexidade-algoritmo-3\" align=\"center\" /\u003e\n\n\u003ch3\u003e16 - Como determinar a complexidade do BubbleSort?\u003c/h3\u003e\n\nO BubbleSort é um algoritmo de ordenação que percorre uma lista várias vezes. Em cada iteração, ele compara pares de elementos adjacentes e os troca se estiverem na ordem errada. O algoritmo continua até que a lista esteja ordenada.\n\n```python\ndef bubble_sort(arr):\n  n = len(arr)\n  for i in range(n):\n    for j in range(n - 1):\n      if arr[j] \u003e arr[j + 1]:\n        arr[j], arr[j + 1] = arr[j + 1], arr[j]\n  return arr\n```\n\n\u003cimg src=\"/imgs/bubble-sort.png\" alt=\"bubble-sort\" title=\"bubble-sort\" align=\"center\" /\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilliamkoller%2Fintroduction-analysis-algorithms-big-o","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwilliamkoller%2Fintroduction-analysis-algorithms-big-o","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilliamkoller%2Fintroduction-analysis-algorithms-big-o/lists"}