Greedy algorithm (greedy algorithm)

main idea

When solving the problem, each step selects the local optimal solution , hoping to finally get the global optimal solution.
(The final result of the greedy algorithm is not necessarily the global optimal solution, but it is indeed the approximate optimal solution.)


Classic problem 1-set covering problem

There are n sets, and each set contains several elements. To find m sets from them, it is required to contain all the elements in the n sets and m is the smallest.
General solutions:
(1) List all combinations of n sets, because each set can be in the set or not in the set, so there are a total of 2 n 2^n2n kinds of combination schemes.
(2) In these combination schemes, find the combination of the set containing all the elements, and the combination contains the smallest number of sets.

The time complexity of this method is O (2 n) O(2^n)O ( 2n ), as n increases, the time will increase sharply and become unavailable.

Greedy algorithm ideas (approximate algorithm):
(1) Select a set that contains the most uncontained elements.
(2) Repeat the first step until the selected set contains all the elements.

The time complexity of the greedy algorithm is O (n 2) O(n^2)O ( n2 ).
Example:
There are several sets as follows, solve
set1 = {1, 2, 3};
set2 = {1, 3, 4};
set3 = {2, 5, 6};
set4 = {2, 3};
set5 = {6, 7};

Code:

public class GreedyAlgorithm {
    
    
    public Set<Integer> greedy(List<Set<Integer>> setList) {
    
    
    	//收集所有集合中的所有元素
        Set<Integer> needed = new HashSet<>();
        for (Set<Integer> set : setList) {
    
    
            for (int i : set) {
    
    
                needed.add(i);
            }
        }
        Set<Integer> result = new HashSet<>();
        while (!needed.isEmpty()) {
    
    
            int bestSet = 0;
            int bestCoveredSize = 0;
            for (int i = 0; i < setList.size(); i++) {
    
    
            	if (result.contains(i)) {
    
    
                    continue;
                }
                int coveredSize = 0;
                for (int j : setList.get(i)) {
    
    
                    if (needed.contains(j)) {
    
    
                        coveredSize++;
                    }
                }
                //体现出贪心算法,每次都选含有最多未包含元素的集合
                if (coveredSize > bestCoveredSize) {
    
    
                    bestSet = i;
                    bestCoveredSize = coveredSize;
                }
            }
            result.add(bestSet);
            needed.removeAll(setList.get(bestSet));

        }
        return result;
    }

    public static void main(String[] args) {
    
    
        List<Set<Integer>> setList = new ArrayList<>();
        setList.add(new HashSet<>(Arrays.asList(1, 2, 3)));
        setList.add(new HashSet<>(Arrays.asList(1, 3, 4)));
        setList.add(new HashSet<>(Arrays.asList(2, 5, 6)));
        setList.add(new HashSet<>(Arrays.asList(2, 3)));
        setList.add(new HashSet<>(Arrays.asList(6, 7)));
        System.out.println(new GreedyAlgorithm().greedy(setList));
    }
}

Classic problem 2-traveling salesman problem

There is a traveling agent who needs to travel from city A to the other n cities. Please plan his travel route to make the total journey the shortest.

General solution:
calculate n! N!n ! Travel routes, and select the shortest route from them. The time complexity isO (n!) O(n!)O ( n ! )

Greedy algorithm idea:
every time you choose the next city you want to go to, choose the closest city you haven't been to.

Code

public class GreedyAlgorithm2 {
    
    
    public static int[] greedyAlgorithm2(int[][] distance, int n) {
    
    
        int[] result = new int[n];
        Set<Integer> notBeenTo = new HashSet<>(n);
        for (int i = 1; i <= n; i++) {
    
    
            notBeenTo.add(i);
        }

        int from = 0;
        for (int i = 0; i < result.length; i++) {
    
    
            int next = 0;
            for (int j : notBeenTo) {
    
    
                //体现出贪心算法,每次都选还没去过的距离最近的城市
                if (next == 0 || distance[from][next] > distance[from][j]) {
    
    
                    next = j;
                }
            }
            result[i] = next;
            from = next;
            notBeenTo.remove(next);
        }

        return result;
    }

    //测试代码
    public static void main(String[] args) {
    
    
        int n = 4;
        int[][] distance = new int[n + 1][n + 1];
        //0表示旅行商当前所在城市A, 1...n表示要去的城市
        Random rnd = new Random();
        for (int i = 0; i < distance.length; i++) {
    
    
            for (int j = 0; j < i; j++) {
    
    
                if (i != j) {
    
    
                    distance[i][j] = distance[j][i] = rnd.nextInt(10) + 1;
                }
            }
        }
        for (int[] arr : distance) {
    
    
            System.out.println(Arrays.toString(arr));
        }
        System.out.println();
        int[] result = greedyAlgorithm2(distance, n);
        System.out.println(Arrays.toString(result));
    }
}

NP complete problem

Regarding what is the P problem, NP problem, NP complete problem (NPC), NP-hard problem (NPH), please Baidu by yourself, but I did not find a satisfactory answer (I didn't understand it).

  • The simple definition of NP-complete problems is known as difficult-to-solve problems (problems that cannot be solved in polynomial time), such as the set covering problem and the traveling salesman problem.
  • When judging that a problem is NP-complete, there is no need to find a perfect solution, but to use an approximate algorithm. But it is difficult to judge whether a problem is NP-complete, because the difference between easy-to-solve problems and NP-complete problems is usually very small. Such as "the shortest path problem between two points" and "traveling salesman problem".

The following method can be used to simply (not necessarily) judge whether the problem is NP-complete.

  • When the number of elements is small, the algorithm runs very fast, but as the number of elements increases, the speed becomes very slow.
  • Problems involving "all combinations" are usually NP-complete.
  • The problem cannot be divided into small problems, all possible situations must be considered. This may be an NP-complete problem.
  • If the problem involves a sequence (such as the city sequence in the traveling salesman problem) and is difficult to solve, it may be an NP-complete problem.
  • If the problem involves a collection (such as a collection of broadcast stations) and is difficult to solve, it may be an NP-complete problem.
  • If the problem can be transformed into a set covering problem or a traveler problem, it must be an NP-complete problem.

Reference: "Algorithm Diagram" Chapter 8 Greedy Algorithm

Guess you like

Origin blog.csdn.net/AmorFati1996/article/details/110998879