递归、分治

第n个月后共有多少对兔子

/*
    * 题目描述:每对兔子每个月不多不少恰好能生一对(一雌一雄)新兔子,而且每对新生兔出生两个月后就成熟并具备生殖能力;
    * 另外,假定所有的兔子都不会死亡。假如养了初生的小兔一对,试问第n个月后共有多少对兔子?
    * 思路:
    * 现在兔子的数量=前一个月兔子的数量+新生兔子的数量
    * 前一个月兔子的数量:f(i-1)
    * 新生兔子的数量:f(n-2) (前两个月的兔子都具备生殖能力)
    * */
    public int NumberOfRabit(int i){
        if(i==0) return 1;
        if(i==1) return 1;
        return NumberOfRabit(i-1)+NumberOfRabit(i-2);
    }

集合划分

/*
    * 题目描述:给定正整数n 和 m,计算出n个元素的集合{1,2,…,n }可以划分为多少个不同的由 m 个非空子集构成的集合。
    * 思路:
    * n个元素的划分为m个子集的数量=n-1个元素划分为m-1个子集的数量+n-1个元素划分为m个子集的数量*m
    * 当n-1个元素划分为m-1个子集时,把第n个元素单独当成一个子集加入就好。
    * 当n-1个元素划分为m个子集时,把第n个元素往m个子集中任意一个插入,每个划分有m种插入方式。
    * 终止条件:
    * n<m或m==0时,0种插入方式
    * m==n或m==1时,1种插入方式
    * */
    public int numOfDivide(int n,int m){
        if(m==0||m>n) return 0;
        if(m==n||m==1) return 1;
        return numOfDivide(n-1,m-1)+numOfDivide(n-1,m)*m;
    }

给表达式加括号

 /*
    * 题目:给表达式加括号
    * 题目描述:Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are +, - and *.
    * 思路:从头开始遍历字符串,遇到'+','-','*',就把字符串分割为两部分递归处理, 将两部分的计算结果用列表保存返回。
    * 再把leftList和rightList的所有组合进行运算,将最终结果们保存到List中。
    * 递归过程中,当字符串中没有运算符号时说明整个字符串是一个数字,这种情况下,直接将字符串转为数字保存到list中即可
    * */
    public List<Integer> diffWaysToCompute(String input) {
        List<Integer> list = new LinkedList<>();
        boolean isNumber = true;
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if (c == '+' || c == '-' || c == '*') {
                isNumber = false;
                List<Integer> leftList = diffWaysToCompute(input.substring(0, i));
                List<Integer> rightList = diffWaysToCompute(input.substring(i + 1, input.length()));
                for (int leftElem : leftList) {
                    for (int rightElem : rightList) {
                        switch (c) {
                            case '+':
                                list.add(leftElem + rightElem);
                                break;
                            case '-':
                                list.add(leftElem - rightElem);
                                break;
                            case '*':
                                list.add(leftElem * rightElem);
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        }
        if (isNumber) {
            list.add(Integer.valueOf(input));
        }
        return list;
    }

不同的二叉搜索树

/*
    * 不同的二叉搜索树
    * 题目描述:给定一个数字 n,要求生成所有值为 1...n 的二叉搜索树。
    * 思路:每遍历到一个元素,就把该元素作为根节点,将数组以当前元素分割,分别将左列表和右列表构建为它的左右子树。
    * 注意,当左右子树没有值时,要把相应列表add一个null,返回给根节点
    * */
    public LinkedList<TreeNode> buldTree(int start, int end) {
        LinkedList<TreeNode> list = new LinkedList<>();
        if (start > end) list.add(null);
        for (int i = start; i <= end; i++) {
            LinkedList<TreeNode> left = buldTree(start, i - 1);
            LinkedList<TreeNode> right = buldTree(i + 1, end);
                for (TreeNode leftRoot : left) {
                    for (TreeNode rightRoot : right) {
                        TreeNode root = new TreeNode(i);//注意这里每次都要重新new
                        root.left = leftRoot;
                        root.right = rightRoot;
                        list.add(root);
                    }
            }
        }
        return list;
    }

最接近点对(减治)

题目描述:在二维空间内找到两个距离最近的点
思路:
在这里插入图片描述

  1. 选取一垂直线l: x = m来作为分割直线,其中m为S中各点x坐标的中位数。将S分割为S1和S2。
  2. 递归地在S1和S2上找出其最小距离d1和d2,并设d = min{d1, d2},S中的最接近点对是d,或者是某个{p, q},其中p∈S1且q∈S2。
  3. 候选点 p 和 q 到直线l 的距离不能超过d,则只需考虑区间P1和P2的范围;
  4. 考虑P1中任意一点p,它若与P2中的点q构成最接近点对的候选者,则必有distance(p,q)<d。满足这个条件的P2中的点一定落在一个d×2d的矩形R中;
  5. 由d的意义可知,P2中任何2个S中的点的距离都不小于d。由此可以推出矩形R中最多只有6个S中的点
    证明: 将矩形R的长为2d的边3等分,将它的长为d的边2等分,由此导出6个(d/2)×(2d/3)的矩形。若矩形R中有多于6个S中的点,则由鸽舍原理易知至少有一个(d/2)×(2d/3)的小矩形中有2个以上S中的点。设u,v是位于同一小矩形中的2个点,则(?/2)2+(2?/3)2=25/36 ?^2。distance(u,v)=5d/6<d。这与d的意义相矛盾。

算法描述:

预处理1: 对点集S按x轴从小到大排序;
预处理2: 对点集S按y轴从小到大排序放Y中,并记录各点对应S中的下标;
在这里插入图片描述
时间复杂度:T(n)=O(n)+O(n)+T(n/2)+T(n/2)+O(n)
T(n)=O(nlog(n))

线性时间选择(减治)

归并排序,逆序对(分治)

快速排序(分治)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值