剑指Offer系列之题16~题20
16.反转链表
输入一个链表,反转链表后,输出新链表的表头。
从前往后,依次将当前节点的next指向前结点。用多个变量存储当前节点,下一节点,前结点。
public class Solution {
    public ListNode ReverseList(ListNode head) {
        if(head==null)
            return null;
        //从头开始,依次将节点的next指向前一个结点
        ListNode prev=null;
        ListNode cur=head;
        ListNode follow=null;
        while(cur.next!=null){
            follow=cur.next;//获得当前结点的下个节点
            cur.next=prev;//将当前节点的next指向前一个结点
            prev=cur;//保存当前结点作为前结点
            cur=follow;
        }
        cur.next=prev;
        return cur;
    }
}
17.合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
基本:遍历两链表,当l2中元素小于l1时,将其加入l1,直到末尾。或者新建一个链表,将小的依次加入该链表
1.暴力:
/*添加至list1*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        //结果要求是单调递增
        //错误输入的判断
        if(list1==null && list2 ==null)
            return null;
        if(list1== null)
            return list2;
        if(list2==null)
            return list1;
        ListNode p1=list1;
        ListNode p2=list2;
        ListNode temp1=null;//暂存两链表的结点
        ListNode temp2=null;
        //依次从链表头开始判断
        while(p1!=null && p2!=null ){
            while(p1!=null && p1.val<p2.val){//当l1的结点小于l2时,将l1结点右移
                temp1=p1;//记录当前结点,便于后续插入
                p1=p1.next;
            }//直到p1.val >= p2.val或p1.next==null
            if(p1==null){//若l1已到末尾,则将l2的结点接到l1末尾后
                temp1.next=p2;
                return list1;
            }
            temp2=new ListNode(p2.val);//list2的结点移到list1
            temp2.next=p1;
            if(temp1!=null)//判断是否是添加到l1的头部
                temp1.next=temp2;
            else{//是则让list1头节点变为temp2
                list1=temp2;
            }
            p1=temp2;//该结点一定比l2的下一节点小,所以temp1下一步一定会切换
            if(p2.next==null)//如果l2遍历完毕
                break;
            p2=p2.next;//p2右移
        }
        return list1;
    }
}
2.递归:
/*相当于一个新链表*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        //结果要求是单调递增
        //错误输入的判断
        if(list1==null && list2 ==null)
            return null;
        if(list1== null)
            return list2;
        if(list2==null)
            return list1;
        //递归
        if(list1.val <=list2.val){
            list1.next=Merge(list1.next,list2);
            return list1;
        }else{
            list2.next=Merge(list1,list2.next);
            return list2;
        }
    }
}
3.新建链表存储:
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        //新建一个头节点,用来存合并的链表。
        ListNode head=new ListNode(-1);
        head.next=null;
        ListNode root=head;
        while(list1!=null && list2!=null){
            if(list1.val<list2.val){
                head.next=list1;
                head=list1;
                list1=list1.next;
            }else{
                head.next=list2;
                head=list2;
                list2=list2.next;
            }
        }
        //把未结束的链表连接到合并后的链表尾部
        if(list1!=null){
            head.next=list1;
        }
        if(list2!=null){
            head.next=list2;
        }
        return root.next;
    }
}
18.树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
先判断A中根节点是否等于B根节点,相等则对两者左右子树进行遍历判断是否相等;
若根节点不等,则从A的左右子树中寻找等于B中根节点的节点,然后判断。
递归
递归:
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root1 ==null || root2 == null)//输入判断
            return false;
        boolean flag=false;
        //查看2的前序和中序遍历是否属于1
        if (root1.val == root2.val){//当A的根结点等于B的根节点时,对其子树进行遍历判断(递归)
            flag=judgeSub(root1,root2);
        }
        if(!flag)//当A的根节点不等于B的根节点时,从根节点的左子树中查找相等的节点
            flag=HasSubtree(root1.left,root2);
        if(!flag)//从根节点的右子树中查找相等的节点
            flag=HasSubtree(root1.right,root2);
        return flag;
    }
    //根节点相等时,判断其结构是否相等
    public boolean judgeSub(TreeNode root1,TreeNode root2){
        if(root2==null)//若B节点为空,则证明该节点前结构属于A,因为前面的已证过相等,不然不会走到该步
            return true;
        if(root1==null)//若A节点为空,则两者结构不等
            return false;
        if(root1.val != root2.val)
            return false;
        return judgeSub(root1.left,root2.left) && judgeSub(root1.right,root2.right);//递归判断左右子树是否相等
    }
}
19.二叉树的镜像
操作给定的二叉树,将其变换为源二叉树的镜像。
    输入描述:
二叉树的镜像定义:
     源二叉树
        8
       /  \
      6   10
     / \  / \
    5  7 9 11
    镜像二叉树
        8
       /  \
      10   6
     / \  / \
    11 9 7  5
递归处理左右子树
递归:
public class Solution {
    public void Mirror(TreeNode root) {
        if(root!=null){
            //根节点不变,左右子树交换位置
            //递归
            if(root.left!=null ){//若根节点左右子树非空,则将左右子树进行翻转
                Mirror(root.left);
            }
            if(root.right!=null)
                Mirror(root.right);
            TreeNode temp=root.left;
            root.left=root.right;
            root.right=temp;
        }
    }
}
20.顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10。
找到每次遍历的起始点,然后以此进行判断每次遍历的边界。(每次遍历前一定要判断前置条件)
1.暴力:
import java.util.ArrayList;
public class Solution {
    private ArrayList<Integer> result=new ArrayList<>();
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        if(matrix==null || matrix.length==0)
            return null;
        int rows=matrix.length;
        int cols=matrix[0].length;
        int start=0;
        //找出每一圈的起始点。即左上角的点,(0,0) (1,1)等
        while(rows>start*2 && cols>start*2){
            int endCol=cols-1-start;//该次遍历时最右边列的坐标
            int endRow=rows-1-start;//该次遍历时最下边行的坐标
            for(int i=start;i<=endCol;++i){//打印第一行
                result.add(matrix[start][i]);
            }
            if(start<endRow){//满足才有一列可以打印,否则一行直接打印完毕
                for(int i=start+1;i<=endRow;++i){//打印最后一列
                    result.add(matrix[i][endCol]);
                }
            }
            if(start<endCol && start<endRow){//满足才有最后一行可以打印
                for(int i=endCol-1;i>=start;--i){//打印最后一行
                    result.add(matrix[endRow][i]);
                }
            }
            if(start<endCol && start< endRow-1){//满足时才会在最后一行打印完毕后仍有上面的行
                for(int i=endRow-1;i>start;--i){//打印第一列
                    result.add(matrix[i][start]);
                }
            }
            start++;
        }
        return result;
    }
}
如有错误,欢迎指正
剑指Offer系列之题16~题20的更多相关文章
- 剑指offer——python【第16题】合并两个有序链表
		
题目描述 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1->1-& ...
 - 干货 | 剑指offer系列文章汇总
		
下面是名企面试中经常会出现的面试题目,大家可以戳相应的题目查看题目细节,其答案会在紧接着的后一篇中出现 剑指offer系列 始 剑指offer—灯管问题(1) 剑指offer—10人电梯(2) ...
 - 剑指offer——python【第54题】字符流中第一个不重复的字符
		
题目描述 请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g".当从该字符流中读出 ...
 - 7、斐波那契数列、跳台阶、变态跳台阶、矩形覆盖------------>剑指offer系列
		
题目:斐波那契数列 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0). f(n) = f(n-1) + f(n-2) 基本思路 这道题在剑指offe ...
 - 剑指Offer系列之题1~题5
		
目录 1.二维数组的查找 2.替换空格 3.从尾到头打印链表 4.链表中环的入口节点 5.重建二叉树 写在前面:本随笔中包含五道题:题目描述,题目思路以及对应解法. 1.二维数组的查找 在一个二维数组 ...
 - 剑指offer——python【第60题】把二叉树打印成多行
		
题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行.#类似于二维列表[[1,2],[4,5]] 解题思路 其实这倒题和其他类似的题有所区别,这里是分层打印,把每层的节点值放在同一 ...
 - 剑指offer——python【第28题】数组 中出现次数超过一半的数字
		
题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
 - 《剑指offer》第二十六题(树的子结构)
		
// 面试题26:树的子结构 // 题目:输入两棵二叉树A和B,判断B是不是A的子结构. #include <iostream> struct BinaryTreeNode { doubl ...
 - 剑指offer——python【第23题】二叉搜索树的后序遍历序列
		
题目描述 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 解题思路 首先要清楚,这道题不是让你去判断一个给定 ...
 
随机推荐
- 基于Canal和Kafka实现MySQL的Binlog近实时同步
			
前提 近段时间,业务系统架构基本完备,数据层面的建设比较薄弱,因为笔者目前工作重心在于搭建一个小型的数据平台.优先级比较高的一个任务就是需要近实时同步业务系统的数据(包括保存.更新或者软删除)到一个另 ...
 - Eureka停更了?试试Zookpper和Consul
			
在Spring Cloud Netflix中使用Eureak作为注册中心,但是Eureka2.0停止更新,Eureka1.0 进入了维护状态.就像win7一样,同样可以用,但是官方对于新出现的问题并不 ...
 - 实验一 Linux系统与应用准备(嵌入式Linux工程师的“修真之路”)
			
作业格式 项目 内容 这个作业属于哪个课程 这里是链接[https://edu.cnblogs.com/campus/nchu/2020SpringSystemAndApplication] 这个作业 ...
 - TCP粘包很难么,为何我屡屡受挫??
			
无论走到哪里,都应该记住,过去都是假的,回忆是一条没有尽头的路,一切以往的春天都不复存在,就连那最坚韧而又狂乱的爱情归根结底也不过是一种转瞬即逝的现实. --马尔克斯 本文已经收录至我的GitHub, ...
 - Netty源码分析之ChannelPipeline—出站事件的传播
			
上篇文章中我们梳理了ChannelPipeline中入站事件的传播,这篇文章中我们看下出站事件的传播,也就是ChannelOutboundHandler接口的实现. 1.出站事件的传播示例 我们对上篇 ...
 - Spark实战--寻找5亿次访问中,访问次数最多的人
			
问题描述 对于一个大型网站,用户访问量尝尝高达数十亿.对于数十亿是一个什么样的概念,我们这里可以简单的计算一下.对于一个用户,单次访问,我们通常会记录下哪些数据呢? 1.用户的id 2.用户访问的时间 ...
 - C语言 变量初始化二进制、八进制、十六进制
			
int a1 = 10; //十进制 int a2 = 0b10; //二进制 int a3 = 010; //八进制 int a4 = 0x10; //十六进制 打印的结果:
 - 记一次Maven发布Jar包中文乱码解决方法
			
Maven deploy 乱码 今天使用Maven发布Jar包时,发布功能都是正常的也成功上传到了仓库,就是项目跑越来后出中文中现了乱码: { "code": "SUCC ...
 - Mol Cell Proteomics. | Identification of salivary biomarkers for oral cancer detection with untargeted and targeted quantitative proteomics approaches (解读人:卜繁宇)
			
文献名:Identification of salivary biomarkers for oral cancer detection with untargeted and targeted qua ...
 - VMware 虚拟机正在使用中
			
1.出现报错信息: 2.找到安装目录下面的.lck后缀文件夹(如有多个则全部删除) 3.删除此文件夹 4.成功开启虚拟机