刷leetCode算法题+解析(八)

今天周一,刷题继续。

合并两个有序数组

给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。

说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]

思路:首先我记得以前做过类似的题,如果能不借助于list就要自排序,反正我首先用最笨但是每个人都会的方法把第一版本做出来了,当然性能低是意料之中的。

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        List<Integer> list = new ArrayList<Integer>();
        for(int i=0;i<m;i++){
            list.add(nums1[i]);
        }
        for(int i:nums2){
            list.add(i);
        }
        Collections.sort(list);
        for(int i=0;i<m+n;i++){
            nums1[i]=list.get(i);
        }
    }
}

第一版本做完了才开始有心情做第二个版本,从优化开始讲起,我接着开始分析题目,发现可以直接把nums2插入到nums1中,然后在Array.sort(),美滋滋,运行速度也快,然后出题的意义没了。还是老老实实自己写吧:

    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int [] arr = new int[m];
        for(int i=0;i<arr.length;i++){
            arr[i]=nums1[i];
        }
        int k = 0;
        int i = 0;
        int j = 0;
        while(i<m && j<n){
            if(arr[i]<nums2[j]){
                nums1[k]=arr[i];
                i++;
            }else{
                nums1[k]=nums2[j];
                j++;
            }
            k++;           
        }
        if(i<m){//说明数组1还有元素
            for(;i<m;i++){
               nums1[k]=arr[i];
               k++;
            }
        }else if(j<n){
            for(;j<n;j++){
               nums1[k]=nums2[j];
               k++;
            }
        }
    }

如图所示吧,其实这个返回值如果是自己定义的更简单了,但是因为返回的就是nums1,所以没办法,只能做一个nums1的副本arr,然后从头开始判断,双指针法,把arr和nums2按顺序插入nums1.得出的答案就是想要的。
本来我还以为这么麻烦会性能不太好呢,结果居然是0ms。
接着看了大神解析,很多用了递归啥的,不过因为我的方法可以了,所以也没仔细研究。其实想了很多思路。比如这个nums2插入到nums1.可不可以理解为把nums2的每一个元素,插入到有序数组nums1?这样循环下来也能满足需求,但是性能怎么样因为我没测试所以也不知道。然后今天因为工作原因,本来计划好的三道题都没做完,所以先不多想了,继续往下做。

相同的树

给定两个二叉树,编写一个函数来检验它们是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

(因为这个题的题目不好复制粘贴,所以直接截图)


image.png

思路:比较树、链表啥的,递归没跑了,所以重点就是怎么递归咯、因为树分左右两叉。所以结果也应该是两边都相等才能。这个因为做过类似的功能,所以直接上代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        //俩都是空则true
        if(p==null && q==null){
             return true;
        }
        //如果都不为空并且val相等才判断左节点右节点
        if(p!=null && q!=null && p.val==q.val){
             return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
        }else{
            //走到这说明一个空一个不是空,或者值不相等,直接返回false;
            return false;
        }     
    }
}

这道题比较简单,所以不多说了,而且因为我做过类似的,所以思路也很清晰。继续下一题、

对称二叉树

题目:给定一个二叉树,检查它是否是镜像对称的。(题目不好复制粘贴,所以截图)

image.png

思路:这个题我觉得跟上道题一起做简直是送分的,所谓的中间对称,不就是从中劈开,节点左子节点等于节点右子节点。反之亦然。上一个是相等,这一个是相反不就ok了,递归的方法很容易做出来:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        //我理解的对称的概念:从中劈开,左右一样
        if(root==null || (root.left==null && root.right==null)){
            return true;
        }
        if(root.left!=null && root.right!=null && root.left.val==root.right.val){
            return isSymmetric(root.left,root.right);
        }else{
            return false;
        }   
    }
    public boolean isSymmetric(TreeNode p,TreeNode q) {
        if(p==null && q==null){
            return true;
        }
        if(p!=null && q!=null && p.val==q.val){
            return isSymmetric(p.left,q.right) && isSymmetric(p.right,q.left);
        }else{
            return false;
        }
    }
}

这个前期判断有点麻烦,就是首先这个节点不是空节点,不然肯定是对称的,其次如果只有一个根节点肯定是对称的。
其次如果只有两个节点,那么这个一定要相等。这些都满足了才需要往下判断。
判断的方法就是上面的判断两个树是不是相等反过来而已,没什么可多数的。但是题目要求最好是递归和迭代两种方法,所以接下来继续看迭代的方法:
算了,迭代不出来了,直接看大神解析吧,虽然我不会,但是我已经预测到迭代应该就几行代码,然后看了豁然开朗。
好的,看了题解,然后发现了一句非常好的话:
一看就会,一写就废。
哈哈,继续说迭代法怎么比较对称吧。
这个题解里用了一种我不是很了解的数据结构,队列Queue。说实话这个数据格式我几乎没用过。然后这里如果是对称的树,从根节点不算,起码第二层的节点应该是相等的,然后对应的节点值一样,节点的子节点互相反转,也就是left=right。

public boolean isSymmetric(TreeNode root) {
    Queue<TreeNode> q = new LinkedList<>();
    q.add(root);
    q.add(root);
    while (!q.isEmpty()) {
        TreeNode t1 = q.poll();
        TreeNode t2 = q.poll();
        if (t1 == null && t2 == null) continue;
        if (t1 == null || t2 == null) return false;
        if (t1.val != t2.val) return false;
        q.add(t1.left);
        q.add(t2.right);
        q.add(t1.right);
        q.add(t2.left);
    }
    return true;
}

这个题说真的,我到现在还有点懵,只能说百分之八十理解百分之二十脑补。只能靠猜的。所以也就不多说了,今天就到这里了。
如果稍微帮到你了记得点个喜欢点个关注呦!也祝大家工作顺顺利利!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容