第三课刷题

目录:

1、通过有序数组生成平衡搜索二叉树

2、二叉树的序列化和反序列化

3、将整数字符串转成整数值

4、跳跃游戏

5、在有序但含有空的数组中查找字符串

6、斐波那契系列问题的递归和动态规划

 
通过有序数组生成平衡搜索二叉树
【题目一】
给定一个有序数组sortArr,已知其中没有重复值,用这个有序数组生成一棵平衡搜索二叉树,并且该搜索二叉树中序遍历的结果与sortArr一致。

【思路】

1、平衡搜索二叉树:左子树和右子树的深度相差不超过1

2、对有序数组arr,获取中心位置(length/2)以中心位置为根节点,0~左边给我生成平衡搜索二叉树,右边~length-1给我生成平衡搜索二叉树,递归行为

【Code】

public static Node sortArr2Tree(int[] sortArr)
    {
        if(sortArr==null)
            return null;
        return help(sortArr, 0, sortArr.length-1);
    }
    //帮助数组,将数组上start位置到end位置变成平衡搜索二叉树
    public static Node help(int[] arr,int start,int end) {
        if(start > end)
            return null;
        int mid = (start+end)/2;//生成头结点
        Node head = new Node(arr[mid]);
        //对左右子树递归生成树
        head.letf = help(arr, start, mid-1);
        head.right = help(arr, mid+1, end);
        //最终返回头结点
        return head;
    }

【题目二】

二叉树的序列化和反序列化
【题目】
二叉树被记录成文件的过程叫作二叉树的序列化,通过文件内容重建原来二叉树的过程叫作二叉树的反序列化。给定一棵二叉树的头节点head,并已知二叉树节点值的类型为32位整型。请设计一种二叉树序列化和反序列化的方案,并用代码实现。
【要求】
1,实现先序遍历序列化与反序列化
2,实现按层遍历序列化与反序列化

【Code】

public static class Node
    {
        public int value;
        public Node letf;
        public Node right;
        public Node(int data) {
            // TODO Auto-generated constructor stub
            this.value = data;
        }
    }
    //先序顺序序列化
    public static String xuLiehuaByPre(Node head)
    {
        if(head==null)
            return "#!";
        String reS = head.value + "!";
        reS +=xuLiehuaByPre(head.letf);
        reS +=xuLiehuaByPre(head.right);
        return reS;
    }
    //反序列化
    public static Node FanXuLieByPreString(String preStr)
    {
        //将序列按!分隔符分开
        String[] value = preStr.split("!");
        Queue<String>queue = new LinkedList<String>();
        for(int i = 0;i!=value.length;i++)
            queue.offer(value[i]);
        return reconPreOrder(queue);
    }
    public static Node reconPreOrder(Queue<String> queue)
    {
        String value = queue.poll();
        if(value.equals("#"))
            return null;
        Node head = new Node(Integer.valueOf(value));
        head.letf = reconPreOrder(queue);
        head.right = reconPreOrder(queue);
        return head;
    }
    //按层遍历序列化
    public static String XuLieHuaByLevel(Node head)
    {
        if(head==null)
            return "#!";
        String reS = head.value+"!";
        Queue<Node>queue = new LinkedList<class2.Node>();
        queue.offer(head);
        while(!queue.isEmpty())
        {
            //其实就是宽度优先遍历
            head = queue.poll();
            if(head.letf!=null) 
            {
                //左子树不为空,将左子树值加上
                reS +=head.letf.value+"!";
                queue.offer(head.letf);
            }
            else {
                reS+="#!";
            }
            if(head.right!=null)
            {
                reS+=head.right.value+"!";
                queue.offer(head.right);
            }
            else {
                reS+="#!";
            }
        }
        return reS;
    }
    //层次遍历的反序列化
    public static Node reconByLevelString(String levelStr)
    {
        String[] value = levelStr.split("!");
        int index =0 ;
        Node head =generateNodeByString(value[index++]);
        Queue<Node>queue = new LinkedList<class2.Node>();
        if(head!=null)
            queue.offer(head);
        Node node = null;
        while(!queue.isEmpty())
        {
            node = queue.poll();
            node.letf = generateNodeByString(value[index++]);
            node.right = generateNodeByString(value[index++]);
            if(node.letf!=null)
                queue.offer(node.letf);
            if(node.right!=null)
                queue.offer(node.right);
        }
        return head;
     }
    //根据树的值建立树节点并返回
    public static Node generateNodeByString(String val) {
        if(val.equals("#"))
            return null;
        return new Node(Integer.valueOf(val));
    }

【题目三】 

将整数字符串转成整数值

 给定一个字符串str,如果str符合日常书写的整数形式,并且属于32 位整数的范围,返回str所代表的整数值,否则返回0

【举例】

str="123",返回123

str="023",因为"023"不符合日常的书写习惯,所以返回0

str="A13",返回0

str="0",返回0

str="2147483647",返回2147483647

str="2147483648",因为溢出了,所以返回0

str="-123",返回-123

【思路】

先穷举出字符串有哪些非法形式

1、头位置不为负号- 的同时也不属于0~9之间

2、头位置为负号-且长度为1 即仅仅只有一个负号

3、头位置为负号且第二位置为0 即-0

4、头位置为0且长度大于1 则为0213之类,也非法

5、从1位置往后遍历整个字符串,如果出现非0~9的字符则非法,即A13情况  

我们先提前统一当做负数来转,记下头位置是否是负号,最后再根据符号位将结果转化

理由: 

  由于题干说字符串属于32位整数的范围。可以打印一下Integer的系统最小是-214748364,系统最大是2147483647,如果按照正数转的话,当其为系统最小时,正数是无法表示的,会溢出。此时系统最小便无法转化。

 

【Code】

public static int convert(String str)
    {
        //空串直接返回
        if(str == null || str.equals(""))
            return 0;
        char[] chas = str.toCharArray();
        //先判断字符串是否合规
        if(!isValid(chas))
            return 0;
        boolean flag = chas[0]=='-'? false:true;
        int minq = Integer.MIN_VALUE/10;
        int minr = Integer.MIN_VALUE;
        int res = 0;
        int cur = 0;
        //如果是正数从0位置开始。如果是负数从1位置开始
        for(int i = flag?0:1;i<chas.length;i++)
        {
            //获得负数,即 chas[i]=2 则 cur = -2
            cur = '0' - chas[i];
            //minq是系统最小除以10
            //如果res比系统最小除以10还要小,下面的res=res*10+cur必定会溢出
            //当res是系统最小除以10时,往后要加上cur这个尾数
            //如果cur比系统最小的尾数还要小,则后面操作也会溢出
            if((res<minq)|| ( res == minq && cur < minr))
                return 0;
            res = res*10+cur;
        }
        if(flag && res == Integer.MIN_VALUE)
            return 0;
        return flag? -res:res;
    }
    public static boolean isValid(char[] chas)
    {
        //类似a34 sb351
        if(chas[0]!='-' && (chas[0]<'0' || chas[0] > '9'))
            return false;
        //类似 -  -0
        if(chas[0] == '-' && (chas.length==1 || chas[1] == '0'))
            return false;
        //类似 0325 0221
        if(chas[0]=='0' && chas.length>1)
            return false;
        //类似341a56
        for(int i = 1;i<chas.length;i++)
        {
            if(chas[i] < '0' || chas[i] > '9')
                return false;
        }
        return true;
    }

 

跳跃游戏

【题目四】

给定数组arr,arr[i]==k代表可以从位置i向右跳1~k个距离。比如,arr[2]==3,代表从位置2可以跳到位置3、位置4或位置5。如果从位置0出发,返回最少跳几次能跳到arr最后的位置上。

【举例】

arr=[3,2,3,1,1,4]。

arr[0]==3,选择跳到位置2;arr[2]==3,可以跳到最后的位置。

所以返回2。

【要求】

如果arr长度为N,要求实现时间复杂度为O(N)、额外空间复杂度为O(1)的方法。

【思路】

设立next指针和cur指针

1、next指针表示如果走k+1步时能够到达的最右位置

2、cur指针表示当前走k步能够到达的最右位置

【Code】

public static int jump(int[] arr)
    {
        int jump = 0;
        int next = 0;
        int cur = 0;
        for(int i = 0;i<arr.length;i++)
        {
            if(cur<i)
            {
                jump++;
                cur = next;
            }
            next = Math.max(next, arr[i]+i);
        }
        return jump;
    }

 

在有序但含有空的数组中查找字符串
【题目五】
给定一个字符串数组strs[],在strs中有些位置为null,但在不为null的位置上,其字符串是按照字典顺序由小到大依次出现的。再给定一个字符串str,请返回str在strs中出现的最左的位置。
【举例】
strs=[null,"a",null,"a",null,"b",null,"c"],str="a",返回1。
strs=[null,"a",null,"a",null,"b",null,"c"],str=null,只要str为null,就返回-1。
strs=[null,"a",null,"a",null,"b",null,"c"],str="d",返回-1。

 

 

 

斐波那契系列问题的递归和动态规划
【题目六】
给定整数N,返回斐波那契数列的第N项。
【补充题目1】
给定整数N,代表台阶数,一次可以跨2个或者1个台阶,返回有多少种走法。
【举例】
N=3,可以三次都跨1个台阶;也可以先跨2个台阶,再跨1个台阶;还可以先跨1个台阶,再跨2个台阶。所以有
三种走法,返回3。
【补充题目2】
假设农场中成熟的母牛每年只会生1头小母牛,并且永远不会死。第一年农场有1只成熟的母牛,从第二年开始,
母牛开始生小母牛。每只小母牛3年之后成熟又可以生小母牛。给定整数N,求出N年后牛的数量。
【补充题目3】
0左边必有1的二进制字符串数量
【题目描述】
给定一个整数N,求由"0"字符与"1"字符组成的长度为N的所有字符串中,满足"0"字符的左边必有"1"字符的字符
串数量。
【举例】
N=1。只由"0"与"1"组成,长度为1的所有字符串:"0"、"1"。只有字符串"1"满足要求,所以返回1。
N=2。只由"0"与"1"组成,长度为2的所有字符串为:"00"、"01"、"10"、"11"。只有字符串"10"和"11"满足要求,
所以返回2。
N=3。只由"0"与"1"组成,长度为3的所有字符串为:"000"、"001"、"010"、"011"、"100"、"101"、"110"、"111"。
字符串"101"、"110"、"111"满足要求,所以返回3。

 

posted @ 2021-03-03 16:59  γGama  阅读(82)  评论(0编辑  收藏  举报