LeetCode刷题2-火柴拼正方形

前言

经常遇到这样的问题

dfs算法?bfs又是啥?

怎么枚举所有可能性?

 

题目描述:

你将得到一个整数数组 matchsticks ,其中 matchsticks[i] 是第 i 个火柴棒的长度。你要用 所有的火柴棍 拼成一个正方形。你 不能折断 任何一根火柴棒,但你可以把它们连在一起,而且每根火柴棒必须 使用一次 。

如果你能使这个正方形,则返回 true ,否则返回 false 。

示例代码:

class Solution {
    public boolean makesquare(int[] matchsticks) {
        // 当matchsticks数组长度小于等于3时(火柴数量小于等于3),无法拼成正方形
        if(matchsticks.length <= 3){
            return false;
        }
        // 所有火柴长度求和必须为4的倍数,不然无法拼成正方形
        int totalLen = Arrays.stream(matchsticks).sum();
        if (totalLen % 4 != 0) {
            return false;
        }
        // 先用Arrays.sort从小到大排序,再从大到小排序,减少搜索量
        Arrays.sort(matchsticks);
        for (int i = 0, j = matchsticks.length - 1; i < j; i++, j--) {
            int temp = matchsticks[i];
            matchsticks[i] = matchsticks[j];
            matchsticks[j] = temp;
        }
        // 存放4条边
        int[] edges = new int[4];
        // 给dfs传入的参数分别是:索引、matchsticks数组、存放边长的edges数组,边长的长度(由总长度除以4得到)
        return dfs(0, matchsticks, edges, totalLen / 4);
    }

    public boolean dfs(int index, int[] matchsticks, int[] edges, int len) {
        if (index == matchsticks.length) {
            return true;
        }
        // 开始循环遍历edges数组并赋值(因为matchsticks数组已经从小到大排序好,直接把matchsticks数组中的元素一个个累加进去,在if判断时递归),经过递归的处理,它能让edges数组上的元素和边长(len)相等
        for (int i = 0; i < edges.length; i++) {
            edges[i] += matchsticks[index];
            if (edges[i] <= len && dfs(index + 1, matchsticks, edges, len)) {
                return true;
            }
            edges[i] -= matchsticks[index];
        }
        // 上面的步骤中没有走到return true,说明不能用所有火柴拼成正方形
        return false;
    }
}

执行结果:

 

 

开始这个题目对我来说真的难度还是挺大的,尤其对于DFS-深度优先搜索不太清楚的我。接下来,我们先讲讲DFS一些东西。便于更好的理解这道题目解法。

大O标记法-时间复杂度(Time Complexity):

O(1) 常数

    public static void main(String[] args) {
        int n = 10;
        System.out.println("hello n = " + n);
    }

O(log n)  对数

 对数公式是数学中的一种常见公式,如果a^x=N(a>0,且a≠1),则x叫做以a为底N的对数,记做x=log(a)(N),其中a要写于log右下。其中a叫做对数的底,N叫做真数 。通常我们将以10为底的对数叫做常用对数,以e为底的对数称为自然对数。

    public static void main(String[] args) {
        int n = 1024;
        int count = 1;
        for (int i = 1; i <= n; i = i * 2) {
            System.out.println("第" + count + "次循环");
            System.out.println("hello i = " + i);
            count++;
        }
    }

运行结果:

简单这样理解:之前需要运行N次才能完成,现在(i=i*2)我只需要运行logN次就能结束了

O(n)  线性

    public static void main(String[] args) {
        int n = 10;
        for (int i = 1; i <= n; i++) {
            System.out.println("hello i = " + i);
        }
    }

O(n^2)  平方

    public static void main(String[] args) {
        int n = 10;
        for (int i = 1; i <= n; i++) {
            System.out.println("hello i = " + i);
            for (int j = 1; j <= n; j++) {
                System.out.println("hello j = " + j);
            }
        }
    }

O(n^3)  立方

    public static void main(String[] args) {
        int n = 10;
        for (int i = 1; i <= n; i++) {
            System.out.println("hello i = " + i);
            for (int j = 1; j <= n; j++) {
                System.out.println("hello j = " + j);
                for (int k = 1; k <= n; k++) {
                    System.out.println("hello k = " + k);
                }
            }
        }
    }

O(2^n)  指数

    public static void main(String[] args) {
        int n = 2;
        int count = 1;
        for (int i = 1; i <= Math.pow(2, n); i++) {
            System.out.println("第" + count + "次循环");
            System.out.println("hello i = " + i);
            count++;
        }
    }

O(n!) 阶乘

 

广度优先搜索(Breadth First Search)

(37条消息) 【算法入门】广度/宽度优先搜索(BFS)_raphealguo的博客-CSDN博客_bfs算法

 

深度优先搜索(Depth First Search)

(37条消息) java实现-深度优先搜索_Longtermevolution的博客-CSDN博客_java深度优先搜索

 

posted @ 2022-06-04 11:32  chch213  阅读(71)  评论(0编辑  收藏  举报