LinkedList和ArrayList要好好研究一下
ArrayList和LinkedList的大致区别:
- ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构
- 对于随机访问的get和set方法,ArrayList要优于LinkedList
- 对于新增和删除操作add和remove,LinkedList比较占优势
个人理解可能是ArrayList是种顺序结构,而LinkedList是种链式结构,双向链表
ArrayList使用在查询比较多,但是插入和删除比较少的情况,而LinkedList用在查询比较少而插入删除比较多的情况
首先说ArrayList
关于ArrayList是import java.util.ArrayList;
包中的
list.add(data);//添加data到list尾部
list.add(index,data);//添加data到index位置
list.remove(index);//删除下标为index的data
list.removeRange(start,end);//删除下标从start到end结束的data
list.clear();//清空列表
list.get(index);//获得下标为index的数据
list.set(index,new_data);//修改下标为index的数据为new_data
list.contains(data);//包含data,返回true
list.indexOf(data);//返回data在列表中第一次出现的位置,没有该元素返回-1
list.last Index Of(data);//返回data在列表中最后一次出现的位置,没有该元素返回-1
list.isEmpty();//列表为空返回true
list.size();//返回列表长度
//对ArrayList进行遍历
for(Object obj:list){
对obj进行操作;
//还有一种Iterator遍历的方法,
Iterator<Object> iterator = lst.iterator();
//iterator.hasNext()如果存在元素的话返回true
while(iterator.hasNext()) {
//iterator.next()返回迭代的下一个元素
System.out.println(iterator.next());
}
}
然后说说LinkedList
list.getFirst();//获得头元素
list.getLast();//获得尾元素
list.get(index);//获得下标为index的元素
list.indexOf(data);//获得data的下标
//遍历链表
for(Object obj:list){
对obj进行操作
}
list.subList(start,end);//生成下标从start开始到end结束的子链表
list.add(data);//将data添到链表最后
list.add(index,data);//添加data到下标为index的位置
list.addFirst(data);//添加data到链头
list.addLast(data);//添加data到链尾
list.remove(data);//删除data元素
list.remove(index);//删除下标为index的元素
list.removeFirst();//删除头元素
list.removeLast();//删除尾元素
list.clear();//清空链表
list.subList(start,end).clear();//删除指定范围内的data
二叉树
对称二叉树或者镜像二叉树
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
肯定是用递归的,也就是设两个root节点,当左root的left=右root的right同时左root的right=右root的left,肯定对称
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot==null) return true;
return isSymme(pRoot.left,pRoot.right);
}
boolean isSymme(TreeNode root1,TreeNode root2)
{
if(root1==null&&root2==null) return true;
if(root1==null||root2==null) return false;
if(root1.val!=root2.val) return false;
return isSymme(root1.left,root2.right)&&isSymme(root1.right,root2.left);
}
}
之字形打印二叉树
即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
我的思路:使用两个栈,一个奇数层用一个偶数层用
另一种思路,记录每层的大小,奇数层正着输入,偶数层反着输入
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> res=new ArrayList<>();
LinkedList<TreeNode> q=new LinkedList<>();
boolean rev=true;//判断奇偶层
q.add(pRoot);
while(!q.isEmpty()){
int size=q.size();
ArrayList<Integer> list=new ArrayList<>();
for(int i=0;i<size;i++){
TreeNode node=q.poll();
if(node==null) continue;
if(rev){
list.add(node.val);
}else
list.add(0,node.val);
q.offer(node.left);
q.offer(node.right);
}
if(list.size()!=0) res.add(list);
rev=!rev;
}
return res;
}
使用递归进行层序遍历
高
public class Solution {
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
depth(pRoot, 1, list);
return list;
}
private void depth(TreeNode root, int depth, ArrayList<ArrayList<Integer>> list) {
if(root == null) return;
if(depth > list.size())//将层数与当前存的arraylist比较,arraylist小了就再添一行
list.add(new ArrayList<Integer>());
list.get(depth -1).add(root.val);//添加到相应的层数就行
depth(root.left, depth + 1, list);
depth(root.right, depth + 1, list);
}
}
二叉树的序列化和反序列化
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
这个半命题层序遍历挺简单的,但是我用先序遍历尝试一下
序列化
void BST_Preorder(TreeNode node,String data){
if(!node) {data+="#!"; return;}
String str=node.val+"!";
data+=str;
BST_Preorder(node->left,data);
BST_Preorder(node->right,data);
}
String[] str=data.split("!");
反序列化
int index=0;
TreeNode out_BST_order(String[] str){
if(str[index].equals("#"){
index++;
return null;
}
TreeNode root=new TreeNode(Integer.valueOf(str[index]);
index++;
root.left(out_BST_order(str));
root.right(out_BST_ordr(str));
return root;
}
给定一棵二叉搜索树,请找出第k小的节点
二叉搜索树:就是左子树<根节点<右子树
public class Solution {
ArrayList<TreeNode> list=new ArrayList<>();
TreeNode KthNode(TreeNode pRoot, int k)
{
if(pRoot==null||k<=0) return null;
Search(pRoot,k);
if(k>list.size())
return null;
return list.get(k-1);
}
void Search(TreeNode pRoot, int k)
{
if(pRoot!=null) {
if(k<=list.size()){
return;
}
Search(pRoot.left,k);
list.add(pRoot);
Search(pRoot.right,k);
}
}
大小顶堆求中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
import java.util.*;
public class Solution {
private int cnt=0;
PriorityQueue<Integer> low=new PriorityQueue<>();//小顶堆
PriorityQueue<Integer> high=new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2)
{
return o2 - o1;
}
});//大顶堆
public void Insert(Integer num) {
if(high.isEmpty()){
high.offer(num);
return;
}
if(high.size()==low.size()){
if(num<high.peek())
high.offer(num);
else
low.offer(num);
}else if(high.size()>low.size()){
if(num>high.peek())
low.offer(num);
else{
low.offer(high.peek());
high.poll();
high.offer(num);
}
}else if(high.size()<low.size()){
if(num<low.peek())
high.offer(num);
else{
high.offer(low.peek());
low.poll();
low.offer(num);
}
}
}
public Double GetMedian() {
double res=0;
if(high.size()==low.size())
return (high.peek()+low.peek())/2.0;
else if(high.size()>low.size())
res= high.peek();
else
res= low.peek();
return res;
}
}
滑动窗口最小数
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}
采用最大堆维护堆顶元素,最简洁
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> res=new ArrayList<>();
if(num==null||size<=0||num.length<size) return res;
PriorityQueue<Integer> queue=new PriorityQueue<Integer>((o1,o2)->o2-o1);//构建最大堆
for(int i=0;i<size;i++){
queue.offer(num[i]);
}//先输入最开始的size个元素
res.add(queue.peek());
for(int i=size;i<num.length;i++){//接下来的元素,进一个,出一个取堆顶入res
queue.remove(num[i-size]);
queue.offer(num[i]);
res.add(queue.peek());
}
return res;
}
}