前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《剑指offer》专题—算法训练 day04

《剑指offer》专题—算法训练 day04

作者头像
RAIN7
发布2021-10-08 16:20:09
2390
发布2021-10-08 16:20:09
举报
文章被收录于专栏:RAIN7 de 编程之路

《剑指offer》专题—算法训练day04

一、反转链表

https://www.nowcoder.com/practice/75e878df47f24fdc9dc3e400ec6058ca?

思路一

定义三个指针,进行迭代,整体右移,边移动,边翻转,保证不会断链

原链表

第一次循环结束

第二次循环结束

第三次循环结束,跳出循环

最后两个节点进行翻转

原头节点的next 置为 null,更换新的头节点

相关代码

代码语言:javascript
复制
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
       // 设置三个引用指向连续的三个节点
        
        // 如果这个链表中 只有一个节点或者 没有节点时 ,直接返回 head
        if(head== null || head.next == null){
            return head;
        }
        
        // 不带头节点,至少还有2个节点
        ListNode left = head; // 指向第一个节点
        ListNode mid = left.next;// 指向第二个节点
        ListNode right = mid.next; // 指向第三个节点 ,可能为null
        
        while(right != null){
            // 翻转操作
             mid.next = left;
       // 将中间节点的next 置为 前一个节点
            
            // 平移这三个节点
            left = mid;
            mid = right;
            right = right.next;
        }
        
        // 当上面这个循环走完时,最后一个节点 mid 还未反转,或者 这个链表中就只有两个节点
        mid.next = left;
        // 反转完毕后,头节点的next 置为 null
        head.next = null;
       // 反转后的开始节点置为头节点
        head = mid;
        
        return head;
    }
}

思路二

可以采取头插法的思想进行翻转,可以每次把链表的第一个节点拿下来,头插进一个新的链表当中

相关代码

头插法进行反转链表

代码语言:javascript
复制
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {

        // 头插法进行反转链表
        
        ListNode new_head = null;
        while(head!=null){
            // 把原链表的第一个节点拿下来
            ListNode p = head;
            // 第一个节点继续指
           head = head.next;
            
            // 然后这个节点头插进入新的链表当中
            p.next = new_head;
            new_head = p;
        }
        
        return new_head;
    }
}

二、合并有序链表

https://www.nowcoder.com/practice/d8b6b4358f774294a89de2a6ac4d9337?

思路一

有傀儡节点

代码语言:javascript
复制
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
  if(list1 ==null){
           return list2;
       }

       if(list2 == null){
           return list1;
       }
        
     // 建立一个傀儡节点
         ListNode newHead = new ListNode(0);
         ListNode tmp = newHead;

         while(list1!=null && list2 !=null){
             if(list1.val <list2.val){
                 tmp.next = list1;
                 tmp = tmp.next;
                 list1 = list1.next;
             }else{
                 tmp.next = list2;
                 tmp = tmp.next;
                 list2 = list2.next;
             }
         }

         if(list1 == null){
             tmp.next = list2;
         }

         if(list2 ==null){
             tmp.next = list1;
         }

         return newHead.next;
    }
}

思路二

设立一个新的链表,同时定义头尾指针, 1.找到我们需要插入的节点 2.在原来表中删去该节点 3.将该节点尾插到新的链表当中

相关代码

无傀儡节点

代码语言:javascript
复制
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1==null){
            return list2;
        }
        
        if(list2 ==null){
            return list1;
        }
        
        ListNode new_head = null;// 新链表的头指针
        ListNode new_end = null; // 新链表的尾指针
        
        while(list1!=null && list2!=null){
            //1.找到我们要删除的节点
            ListNode p = list1.val<list2.val?list1:list2;
            
            // 2.在原链表中删除节点
            if(p == list1){
                list1 = list1.next;
            }else{
                list2 = list2.next;
            }
            
            //3.放入新链表中
            
            //3.1第一次插入节点|| 其他的情况
            if(new_head == null){
                new_head = p;
                new_end = p;
            }else{
                //3.2 如果不是第一次插入,那么我们就将这个节点进行尾插
                new_end.next = p;
                new_end = p;
            }
        }
        
        // 如果两个链表的长度不一样,那么就会出现 
        // list1 == null || list2 == null
        
        if(list1 == null){
            new_end.next = list2;
        }
        
        if(list2 == null){
            new_end.next = list1;
        }
        
        return new_head;
    }
}

递归思路

重复的过程用递归来进行表示,缩小问题的规模

代码语言:javascript
复制
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1==null){
            return list2;
        }
        
        if(list2 ==null){
            return list1;
        }
        
        ListNode head = null;// 新链表的头指针

             if(list1.val <list2.val){
                 head = list1;
                 list1 = list1.next;
             }else{
                 head = list2;
                 list2 = list2.next;
             }
        head.next = Merge(list1,list2);
        
        return head ;
    }
}

三、树的子结构

https://www.nowcoder.com/practice/6e196c44c7004d15b1610b9afca8bd88?

思路

二叉树都是递归定义的,所以递归操作是比较常见的做法 首先明白:子结构怎么理解,可以理解成子结构是原树的子树(或者一部分) 也就是说,B要是A的子结构,B的根节点+左子树+右子树,都在A中存在且构成树形结构

比较的过程要分为两步 1.先确定起始位置 2.在确定从该位置开始,后续的左右子树的内容是否一致

相关代码

代码语言:javascript
复制
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    
    public boolean isSameChild(TreeNode root1,TreeNode root2){
        // 这个函数用来判断左右子树是否相等
        if(root2 ==null){
//             原子树全部遍历完,说明左右子树相等
            return true;
        }
        if(root1 == null){
//             目标子树全部遍历完,说明左右子树不相等
            return false;
        }
        
        if(root1.val != root2.val){
            return false;
        }
        
        return isSameChild(root1.left,root2.left ) && isSameChild(root1.right,root2.right);
        
    }
    
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        
        if(root1 == null || root2== null){
            return false;
        }
        
        boolean result = false;
//         1.先找对应的起始位置
        if(root1.val == root2.val){
            // 此时判断左右子树是否相等
            result = isSameChild(root1,root2);
        }
        
        // 如果resule 为 false ,那么没找到起始位置,继续从左子树找
        if(result != true){
            result = HasSubtree(root1.left,root2);
        }
        
        // 如果result 为 false ,那么没找到 起始位置,继续从右子树找
        if(result !=true){
            result = HasSubtree(root1.right,root2);
        }
        
        return result;
        
    }
}

四、镜像二叉树

https://www.nowcoder.com/questionTerminal/a9d0ecbacef9410ca97463e4a5c83be7

思路

二叉树的常规操作是递归思路,缩小问题的规模 这道题镜像二叉树,我们可以看到整颗树的左右子树都交换位置,我们缩小问题的规模,变成每颗子树的问题,每颗子树我们都需要进行交换左右子树的位置,进行递归操作.

相关代码

代码语言:javascript
复制
import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param pRoot TreeNode类 
     * @return TreeNode类
     */
    public TreeNode Mirror (TreeNode pRoot) {
        // write code here
        
        if(pRoot == null){
            return null;
        }
        TreeNode temp = pRoot.right;
        pRoot.right = pRoot.left;
        pRoot.left = temp;
        
        Mirror(pRoot.left);
        Mirror(pRoot.right);
        
        return pRoot;
        
    }
}

  好了,今天的内容就结束了,希望大家多多练习~~

谢谢欣赏!!!

《剑指offer》 算法训练day5 敬请期待…

未完待续…

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/10/03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 《剑指offer》专题—算法训练day04
  • 一、反转链表
    • 思路一
      • 思路二
      • 二、合并有序链表
        • 思路一
          • 思路二
            • 递归思路
            • 三、树的子结构
              • 思路
              • 四、镜像二叉树
                • 思路
                • 未完待续…
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档