1、判断一棵二叉树是否为平衡二叉树
Balanced Binary Tree
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.
这里面题目还给了提示,一棵平衡二叉树的左右子树高度差不会超过1。
方法1:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public boolean isBalanced(TreeNode root) {
return height(root) != -1;
}
public int height(TreeNode node){
if(node==null){
return 0;
}
int lH=height(node.left);
if(lH==-1){
return -1;
}
int rH=height(node.right);
if(rH==-1){
return -1;
}
if(lH-rH<-1 || lH-rH>1){
return -1;
}
return Math.max(lH,rH)+1;
}
}
方法2:
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
int depth = depth(root);
if (depth == -1) return false;
else return true;
}
private int depth(TreeNode root) {
if (root == null) return 0;
int left = depth(root.left);
int right = depth(root.right);
if (left == -1 || right == -1 || Math.abs(left-right) > 1) return -1;
return Math.max(left,right)+1;
}
上面都是用递归的方法来判断的,要是用非递归的要怎么写呢?这里读者也可以想一下。(虽然说递归是一定能转换成非递归的,但是要做到的话也不是一件简单的事啊)。
2、判断一棵二叉树是否是对称树
Symmetric Tree
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
For example, this binary tree is symmetric:
1
/ \
2 2
/ \ / \
3 4 4 3
But the following is not:
1
/ \
2 2
\ \
3 3
Note:
Bonus points if you could solve it both recursively and iteratively.
思路很简单,就是从最底下的结点开始,最左边结点和最后边结点进行比较,如果不同,就不是对称树,否则,再将另外对称的结点进行比较,...,到最后要是所有的对称点都相同的话,这就是一颗对称树。具体实现请看下面代码。
递归代码:
public boolean isSymmetric(TreeNode root) {
return root==null || isSymmetricHelp(root.left, root.right);
}
private boolean isSymmetricHelp(TreeNode left, TreeNode right){
if(left==null || right==null)
return left==right;
if(left.val!=right.val)
return false;
return isSymmetricHelp(left.left, right.right) && isSymmetricHelp(left.right, right.left);
}
非递归代码(借助栈):
public boolean isSymmetric(TreeNode root) {
if(root==null) return true;
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode left, right;
if(root.left!=null){
if(root.right==null) return false;
stack.push(root.left);
stack.push(root.right);
}
else if(root.right!=null){
return false;
}
while(!stack.empty()){
if(stack.size()%2!=0) return false;
right = stack.pop();
left = stack.pop();
if(right.val!=left.val) return false;
if(left.left!=null){
if(right.right==null) return false;
stack.push(left.left);
stack.push(right.right);
}
else if(right.right!=null){
return false;
}
if(left.right!=null){
if(right.left==null) return false;
stack.push(left.right);
stack.push(right.left);
}
else if(right.left!=null){
return false;
}
}
return true;
}
3、使用栈来实现队列
Implement Queue using Stacks
Implement the following operations of a queue using stacks.
push(x) – Push element x to the back of queue. pop() – Removes the
element from in front of queue. peek() – Get the front element.
empty() – Return whether the queue is empty.
Notes: You must use only standard operations of a stack – which means only push to top, peek/pop from top, size, and is empty
operations are valid. Depending on your language, stack may not be
supported natively. You may simulate a stack by using a list or deque
(double-ended queue), as long as you use only standard operations of a
stack. You may assume that all operations are valid (for example, no
pop or peek operations will be called on an empty queue).
下面贴下代码:
class MyQueue {
Stack<Integer> input = new Stack();
Stack<Integer> output = new Stack();
public void push(int x) {
input.push(x);
}
public void pop() {
peek();
output.pop();
}
public int peek() {
if (output.empty())
while (!input.empty())
output.push(input.pop());
return output.peek();
}
public boolean empty() {
return input.empty() && output.empty();
}
}
4、二叉树的层序遍历
Binary Tree Level Order Traversal
Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level).
For example:
Given binary tree {3,9,20,#,#,15,7},
3
/ \
9 20
/ \
15 7
return its level order traversal as:
[[3],[9,20],[15,7]]
方法1(递归)[深度优先算法]:
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
levelHelper(res, root, 0);
return res;
}
public void levelHelper(List<List<Integer>> res, TreeNode root, int height) {
if (root == null) return;
if (height >= res.size()) {
res.add(new LinkedList<Integer>());
}
res.get(height).add(root.val);
levelHelper(res, root.left, height+1);
levelHelper(res, root.right, height+1);
}
方法2(非递归):
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<TreeNode>();
List<List<Integer>> wrapList = new LinkedList<List<Integer>>();
if(root == null) return wrapList;
queue.offer(root);
while(!queue.isEmpty()){
int levelNum = queue.size();
List<Integer> subList = new LinkedList<Integer>();
for(int i=0; i<levelNum; i++) {
if(queue.peek().left != null) queue.offer(queue.peek().left);
if(queue.peek().right != null) queue.offer(queue.peek().right);
subList.add(queue.poll().val);
}
wrapList.add(subList);
}
return wrapList;
}
5、判断一个链表是不是循环链表
Linked List Cycle
Given a linked list, determine if it has a cycle in it.
Follow up:
Can you solve it without using extra space?
这种题目在牛客上刷专项的时候遇到过一两次,这种题目最快的解决办法使快慢指针法,设置两个指针,一个跑得快一个跑得慢,要是快的那一个追上了慢的那一个,就说明,这是一个循环链表,否则不是。
看看我下面的代码吧:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null) return false;
ListNode fast = head;
ListNode slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow) return true;
}
return false;
}
}
这是我提交几次之后,发现错误之后慢慢改过来的,就是里面的循环判断条件,就是一定要拿快指针的下一个和下下一个来判断,相信不用我解释大家都会懂的吧,唉当时一下就直接把fast.next != null && slow.next != null
给放进去了(我怎么会犯这种低级错误呢?而且还改了几次)。这道题就给自己一个教训。
6、反转数列
Rotate Array
Rotate an array of n elements to the right by k steps.
For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
Hint:
Could you do it in-place with O(1) extra space?
这道题有很多种解法,下面介绍三种。
( 正常的解法, 时间复杂度是O(n), 空间复杂度是O(k % nums.length) )
public class Solution {
public void rotate(int[] nums, int k) {
if(nums.length <= 1){
return;
}
int step = k % nums.length;
int[] tmp = new int[step];
for(int i = 0; i < step; i++){
tmp[i] = nums[nums.length - step + i];
}
for(int i = nums.length - step - 1; i >= 0; i--){
nums[i + step] = nums[i];
}
for(int i = 0; i < step; i++){
nums[i] = tmp[i];
}
}
}
( 用3次反转来解决问题, 时间复杂度是O(n), 空间复杂度是O(1))
public class Solution {
public void rotate(int[] nums, int k) {
if(nums.length <= 1){
return;
}
int step = k % nums.length;
reverse(nums,0,nums.length - 1);
reverse(nums,0,step - 1);
reverse(nums,step,nums.length - 1);
}
public void reverse(int[] nums, int n, int m){
while(n < m){
nums[n] ^= nums[m];
nums[m] ^= nums[n];
nums[n] ^= nums[m];
n++;
m--;
}
}
}
(下面这是个有趣的方法, 时间复杂度是O(n), 空间复杂度是O(1))
public class Solution {
public void rotate(int[] nums, int k) {
if(nums.length <= 1){
return;
}
//step each time to move
int step = k % nums.length;
//find GCD between nums length and step
int gcd = findGcd(nums.length, step);
int position, count;
//gcd path to finish move
for(int i = 0; i < gcd; i++){
//beginning position of each path
position = i;
//count is the number we need swap each path
count = nums.length / gcd - 1;
for(int j = 0; j < count; j++){
position = (position + step) % nums.length;
//swap index value in index i and position
nums[i] ^= nums[position];
nums[position] ^= nums[i];
nums[i] ^= nums[position];
}
}
}
public int findGcd(int a, int b){
return (a == 0 || b == 0) ? a + b : findGcd(b, a % b);
}
}
本系列未完,下一篇请看:LeetCode上做题之体会(五)