注意:
ArrayList、List和LinkedList都是Java中常见的集合类,它们的主要区别如下:
- ArrayList是一个动态数组类,它实现了List接口。它通过数组来存储元素,支持快速随机访问。ArrayList的缺点是在插入和删除元素时,需要对后面的元素进行移动,因此效率较低。但是,在对集合进行频繁的随机访问时,ArrayList的性能要优于LinkedList。
- LinkedList是一个双向链表类,它同样实现了List接口。它通过链表来存储元素,支持快速的插入和删除操作。LinkedList的缺点是访问任意位置的元素时需要从头或从尾部遍历链表,因此效率较低。但是,在对集合进行频繁的插入和删除操作时,LinkedList的性能要优于ArrayList。
- List是一个接口,它定义了访问列表元素的基本操作,如添加元素、获取元素、删除元素等。List接口的实现类包括ArrayList、LinkedList等。List接口提供了一些额外的操作,如获取子列表、查找元素位置等。
综上所述,ArrayList和LinkedList都实现了List接口,但是它们的内部实现不同,适用于不同的场景。在需要频繁进行随机访问的情况下,ArrayList的性能更好;在需要频繁进行插入和删除操作的情况下,LinkedList的性能更好。List接口提供了一些基本的操作,可以方便地对集合进行操作。在实际应用中,需要根据具体场景选择合适的集合类。
层序遍历
LeetCode102:二叉树的层序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> ans = new ArrayList<List<Integer>>(); // 这个ans要加个public ,不然在getAns里面调用不到。
public List<List<Integer>> levelOrder(TreeNode root) {
// 广度优先算法
// 需要一个flag用来记录是哪一层,也就是表示要弹出这一层
// 递归法不太好理解,借助队列迭代好理解
getAns(root);
return ans;
}
public void getAns(TreeNode node){
if(node == null){
return;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(node);
while(!queue.isEmpty()){
List<Integer> ans_ = new ArrayList<Integer>();
int len = queue.size(); // 用来标记这一层有多少个node
while(len>0){
TreeNode temp = queue.poll();
ans_.add(temp.val);
if(temp.left != null){
queue.offer(temp.left); // 队列,先进先出。所以left在前面
}
if(temp.right != null){
queue.offer(temp.right);
}
len--;
}
ans.add(ans_);
}
}
}
C++的代码还是要熟悉,里面的元素的
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> ans;
if(root == NULL) return ans;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()){
int size = que.size(); // 要先将这一层的元素个数取出来,用于下面的遍历边界
vector<int> ans_;
for(int i=0;i<size;i++){
TreeNode* node = que.front();
ans_.push_back(node->val);
que.pop();
if(node->left) que.push(node->left); // 就是因为这里会改变que的长度,所以在一开始的时候就要确定好size
if(node->right) que.push(node->right);
}
ans.push_back(ans_);
}
return ans;
}
};
LeetCode107:二叉树的层序遍历 ②
思路:得到从上到下的层序遍历之后,再将ans 翻转
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> levelOrderBottom(TreeNode root) {
getAns(root);
Collections.reverse(ans);// 得到从上到下的层序遍历之后,再将ans 翻转
return ans;
}
public void getAns(TreeNode node){
if(node == null){
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(node);
while(!queue.isEmpty()){
List<Integer> ans_ = new ArrayList<>();
int len = queue.size();
while(len>0){
TreeNode temp = queue.poll();
ans_.add(temp.val);
// 注意 不用将left 和right颠倒,这是队列,
if(temp.left != null){
queue.offer(temp.left);
}
if(temp.right != null){
queue.offer(temp.right);
}
len--;
}
ans.add(ans_);
}
}
}
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>> ans;
if(root == NULL) return ans;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()){
int size = que.size();
vector<int> ans_;
for(int i=0;i<size;i++){
TreeNode* node = que.front();
que.pop();
ans_.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
ans.push_back(ans_);
}
reverse(ans.begin(), ans.end()); // 翻转一下
return ans;
// 不可以写成 return reverse(ans.begin(), ans.end());
// 因为reverse只是翻转 不会返回反转之后的ans
}
};
LeetCode199:二叉树的右视图
思路:只将当前层的最后一个元素放到ans里面。size是用来记录当前层一共有多少个元素的,所以只要当size==1 到了最后一个元素时,将他记录到ans就可以。
关键点:注意右视图,不是仅返回右侧的右节点。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> rightSideView(TreeNode root) {
// 右视图 不是只返回右节点
// 最右边只有左节点的情况也是可以看到左节点的。
List<Integer> ans = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
if(root == null){
return ans;
}
queue.offer(root);
while(!queue.isEmpty()){
int size = queue.size();
while(size>0){
TreeNode temp = queue.poll();
if(temp.left != null){
queue.offer(temp.left);
}
if(temp.right != null){
queue.offer(temp.right);
}
if(size==1){
ans.add(temp.val);
}
size--;
}
}
return ans;
}
}
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int> ans;
if(root == NULL) return ans;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()){
int size = que.size();
for(int i=0;i<size;i++){
TreeNode* node = que.front();
if(size-i==1) ans.push_back(node->val);
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return ans;
}
};
后续再补
LeetCode226:翻转二叉树
思路:这一题本质还是遍历。递归法遍历的时候加一个交换左右子节点的步骤即可
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode invertTree(TreeNode root) {
// 递归
if(root == null){
return root;
}
TreeNode left = root.left;
TreeNode right = root.right;
swap(root);
invertTree(left);
invertTree(right);
return root;
}
public void swap(TreeNode root){
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
迭代:
注意:这里是返回的root因此不能像之前的层序遍历那样自己建立数组用于返回。而且在对node左右节点交换是,也不是将queue里面换个位置就可以了。而是要swap(node->left,node->right)。
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root == NULL) return root;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()){
int size = que.size();
for(int i=0;i<size;i++){
TreeNode* node = que.front();
que.pop();
swap(node->left, node->right);
// 因为返回的是root而不是自己定义的数组,因此这里必须对node操作交换左右节点。
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return root;
}
};