hot100补充(5题一组)

 

//f(i)表示以i为根的二叉树的搜索树个数,所以n的全部的搜索树个数G(n)
// G(n)=f(1)+f(2)+f(3)+f(4)+...+f(n)

// 当 i 为根节点时,其左子树节点个数为 i-1 个,右子树节点为 n-i,则左子节点二叉排序树的个数*右子节点二叉排序树的个数就是当i为根节点时候二叉排序树的个数
// f(i) = G(i−1)∗G(n−i)

// 综合两个公式可以得到 卡特兰数 公式
//G(n)=G(0)∗G(n−1)+G(1)∗(n−2)+...+G(n−1)∗G(0)



class Solution {
    public int numTrees(int n) {
        int[] G = new int[n+1];
        G[0] = 1;
        G[1] = 1;
        //反正一个i一个j尝试的方式比着上面公式写进去
        for (int i = 2; i < n + 1; i++) {
            for (int j = 1; j < i + 1; j++) {
                G[i] += G[j - 1] * G[i - j];
            }
        }
        return G[n];
    }
}

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
 //看成只有左子树右子树和根,重点是前序遍历第一个肯定是根,从中序遍历中找到这个节点,
 //然后左边是左子树,右边是右子树,以此递归构建树
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        //两个数长度一样,也一个的长度就行
        if (preorder.length == 0) return null;
        TreeNode root = new TreeNode(preorder[0]);
        for (int i = 0; i < preorder.length; i++) {
            if (preorder[0] == inorder[i]) {
                root.left = buildTree(Arrays.copyOfRange(preorder, 1, i + 1), 
                //类似的copyOfRange这种方法都是包含前不包含尾
                Arrays.copyOfRange(inorder, 0, i));
                
                root.right = buildTree(Arrays.copyOfRange(preorder, i + 1, preorder.length),
                Arrays.copyOfRange(inorder, i + 1, inorder.length));
                break;
            }
        }
        return root;
    }
}

 

 

//先去重,在从最小的那个数开始找保存最长的连续序列
class Solution {
    public int longestConsecutive(int[] nums) {
        HashSet<Integer> set = new HashSet<>();
        for (int x : nums) {
            set.add(x);
        }
        int res = 0;
        for (int x : set) {
            //从最小的开始找
            if (!set.contains(x - 1)) {
                //把x拿出来,不操作原set中数据
                int num = x;
                int curMaxXL = 1;
                //找比他大的记录为连续的序列,记录连续序列长度
                while (set.contains(num + 1)) {
                    num++;
                    curMaxXL++;
                }
                res = Math.max(res, curMaxXL);
            }
        }
        return res;
    }
}

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
// class Solution {
//     public ListNode sortList(ListNode head) {
//         return sortList(head, null);
//     }
//     //归并排序
//     //方法重载
//     public ListNode sortList(ListNode head, ListNode tail) {
//         //不进入这个递归的情况
//         if (head == null) return head;
        
//         //递归结束的条件
//         if (head == tail) 

//         //递归要做什么,返回什么
//         //要给表排序,分而治之,归并排序
//         ListNode slow = head;
//         ListNode fast = head;
//         //快的到了,慢的走到一半
//         //避免空指针,好像还是不用xxx.next作为判断条件比较多
//         while (fast != tail) {
//             slow = slow.next;
//             fast = fast.next;
//             if (fast != tail) {
//                 fast = fast.next;
//             }
//         }
//         ListNode mid = slow;
//         ListNode l1 = sortList(head, mid);
//         ListNode l2 = sortList(mid, tail);
//         ListNode sorted = merge(l1, l2);
//         return sorted;

//     }
// }
class Solution {
    public ListNode sortList(ListNode head) {
        return sortList(head, null);
    }

    public ListNode sortList(ListNode head, ListNode tail) {
        if (head == null) {
            return head;
        }
        //分而治之,归并排序是分到一个为止,head后面是tail,然后让其变成真正的null
        if (head.next == tail) {
            head.next = null;
            return head;
        }
        ListNode slow = head, fast = head;
        //不使用fast.next.next的原因是这样可以更好的划分,比如4个链表的时候把前2个划出去
        while (fast != tail) {
            slow = slow.next;
            fast = fast.next;
            if (fast != tail) {
                fast = fast.next;
            }
        }
        ListNode mid = slow;
        //tail是当作null处理的。所以是这么传入,其实前面的l1中mid是null
        ListNode l1 = sortList(head, mid);
        ListNode l2 = sortList(mid, tail);
        ListNode sorted = merge(l1, l2);
        return sorted;
    }

public ListNode merge(ListNode l1, ListNode l2) {
        if (l1 == null) return l2;
        if (l2 == null) return l1;
        ListNode pre = new ListNode(-1);
        ListNode cur = pre;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            } else { 
                cur.next = l2;
                l2 = l2.next;
            }   
            cur = cur.next;
        }
        cur.next = l1 == null ? l2 : l1;
        return pre.next;
}
}

 

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public void flatten(TreeNode root) {
        List<TreeNode> list = new ArrayList<TreeNode>();
        Deque<TreeNode> stack = new LinkedList<>();
        while (root != null || !stack.isEmpty()) {
            if (root != null) {
                stack.push(root);
                list.add(root);
                root = root.left;
            } else {//root==null&&stack不为空 
                root = stack.pop();
                root = root.right;
            }
        }
        for(int i = 1; i < list.size(); i++) {
            TreeNode pre = list.get(i - 1), cur = list.get(i);
            pre.left = null;
            pre.right = cur;
        }
    }
    //输出显示都是从上到下从左到右的层序遍历
    
   
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值