NP-Completeness

Introduction to the concepts of P, NP, NP-Completeness, and NP-Hardness. Covers examples of NP-Complete problems and techniques for dealing with them.


P (Polynomial Time) Algorithms

Introduction

In the realm of algorithm design and analysis, the concept of polynomial time algorithms is fundamental. Understanding what constitutes a polynomial time algorithm and the complexity class P is crucial for differentiating between problems that can be solved efficiently and those that are likely intractable.

What are P (Polynomial Time) Algorithms?

A polynomial time algorithm is an algorithm whose worst-case running time is bounded by a polynomial expression in the size of the input. In simpler terms, if 'n' represents the size of the input, a polynomial time algorithm has a running time of O(nk) for some constant 'k'. The value of 'k' is important, but the key is that it's a fixed constant and does not depend on the input size.

For example, an algorithm with a running time of O(n), O(n2), O(n3), or O(n100) would be considered a polynomial time algorithm. An algorithm with a running time of O(2n) or O(n!) would not be considered a polynomial time algorithm because the exponent depends on 'n'.

Definition of the Complexity Class P

The complexity class P (Polynomial Time) is the set of all decision problems that can be solved by a deterministic algorithm in polynomial time. A decision problem is a problem that can be answered with a "yes" or "no".

Formally, a problem belongs to the class P if there exists a polynomial time algorithm that, given an instance of the problem, can determine whether the answer is "yes" or "no" in a time bounded by a polynomial function of the input size.

Examples of Problems Solvable in Polynomial Time

  • Sorting: Algorithms like Merge Sort and Heap Sort can sort a list of 'n' elements in O(n log n) time, which is considered polynomial.
  • Searching: Binary Search can find a specific element in a sorted array of 'n' elements in O(log n) time.
  • Graph Traversal: Breadth-First Search (BFS) and Depth-First Search (DFS) can traverse a graph with 'V' vertices and 'E' edges in O(V + E) time.
  • Minimum Spanning Tree (MST): Algorithms like Prim's and Kruskal's algorithms can find the minimum spanning tree of a graph in polynomial time.
  • Path Finding: Finding the shortest path in a graph using Dijkstra's Algorithm (under certain conditions, like non-negative edge weights) takes polynomial time.
  • Multiplication and Addition: Basic arithmetic operations like multiplying or adding two numbers can be done in polynomial time (depending on the representation of the numbers).

Relationship to Tractable Problems

Problems in the class P are often considered tractable or feasible, meaning that they can be solved practically, at least for reasonably sized inputs. While an algorithm with a high degree polynomial running time (e.g., O(n100)) might be theoretically polynomial, it may not be practical for large inputs. However, in practice, many polynomial time algorithms have relatively small exponents (e.g., O(n), O(n log n), O(n2)), making them efficient for real-world applications.

The distinction between problems in P and those outside of P (like NP-complete problems) is crucial for understanding the limits of what computers can efficiently compute. The P vs NP problem is a major unsolved problem in computer science. It asks whether every problem whose solution can be *verified* in polynomial time (NP) can also be *solved* in polynomial time (P). If P = NP, then many problems currently considered intractable would have efficient solutions.