第三课刷题
【思路】
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;
}
【题目二】
【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;
}