# 《剑指offer》全部题目-含Java实现

### 1.二维数组中的查找

public class Solution {
public boolean Find(int target, int [][] array) {
if(array == null||array.length==0) return false;
int rowIdx = 0,colIdx = array[0].length-1;
while(rowIdx<array.length&&colIdx>=0){
if(array[rowIdx][colIdx] == target)
return true;
else if(target>array[rowIdx][colIdx])
rowIdx++;
else if(target<array[rowIdx][colIdx])
colIdx--;
}
return false;
}
}

### 2.替换空格

public class Solution {
public String replaceSpace(StringBuffer str) {
StringBuilder sb = new StringBuilder();
for(int i = 0;i<str.length();i++){
if(str.charAt(i)==' '){
sb.append("%20");
}
else
sb.append(str.charAt(i));
}
return sb.toString();
}
}

### 3.从尾到头打印链表

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
ArrayList<Integer> result = new ArrayList<>();
Stack<Integer> stack = new Stack<>();
if(listNode == null) return result;
while(listNode != null){
stack.push(listNode.val);
listNode = listNode.next;
}
while(!stack.isEmpty())
return result;
}
}

### ==4.重建二叉树==

/**
* Definition for binary tree
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
if (pre == null || in == null || pre.length != in.length||pre.length == 0) return null;
return reConstructBinaryTreeCore(pre, 0, pre.length - 1, in, 0, in.length - 1);
}

public TreeNode reConstructBinaryTreeCore(int[] pre, int preStartIdx, int preEndIdx, int[] in, int inStartIdx, int inEndIdx)  throws Exception{
TreeNode node = new TreeNode(pre[preStartIdx]);
if (preStartIdx == preEndIdx)
if (inStartIdx != inEndIdx || pre[preStartIdx] != in[inStartIdx])
throw new Exception("Invalid input.");
int i = 0;
while (pre[preStartIdx] != in[inStartIdx + i])
i++;
if (i == 0)//证明没有左子树
node.left = null;
else
node.left = reConstructBinaryTreeCore(pre, preStartIdx + 1, preStartIdx + i, in, inStartIdx, inStartIdx + i - 1);
if (inStartIdx + i == inEndIdx)//证明没有右子树
node.right = null;
else
node.right = reConstructBinaryTreeCore(pre, preStartIdx + i + 1, preEndIdx, in, inStartIdx + i + 1, inEndIdx);
return node;

}
}

### 5.用两个栈实现队列

import java.util.Stack;

public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();

public void push(int node) {
stack1.push(node);
}

public int pop() throws Exception {
if(stack1.isEmpty()&&stack2.isEmpty())
throw new Exception("Queue is empty.");
if(!stack2.isEmpty())
return stack2.pop();
while(!stack1.isEmpty())
stack2.push(stack1.pop());
return stack2.pop();
}
}

### ==6.旋转数组的最小数字==


public class Solution {
public int minNumberInRotateArray(int [] array) {
if(array == null||array.length == 0)return 0;
int idx1 = 0,idx2 = array.length-1;
//如果不能进入while循环，则证明第一个元素小于最后一个元素，而且数组为非递减排序，最小值即为首位。
while(array[idx1]>=array[idx2]){
//第一个指针指向前半段递增序列的末尾，第二个指针指向后半段递增序列的首位。
if(idx2-idx1==1)return array[idx2];
//二分法查找临界点
int mid = (idx1+idx2)/2;
//考虑特例：｛1,0,1,1,1｝
if(array[idx1] == array[idx2]&& array[mid] == array[idx1]){
for(int i = idx1;i<=idx2;i++)
if(array[i]<array[mid])
return array[i];
//特例：｛1,1,1,1,1,1,1｝
return array[mid];
}
//更新指针，直至idx2-idx1==1;
if(array[mid]>=array[idx1])
idx1 = mid;
else if(array[mid]<=array[idx2])
idx2 = mid;
}
//此时数组为递增排列，第一个元素最小
return array[0];
}
}

### 7.斐波那契数列

n<=39

public class Solution {
public int Fibonacci(int n) {
if(n<1) return 0;
int[] fibonacci = new int[2];
fibonacci[0] = 1;
fibonacci[1] = 1;
n-=2;
while(n>0){
int temp = fibonacci[0]+fibonacci[1];
fibonacci[0] = fibonacci[1];
fibonacci[1] = temp;
n--;
}
return fibonacci[1];
}
}

### 8.跳台阶（动态规划）

public class Solution {
public int JumpFloor(int target) {
if(target < 1) return 0;
int[] DP = new int[3];
DP[0] = 1;
DP[1] = 2;
DP[2] = DP[0]+DP[1];
if(target<=3)
return DP[target-1];
for(int i =4;i<=target;i++){
DP[0] = DP[1];
DP[1] = DP[2];
DP[2] = DP[0]+DP[1];
}
return DP[2];
}
}

### 9.（变态版）跳台阶

public class Solution {
public int JumpFloorII(int target) {
if(target<=0) return -1;
//if(target == 1) return 1;
return (int)Math.pow(2,target - 1);
// return 2*JumpFloorII(target-1);
}
}

### 10.矩形覆盖

public class Solution {
public int RectCover(int target) {
if(target<1) return 0;
int[] DP = new int[3];
DP[0] = 1;
DP[1] = 2;
DP[2] = DP[1]+DP[0];
if(target<4)
return DP[target-1];
for(int i = 4;i<=target;i++){
int temp = DP[1]+DP[2];
DP[0] = DP[1];
DP[1] = DP[2];
DP[2] = temp;
}
return DP[2];
}
}

### 11.二进制中1的个数

public class Solution {
public int NumberOf1(int n) {
int count = 0;
while(n!=0){
count+=n&1;
n=n>>>1; // >>>运算符，使符号位也跟着右移
}
return count;
}
}

### 12.数值的整数次方

public class Solution {
public double Power(double base, int exponent) {
if(base == 0 && exponent < 0)//输入不合法
return 0.0;
if(exponent < 0)
return 1/PowerWithPositive(base,-1*exponent);
else
return PowerWithPositive(base,exponent);
}
public double PowerWithPositive(double base,int exponent){
if(exponent == 0)
return 1;
if(exponent == 1)
return base;
double result = PowerWithPositive(base,exponent >> 1);
result *= result;
if((exponent & 1) == 1)
result *= base;
return result;
}
}

### 13.调整数组顺序使奇数位于偶数前面

import java.util.Stack;
public class Solution {
public void reOrderArray(int [] array) {
if(array == null||array.length == 0) return;
Stack<Integer> odd = new Stack<>();
Stack<Integer> even = new Stack<>();
for(int i = 0;i<array.length;i++){
if((array[i]&1) == 1)
odd.push(array[i]);
else
even.push(array[i]);
}
int index = array.length-1;
while(!even.isEmpty())
array[index--] = even.pop();
while(!odd.isEmpty())
array[index--] = odd.pop();
}
}

### 14.链表中倒数第K个结点

#### 方法一：使用指针

/*
public class ListNode {
int val;
ListNode next = null;

ListNode(int val) {
this.val = val;
}
}*/
import java.util.Stack;
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
return null;
for(int i=1;i<k;i++){
if(node1==null)
return null;
node1 = node1.next;
}
if(node1 == null)
return null;
while(node1.next!=null){
node1 = node1.next;
node2 = node2.next;
}
return node2;
}

}


#### 方法二：使用辅助栈

/*
public class ListNode {
int val;
ListNode next = null;

ListNode(int val) {
this.val = val;
}
}*/
import java.util.Stack;
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
Stack<ListNode> stack = new Stack<>();
while(node!=null){
stack.push(node);
node = node.next;
}
for(int i =0;i<k;i++){
if(stack.empty())
return null;
node = stack.pop();
}
return node;
}
}


### 15.反转链表

/*
public class ListNode {
int val;
ListNode next = null;

ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
while(node3!=null){
node2.next = node1;
node1 = node2;
node2 = node3;
node3 = node3.next;
}
node2.next = node1;
return node2;
}
}

### 15.反转链表

##### 解法一：（使用栈）
/*
public class ListNode {
int val;
ListNode next = null;

ListNode(int val) {
this.val = val;
}
}*/
import java.util.Stack;
public class Solution {
Stack<ListNode> stack = new Stack<>();
}

while(!stack.empty()){
temp.next = stack.pop();
temp = temp.next;
}
temp.next = null;//一定要注意这里的这行代码
//一定要将链表末位next置为null
}
}
##### 解法二：
public class Solution{
ListNode pre = null;
ListNode node = null;
ListNode next = null;
while(true){
next = node.next;
node.next = pre;
pre = node;
if(next == null){
break;
}
node = next;
}
}
}

### 16.合并两个排序的链表

##### 解法一：
public class Solution {
public ListNode Merge(ListNode list1,ListNode list2) {
//if(list1 == null && list2 == null) return null;
//这行代码可以不要，因为当list1 == null  return list2也等于null
if(list1 == null) return list2;
if(list2 == null) return list1;
if(list1.val <= list2.val){
node = list1;
list1 = list1.next;
}else{
node = list2;
list2 = list2.next;
}
while(list1 != null&&list2 != null){
if(list1.val<=list2.val){
node.next = list1;
list1 = list1.next;
node = node.next;
}else{
node.next = list2;
list2 = list2.next;
node = node.next;
}
}
while(list1 != null){
node.next = list1;
list1 = list1.next;
node = node.next;
}
while(list2 != null){
node.next = list2;
list2 = list2.next;
node = node.next;
}
}
}
##### 解法二：（使用递归）
public class Solution {
public ListNode Merge(ListNode list1,ListNode list2) {
if(list1 == null) return list2;
if(list2 == null) return list1;
if(list1.val <= list2.val){
}else{
}
}
}

### 17.树的子结构

/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;

public TreeNode(int val) {
this.val = val;

}

}
*/
public class Solution {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root1==null||root2==null) return false;
boolean result = false;
if(root1.val == root2.val){
result = isEqualTree(root1,root2);
}
if(!result)
result = HasSubtree(root1.left,root2);
if(!result)
result = HasSubtree(root1.right,root2);
return result;
}
public boolean isEqualTree(TreeNode tree1,TreeNode tree2){
//注意此处，只需判断tree2 == null即可返回true；
//因为tree2为子树，此时tree1可以不为null，即tree1不为叶节点
if(tree2 == null) return true;
if(tree1 == null) return false;
if(tree1.val == tree2.val){
return isEqualTree(tree1.left,tree2.left) && isEqualTree(tree1.right,tree2.right);
}
return false;
}
}

### 18.二叉树的镜像

/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;

public TreeNode(int val) {
this.val = val;

}

}
*/
public class Solution {
public void Mirror(TreeNode root) {
if(root != null){
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
if(root.left!=null) Mirror(root.left);
if(root.right!=null) Mirror(root.right);
}
}
}

### ==19.顺时针打印矩阵（这道题有难度）==

==见书P161==

#### 知识点：

1. 基本数据类型传值，对形参的修改不会影响实参；
2. 引用类型传引用，形参和实参指向同一个内存地址（同一个对象），所以对参数的修改会影响到实际的对象；
3. String, Integer, Double等immutable的类型特殊处理，可以理解为传值，最后的操作不会修改实参对象。

import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
if(matrix == null) return null;
ArrayList<Integer> result = new ArrayList<>();
int start = 0;
while(start*2<matrix.length&&start*2<matrix[0].length){
printMatrixCircle(matrix,start,result);
start++;
}
return result;
}
public void printMatrixCircle(int [][] matrix,int start,ArrayList<Integer> result){
int endX = matrix[0].length - 1 - start;
int endY = matrix.length - 1 - start;
for(int i = start;i <= endX;i++){
}
if(start < endY){
for(int i = start +1;i <= endY;i++)
}
if(start<endX&&start<endY)
for(int i = endX -1;i>=start;i--)
if(start<endX&&start<endY-1)
for(int i = endY -1;i>start;i--)
}
}

import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
if(matrix == null) return null;
ArrayList<Integer> result = new ArrayList<>();
int h = matrix.length,w = matrix[0].length,round = 0;
while(result.size()<h*w){
int c=round,r=round;
while(c<w-round)
c--;
r++;
if(r == h-round) continue;
while(r<h-round)
r--;
c--;
if(c == round-1) continue;
while(c>=round)
c++;
r--;
while(r>round)
round++;
}
return result;
}
}

### 20 包含min函数的栈

import java.util.Stack;

public class Solution {

Stack<Integer> stack = new Stack<Integer>();
Stack<Integer> minStack = new Stack<Integer>();
int min;
public void push(int node) {
stack.push(node);
if(minStack.empty())
min = node;
else
min = Math.min(minStack.peek(),node);
minStack.push(min);
}

public int pop() {
minStack.pop();
return stack.pop();
}

public int top() {
return stack.peek();
}

public int min() {
return minStack.peek();
}
}

### 21.栈的压入、弹出序列

【解题思路】：设计一个辅助栈，如果下一个弹出的数字是辅助栈的栈顶，则弹出，如果不是栈顶，则继续将压入序列压入辅助栈，直到把下一个需要弹出的数字压入栈顶为止；如果所有数字都压入辅助站，栈顶仍然不是欲弹出的数字，则该序列不可能是一个弹出序列。

==注意：当stack为空的时候，调用peek()方法会抛出异常==

import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA == null||popA == null||pushA.length!=popA.length) return false;
Stack<Integer> stack = new Stack<>();
int j = 0;
for(int i = 0 ;i<popA.length;i++){
//一定注意这里需要先判断一下栈是否为空，
//如果为空，则调用peek()时会出现异常;
if(stack.empty())
stack.push(pushA[j++]);
while(stack.peek()!=popA[i]&&j<pushA.length)
stack.push(pushA[j++]);
if(stack.peek()==popA[i])
stack.pop();
else
return false;
}
return true;
}
}

### 22.从上往下打印二叉树

#### Java知识点：

1. 返回长度：
1. String.length();String字符串用length()方法会返回其长度。
2. Array.length;数组有length属性，直接数组名点length就可以取到。
3. ArrayList.size()方法的会返回其长度。
2. ArrayList 操作：
You need to use the get() method to get the element at a particular index from an ArrayList. You can't use [] to get the element at a particular index, in an arraylist. Its possible only for arrays and your files is not an array, but an ArrayList.

import java.util.ArrayList;

/**
* public class TreeNode {
*  int val = 0;
*  TreeNode left = null;
*  TreeNode right = null;
*
*  public TreeNode(int val) {
*      this.val = val;
*  }
* }
*/
public class Solution {
public ArrayList<Integer> PrintFromTopToBottom( TreeNode root )
{
ArrayList<Integer> result = new ArrayList<>();
if ( root == null )
return(result);
if ( root.left != null )
queue.offer( root.left );
if ( root.right != null )
queue.offer( root.right );
while ( !queue.isEmpty() )
{
TreeNode node = queue.poll();
if ( node.left != null )
queue.offer( node.left );
if ( node.right != null )
queue.offer( node.right );
}
return(result);
}
}


/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;

public TreeNode(int val) {
this.val = val;
}
}
*/
import java.util.ArrayList;
/**

*/
public class Solution {
ArrayList<Integer> result = new ArrayList<>();
ArrayList<TreeNode> temp = new ArrayList<>();
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
if(root == null) return result;
while(temp.size() != 0){
TreeNode node = temp.remove(0);
if(node.left!=null)
if(node.right!=null)
}
return result;
}
}

### 23.二叉搜索树的后序遍历序列

public class Solution {
public boolean VerifySquenceOfBST(int [] sequence) {
if(sequence == null || sequence.length == 0) return false;
int start = 0,end = sequence.length-1;
return isSearchTree(sequence,start,end);
}
public boolean isSearchTree(int [] sequence,int start,int end){
if(end==start) return true;
int root = sequence[end];
int index = end;
for(int i = start;i<end;i++){
if(sequence[i] > root){
index = i;
break;
}
}
for(int i = index;i<end;i++)
if(sequence[i]< root)
return false;
if(index == end||index == start)// index = end 时没有右子树；index = start时没有左子树；
return isSearchTree(sequence,start,end-1);
else
return isSearchTree(sequence,start,index-1)&&isSearchTree(sequence,index,end-1);
}
}

### 24.二叉树中和为某一值的路径

【解题思路】：因为根结点和叶子结点一定在路径中，而且路径开始一定是跟结点，使用前序遍历遍历二叉树，每经过一个结点减小target的值，直至找到使target=0的叶子结点，即为路径，每次回退，需要删除路径中最后一个结点。

import java.util.ArrayList;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;

public TreeNode(int val) {
this.val = val;

}

}
*/
public class Solution {
private ArrayList<ArrayList<Integer>> allPath = new ArrayList<>();
private ArrayList<Integer> path = new ArrayList<>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
if(root == null) return allPath;
target -= root.val;
if(target == 0&& root.left == null&&root.right == null)
else{
FindPath(root.left,target);
FindPath(root.right,target);
}
path.remove(path.size()-1);
return allPath;

}
}

### 25.复杂链表的复制

/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;

RandomListNode(int label) {
this.label = label;
}
}
*/
public class Solution {
{
//一定注意考虑输入为空链表的情况
//第一步：克隆每个结点的值和next，并且将新节点放置在对应旧结点之后
while(node != null){
RandomListNode cloneNode = new RandomListNode(node.label);
//cloneNode.label = node.label;
cloneNode.next = node.next;
node.next = cloneNode;
node = cloneNode.next;
}
//第二步：克隆每个随机指针
while(node != null){
RandomListNode cloneNode = node.next;
if(node.random != null)
cloneNode.random = node.random.next;
node = cloneNode.next;
}
//第三步：拆分拼接的链表
while(node != null){
RandomListNode cloneNode = node.next;
node.next = cloneNode.next;
node = node.next;
if(node != null)
cloneNode.next = node.next;
else
cloneNode.next = null;
}
}
}

### 26.二叉搜索树与双向链表

/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;

public TreeNode(int val) {
this.val = val;

}

}
*/
public class Solution {
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree == null) return null;
if(pRootOfTree.left == null && pRootOfTree.right == null) return pRootOfTree;
TreeNode left = Convert(pRootOfTree.left);
TreeNode node = left;

if(node == null)
pRootOfTree.left = null;
else{
while(node.right != null)
node = node.right;
pRootOfTree.left = node;
node.right = pRootOfTree;
}
TreeNode right = Convert(pRootOfTree.right);
pRootOfTree.right = right;
if(right != null)
right.left = pRootOfTree;
return left != null ? left : pRootOfTree;
}
}

### 27.==字符串的排列==

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Collections;
public class Solution {
ArrayList<String> result = new ArrayList<String>();
public ArrayList<String> Permutation(String str) {
if(str == null) return null;
char[] charArray = str.toCharArray();
permutation(charArray,0);
Collections.sort(result);
return result;
}
public void permutation(char[] charArray,int beginIdx){
if(beginIdx >= charArray.length) return;
if(beginIdx == charArray.length-1){
}
HashSet<Character> charSet = new HashSet<>();
for(int i = beginIdx;i<charArray.length;i++){
if(i == beginIdx){
permutation(charArray,beginIdx+1);
}else if(i != beginIdx && !charSet.contains(charArray[i])){
char temp = charArray[beginIdx];
charArray[beginIdx] = charArray[i];
charArray[i] = temp;
permutation(charArray,beginIdx+1);
temp = charArray[beginIdx];
charArray[beginIdx] = charArray[i];
charArray[i] = temp;
}
}
}
}

### 28.数组中出现次数超过一半的数字

#### 解法一：利用HashMap

import java.util.HashMap;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
HashMap<Integer,Integer> map = new HashMap<>();
int length = array.length;
if(length == 1) return array[0]; //此处用于当数组只有一个元素的时候，下面的代码对该情况无效
for(int i : array){
if(map.containsKey(i)){
if(map.get(i) == length/2)
return i;
map.put(i,map.get(i) + 1);

}else{
map.put(i,1);
}
}
return 0;
}
}

#### 解法二：利用数组特点，重复次数超过一半的数字一定大于其它数字出现次数之和

public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
if(array == null || array.length == 0) return 0;
int length = array.length;
int result = array[0];
int times = 1;
for(int i =1;i<length;i++){
if(result == array[i])
times++;
else if(times == 0){
result = array[i];
times =1;
}else
times--;
}
if(times == 0) return 0;
times = 0;
for(int i =0;i<length;i++){
if(array[i] == result)
times++;
}
if(times <= length/2)
result = 0;
return result;
}
}


### 29.最小的K个数

#### 解法一

Partition思想

import java.util.ArrayList;
public class Solution {
/*解法一：允许改变原始数组的情况，时间复杂度O(n)，不适合海量数据*/
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> result = new ArrayList<>();
//注意如果输入不合法，这里返回的是一个空集合，不是Null，与return null不同
if(input == null || k<0 || k>input.length) return result;

int start = 0;
int end = input.length-1;
int smallNums = partition(input,start,end);
while(smallNums != k-1){
if(smallNums > k-1)
smallNums = partition(input,start,smallNums-1);
else if(smallNums < k-1)
smallNums = partition(input,smallNums+1,end);
}
for(int i =0;i<k;i++){
}
return result;
}
//快排方法功能函数，在指定范围内随机选取一个数字，将数组中大与等于的放置其又，小于的放置其左；
//返回值是在变换位置后，该元素的索引值
public static int partition(int[] array,int start,int end){
//边界检测
if(array == null || array.length == 0 || start < 0 || end >= array.length || start > end) return -1;
//在[start,end]范围内，随机选取一个数作为index
int randomIdx = (int)(start + Math.random()*(end-start));
//int length = array.length;
int smallNums = start-1;
swap(array,randomIdx,end);
for(int i=start;i<end;i++){
if(array[i] < array[end]){
smallNums++;
if(smallNums < i){
swap(array,smallNums,i);
}
}
}

smallNums++;
swap(array,smallNums,end);
return smallNums;
}
//交换元素
public static void swap(int[] array,int i,int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}

#### 解法二：

import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
public class Solution {
//解法二：不改变原始数组，使用优先队列，时间复杂度O(nlogk)，适合海量数据
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> result = new ArrayList<>();
if(input == null || k > input.length || k<=0) return result;
PriorityQueue<Integer> maxQueue = new PriorityQueue(k,new Comparator<Integer>(){
@Override
public int compare(Integer o1,Integer o2){
return o2.compareTo(o1);//将先前Integer中的自然排序（从小到大）反过来，实现从大到小；
}
});
for(int i =0;i<input.length;i++){
if(maxQueue.size() != k ){
maxQueue.offer(input[i]);
}else if(maxQueue.peek() > input[i]){
Integer temp = maxQueue.poll();//必须先去除队列头部的数据,以保证队列长度
temp = null;
maxQueue.offer(input[i]);
}
}
for(Integer i : maxQueue){
}
return result;
}
}


### 30.连续子数组的最大和

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢？例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住？(子向量的长度至少是1)

public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
if (array == null || array.length == 0) return 0;
int[] DP = new int[2];
DP[0] = array[0];
int max = DP[0];
for (int i = 1; i < array.length; i++) {
DP[i & 1] = Math.max(array[i], array[i] + DP[(i - 1) & 1]);
max = Math.max(max, DP[i & 1]);
}
return max;
}
}

### ==31.1~n整数中1出现的次数==

#### 解题思路：

n中每一位数字对整体“1”数量的影响包括一下两个方面：

1. 若第i位大于1，则该位1的个数位，高于i的位组成的数字+1倍的10^i；
2. 若第i位等于1，则该位1的个数位，高于i的位组成的数字倍的10^i加上后面各位组成的数字加1；
3. 若第i位小于1，则该位1的个数位，高于i的位组成的数字倍的10^i；
import java.util.ArrayList;
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
if(n<=0) return 0;
//用于将int的每一位数字保存在int[]数组中
ArrayList<Integer> number = new ArrayList<>();
int totalNums = 0;
//已分析过的高位数字组成的乘子
int mult = 0;
int temp = n;
while(temp!=0){
temp = temp/10;
}
for(int i = number.size()-1;i>=0;i--){
int nums = (int)(Math.pow(10,i));
if(number.get(i) == 1){
totalNums += (int)(n % Math.pow(10,i) + 1);
}else if(number.get(i) > 1){
totalNums += (int)(Math.pow(10,i));
}else if(number.get(i) == 0){
}
totalNums += mult * nums;
mult = mult * 10 + number.get(i);
}
}
}

import java.util.ArrayList;

public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
if (n <= 0) return 0;
int num = 0, k = 0, count = 0, i = 1;
while (n != 0) {
int x = n % 10;
if (x == 1) {
count += num + 1;
count += x * k;
} else if (x > 1) {
count += x * k;
count += (int) Math.pow(10, i - 1);
}
num += x * Math.pow(10, i - 1);
k = 10 * k + (int) Math.pow(10, i - 1);
n /= 10;
i++;
}

return count;
}


### 32.把数组排成最小的数

#### 解题思路：

1. 实际是将数组元素进行排序的操作
2. 排序规则为，若MN组成的数字大于NM，则N在前M在后
3. 使用Comparatpr定制排序规则
4. 考虑到数字连接起来可能使int溢出，所以转换为使用String来操作。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Solution {
public String PrintMinNumber(int[] numbers) {
String result = "";
if (numbers == null || numbers.length == 0) return result;
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < numbers.length; i++) {
}
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String sNum1, String sNum2) {
String num1 = sNum1 + sNum2;
String num2 = sNum2 + sNum1;
return num1.compareTo(num2);
}
});
for (String str : list) {
result += str;
}
return result;
}
}

### 33.丑数

public class Solution {
public int GetUglyNumber_Solution(int index) {
if(index <= 0 ) return 0;
int mult2_Idx = 0,mult3_Idx = 0,mult5_Idx = 0;
int[] uglyNumber = new int[index];
uglyNumber[0] = 1;
for(int i = 1;i<index;i++){
int min = Math.min(Math.min(uglyNumber[mult2_Idx]*2,
uglyNumber[mult3_Idx]*3),
uglyNumber[mult5_Idx]*5);
uglyNumber[i] = min;
if(uglyNumber[mult2_Idx]*2 == uglyNumber[i])
mult2_Idx++;
if(uglyNumber[mult3_Idx]*3 == uglyNumber[i])
mult3_Idx++;
if(uglyNumber[mult5_Idx]*5 == uglyNumber[i])
mult5_Idx++;
}
return uglyNumber[index-1];
}
}

### 34.第一个只出现一次的字符

import java.util.HashMap;
public class Solution {
public int FirstNotRepeatingChar(String str) {
int result = Integer.MAX_VALUE;
if(str.length() == 0) return -1;
HashMap<Character,Integer> charIdx = new HashMap<>();
for(int i = 0 ;i < str.length(); i++){
Character c = str.charAt(i);
if(charIdx.containsKey(c)){
charIdx.put(c,-1);
}else{
charIdx.put(c,i);
}
}
for(int index : charIdx.values()){
if(index != -1){
result = Math.min(result,index);
}
}
return result;
}
}

### 35.==数组中的逆序对==

对于%50的数据,size<=10^4

public class Solution {
public int InversePairs(int [] array) {
if(array == null||array.length == 0) return 0;
int length = array.length;
int[] copy = new int[length];
for(int i = 0;i < length ;i++){
copy[i] = array[i];
}
int count = InversePairsCore(array,copy,0,array.length-1);
return count;
}

public int InversePairsCore(int[] array,int[] copy,int start,int end){
if(start == end){
return 0;
}
int count = 0;
int length = (end-start)/2;
//注意：这里是故意将copy和array调换位置的，因为每次执行InversePairCore之后copy在[start,end]部分都是排好序的
//随意使用data作为array输入，省去了来回复制的资源消耗。
int left = InversePairsCore(copy,array,start,start+length);
int right = InversePairsCore(copy,array,start+length+1,end);
int p1 = start+length;
int p2 = end;
int copyIdx = end;
while(p1 >= start && p2 >= start+length+1){
if(array[p1]>array[p2]){
count += p2-start-length;
//此处先判断一下，以免超出运算范围。
if(count > 1000000007)
count = count%1000000007;
copy[copyIdx--] = array[p1--];
}else{
copy[copyIdx--] = array[p2--];
}
}
while(p1 >= start){
copy[copyIdx--] = array[p1--];
}
while(p2 >= start+length+1){
copy[copyIdx--] = array[p2--];
}
return (count+left+right)%1000000007;
}
}

### 36.两个链表的第一个公共结点

/*
public class ListNode {
int val;
ListNode next = null;

ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
if(L1>L2)
for(int i = 0 ;i<(L1-L2);i++)
else if(L2>L1)
for(int i = 0 ;i<(L2-L1);i++)

}
return null;
}
int count = 1;
while(temp.next != null){
temp = temp.next;
count++;
}
return count;
}
}

### 37.数字在排序数组中出现的次数

/*

*/

public class Solution {
public int GetNumberOfK(int [] array , int k) {
if(array.length == 0) return 0;
int count = 0;
for(int i = 0 ; i < array.length ; i++){
if(array[i] == k){
count++;
}else{
if(count != 0)
break;
}
}
return count;
}
}

/*

*/
public class Solution {
public int GetNumberOfK(int[] array,int k){
if(array.length == 0) return 0;
int first = getFirstK(array,k,0,array.length-1);
int last = getLastK(array,k,0,array.length-1);
if(first > -1 && last > -1)
return last - first + 1;
return 0;
}
public int getFirstK(int[] array,int k,int start,int end){
if(start > end) return -1;
int midIdx = (end + start)/2;
if(array[midIdx] == k){
if((midIdx > 0 && array[midIdx-1] != k) || midIdx == 0)
return midIdx;
else{
end = midIdx - 1;
return getFirstK(array,k,start,end);
}
}else if(array[midIdx] > k){
end = midIdx - 1;
}else if(array[midIdx] < k){
start = midIdx +1;
}
return getFirstK(array,k,start,end);
}
public int getLastK(int[] array,int k ,int start,int end){
if(start > end) return -1;
int midIdx = (start + end)/2;
if(array[midIdx] == k){
if((midIdx < array.length-1 && array[midIdx+1] != k) || midIdx == array.length-1)
return midIdx;
else
start = midIdx + 1;
}else if(array[midIdx] > k){
end = midIdx - 1;
}else if(array[midIdx] < k){
start = midIdx + 1;
}
return getLastK(array,k,start,end);
}
}



### 38.二叉树的深度

/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;

public TreeNode(int val) {
this.val = val;

}

}
*/
public class Solution {
public int TreeDepth(TreeNode root) {
if(root == null) return 0;
int left = TreeDepth(root.left);
int right = TreeDepth(root.right);
if(left>right) return left+1;
else return right+1;
}
}

### 39.平衡二叉树

public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
if(root == null) return true;
int left = TreeDepth(root.left);
int right = TreeDepth(root.right);
if((left-right)>1||(left-right)<-1)
return false;
else
return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
}
public int TreeDepth(TreeNode root){
if(root == null) return 0;
int left = TreeDepth(root.left);
int right = TreeDepth(root.right);
return left > right ? left+1 : right+1;
}
}

public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
return getDepth(root) != -1;
}
public int getDepth(TreeNode root){
if(root == null) return 0;
int left = getDepth(root.left);
if(left == -1)
return -1;
int right = getDepth(root.right);
if(right == -1)
return -1;
return Math.abs(left-right) > 1 ? -1 : Math.max(left,right) + 1;
}
}

### 40.数组中只出现一次的数字

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.HashSet;
import java.util.Iterator;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
HashSet<Integer> set = new HashSet<Integer>();
for(int i = 0;i<array.length;i++){
if(set.contains(array[i])){
set.remove(array[i]);
}else{
}
}
boolean isFirst = true;
Iterator iter = set.iterator();
while(iter.hasNext()){
if(isFirst){
num1[0] = (int)iter.next();
isFirst = false;
}else
num2[0] = (int)iter.next();
}
}
}

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int OR = 0;
for(int i = 0;i<array.length;i++)
OR ^= array[i];
int idx = 0;//OR从后数第几位是1，从1开始
while(OR != 0){
OR = OR >> 1;
idx++;
}
num1[0] = 0;
num2[0] = 0;
for(int i = 0;i<array.length;i++){
if((array[i]&(1<<(idx-1))) == 0)
num1[0] ^= array[i];
else
num2[0] ^= array[i];
}
}
}

### 41.和为S的连续正数序列

import java.util.ArrayList;

public class Solution {
public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
int small = 1, big = 2, s = 3, mid = sum / 2;
while (small <= mid) {
if (s == sum) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = small; i <= big; i++)
s -= small;
small++;
} else if (s < sum) {
big++;
s += big;
} else if (s > sum) {
s -= small;
small++;
}
}
return result;
}
}

### 42.和为S的两个数

z=xy

x+y=s

z=x(s-x)=sx-x^2 函数图像为向下开口的抛物线，两段数值小中间大。所以取两边的值。

import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> result = new ArrayList<>();
int p1 = 0,p2 = array.length-1;
while(p1<p2){
if(array[p1]+array[p2] == sum){
return result;
}else if(array[p1]+array[p2]>sum)
p2--;
else
p1++;
}
return result;
}
}

### 43.坐旋转字符串

==该题有好多种做法==

public class Solution {
public String LeftRotateString(String str,int n) {
if(n<0 || str==null || str.length() == 0) return "";
n %= str.length();
StringBuilder sb = new StringBuilder();
for(int i = n;i<str.length();i++){
sb.append(str.charAt(i));
}
for(int i = 0;i<n;i++){
sb.append(str.charAt(i));
}
return sb.toString();
}
}

public class Solution {
public String LeftRotateString(String str, int n) {
if (str.length() == 0 || n < 0) return "";
int length = str.length();
n %= length;
str += str;
return str.substring(n, n + length);
}
}

### 44.翻转字符串

public class Solution {
public String ReverseSentence(String str) {
if (str.length() == 0) return "";
char[] charArray = str.toCharArray();
Reverse(charArray, 0, str.length() - 1);
int start = 0, end = 0;
for (int i = 0; i < charArray.length; i++) {
if (charArray[i] == ' ') {
end = i - 1;
Reverse(charArray, start, end);
start = i + 1;
}
}
//这句话是用于旋转最后一个单词的。
Reverse(charArray, start, charArray.length - 1);
return String.valueOf(charArray);
}

public char[] Reverse(char[] charArray, int start, int end) {
while (start < end) {
char temp = charArray[start];
charArray[start] = charArray[end];
charArray[end] = temp;
start++;
end--;
}
return charArray;
}
}

### 45.扑克牌顺子

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿！！“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。为了方便起见,你可以认为大小王是0。

import java.util.Arrays;
public class Solution {
public boolean isContinuous(int [] numbers) {
if(numbers.length < 5) return false;
Arrays.sort(numbers);
int zerosNum = 0;
int needZeros = 0;
for(int i = 0 ;i < 5;i++){
if(numbers[i] == 0){
zerosNum++;
}else if(i+1<5){
//如存在两数字相同，则一定不是顺子
if(numbers[i+1] == numbers[i]) return false;
needZeros += numbers[i+1] - numbers[i] -1;
}
}
//此时大王个数超过四个，不符合题目要求
if(zerosNum > 4) return false;
if(zerosNum >= needZeros) return true;
else return false;
}
}

### 46.孩子们的游戏

n个人（编号0~(n-1))，从0开始报数，报到(m-1)的退出，剩下的人 继续从0开始报数。求胜利者的编号。（约瑟夫环问题）

public class Solution {
public int LastRemaining_Solution(int n, int m) {
if(n<0||m<1) return -1;
int[] array = new int[n];
int count=n,step=0,idx=-1;
while(count>0){
idx++;
if(idx == n) idx=0;
if(array[idx] == -1) continue;//如果是被标记过的则跳过
step++;
if(step == m){
array[idx] = -1;
count--;
step=0;
}
}
return idx;
}
}

import java.util.ArrayList;
public class Solution {
public int LastRemaining_Solution(int n, int m){
if(n<0||m<1) return -1;
ArrayList<Integer> list = new ArrayList<>();
for(int i = 0;i<n;i++)
int idx = (m-1)%n;
while(list.size()>1){
list.remove(idx);
idx = (idx+m-1)%list.size();
}
return list.get(0);
}
}

### 47.求1+2+3+...+n

1. 需利用逻辑与短路特性实现递归终止。
2. 当n==0时，(n>0)&&((sum+=Sum_Solution(n-1))>0)只执行前面的判断，为false，然后直接返回0；
3. 当n>0时，执行sum+=Sum_Solution(n-1)，实现递归计算Sum_Solution(n)。
public class Solution {
public int Sum_Solution(int n) {
int sum = n;
boolean isEnd = (sum != 0)&&((sum += Sum_Solution(n-1))>0);
return sum;
}
}

### 48.不用加减乘除做加法

• step1:按位与是查看两个数哪些二进制位都为1，这些都是进位位，结果需左移一位，表示进位后的结果
• step2:异或是查看两个数哪些二进制位只有一个为1，这些是非进位位，可以直接加、减，结果表示非进位位进行加操作后的结果
• step3:n1&n2是查看有没有进位位了，如果有，需要重复step1、step2；如果没有，保留n1、n2上二进制为1的部分，用或将之合为一个数，即为最后结果
public class Solution {
public int Add(int num1,int num2) {
int n1,n2;
n1 = num1 & num2;
n1 = n1<<1;
n2 = num1 ^ num2;
if((n1 & n2) != 0) return Add(n1,n2);
return n1 | n2;
}
}

### 49.把字符串转换成整数

public class Solution {
public int StrToInt(String str) {
if(str.length() < 1) return 0;
char[] nums = str.toCharArray();
int result = 0;
int flag = 1;
for(int i = 0 ; i<nums.length ; i++){
if(nums[i]-'0'>9 || nums[i]-'0'<0){
if( i==0 && (nums[i] == '+' || nums[i] == '-'))
flag = nums[i] == '+' ? 1 : -1;
else
return 0;
}else{
result*=10;
result+=(nums[i]-'0');
}
}
return result*flag;
}
}

public class Solution {
public int StrToInt(String str) {
if(str.length() < 1) return 0;
int result = 0;
int flag = 1;
for(int i = 0 ; i<str.length(); i++){
if(str.charAt(i)-'0'>9 || str.charAt(i)-'0'<0){
if( i==0 && (str.charAt(i) == '+' || str.charAt(i) == '-'))
flag = str.charAt(i) == '+' ? 1 : -1;
else
return 0;
}else{
result*=10;
result+=(str.charAt(i)-'0');
}
}
return result*flag;
}
}

### 50.数组中重复的数字

public class Solution {
// Parameters:
//    numbers:     an array of integers
//    length:      the length of array numbers
//    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
//                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
//    这里要特别注意~返回任意重复的一个，赋值duplication[0]
// Return value:       true if the input is valid, and there are some duplications in the array number
//                     otherwise false
public boolean duplicate(int numbers[],int length,int [] duplication) {
if(length<0) return false;
boolean[] result = new boolean[length];
for(int i = 0;i<length;i++){
if(numbers[i]>length-1||numbers[i]<0) return false;
if(result[numbers[i]]){
duplication[0] = numbers[i];
return true;
}
result[numbers[i]] = true;
}
return false;
}
}

### 51.构建乘积数组

import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
int[] B = new int[A.length];
if(A.length == 0) return B;
B[0] = 1;
for(int i = 1;i<A.length;i++){
B[i] = B[i-1] * A[i-1];
}
int temp = 1;
for(int i = A.length-1;i>=0;i--){
B[i] *= temp;
temp *= A[i];
}
return B;
}
}

### ==52.正则表达式匹配==

1. 当patternIndex后一位为‘ * ’时：
此时若strIndex == str.length时，直接将patternIndex+2，跳过两个；
如果strIndex!=str.length时，分为以下三种情况：
1. strIndex，patternIndex+2；（str != pattern时）
2. strIndex+1，patternIndex+2；（str = pattern 时 或者 此时pattern == ‘.’）
3. strIndex+1，patternIndex；(str == pattern 而且 str+1 也 == pattern)
2. 当patternIndex后一位不为‘*’
此时如果strIndex = str.length return false；
如果 str = pattern 则 str+1，pattern+1
反之 return false；
public class Solution {
public boolean match(char[] str, char[] pattern)
{
//1.边缘检测
if(str==null||pattern==null) return false;
int strIndex=0,patternIndex=0;
return matchCore(str,pattern,strIndex,patternIndex);
}
public boolean matchCore(char[] str,char[] pattern,int strIndex,int patternIndex){
if(strIndex == str.length && patternIndex == pattern.length) return true;
if(strIndex != str.length && patternIndex == pattern.length) return false;
//当模式中第二个字符是‘*’
if(patternIndex+1 < pattern.length && pattern[patternIndex +1] == '*'){
//一定注意这里strIndex有可能是str.length 需要把str[strIndex]放在后面，以免溢出
if(strIndex != str.length && (pattern[patternIndex] == '.' || str[strIndex] == pattern[patternIndex])){
return matchCore(str,pattern,strIndex+1,patternIndex) || matchCore(str,pattern,strIndex+1,patternIndex+2) || matchCore(str,pattern,strIndex,patternIndex+2);
}else{
return matchCore(str,pattern,strIndex,patternIndex+2);
}
}else{//模式中第二个字符不是’*‘
if(strIndex != str.length && (str[strIndex] == pattern[patternIndex] || pattern[patternIndex] == '.'))
return matchCore(str,pattern,strIndex+1,patternIndex+1);
else
return false;
}
}
}

### ==53.表示数值的字符串==

• 其中A为带符号整数，可以为空
• B为不带符号整数，可以为空
• A和B不能同时为空
• C为带符号整数，不能为空
public class Solution {
//声明一个全局变量，记录小数点前是否有数字
boolean hasInt = false;
public boolean isNumeric(char[] str) {
if(str == null || str.length == 0) return false;
return scanA(str,0);
}
//第一部分：为带符号整数，后续字符串可包括'./e/E'
public boolean scanA(char[] str,int index){
//1.如果有符号则跳过。
if(str[index] == '-' || str[index] == '+') index++;
while(index < str.length && str[index]-'0' <= 9 && str[index]-'0' >= 0){
hasInt = true;
index++;
}
if(index == str.length) return hasInt;
if(str[index] == '.')
return scanB(str,index+1);
else if(str[index] == 'e'||str[index]=='E')
return scanC(str,index+1);
else
return false;
}
//第二部分:为不带符号整数,后续字符可带'e/E'
public boolean scanB(char[] str,int index){
boolean hasNum = false;
//用于判断是否是“12.”这种数字
if(index == str.length) return hasInt || hasNum;
while(index < str.length && str[index]-'0' <= 9 && str[index]-'0' >= 0){
index++;
hasNum = true;
}
if(index == str.length) return hasInt || hasNum;
if(str[index] == 'e' || str[index] == 'E')
return (hasInt || hasNum) && scanC(str,index+1);
else
return false;
}
//第三部分：为带符号整数
public boolean scanC(char[] str,int index){
//用于判断是否为“12e”这样的数字，这种是不正确的，第三部分不能为空
if(index == str.length) return false;
boolean hasNum = false;
//如果有符号，则跳过
if(str[index]=='+'||str[index]=='-') index++;
while(index < str.length && str[index]-'0' <= 9 && str[index]-'0' >= 0){
hasNum=true;
index++;
}
if(index == str.length) return hasNum;
else return false;
}
}

### 54.字符流中第一个不重复的字符

import java.util.ArrayList;
import java.util.HashSet;
public class Solution {
ArrayList<Character> list = new ArrayList<>();
HashSet<Character> set = new HashSet<>();
//Insert one char from stringstream
public void Insert(char ch)
{
if(!set.contains(ch))
if(list.contains(ch)){
//注意这里之所以将char转换为Character对象，是因为，如果直接带入char
//函数会将char转变成ASCII码int值作为索引，会导致溢出。
list.remove((Character)ch);
}else{
}
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
if(list.size() > 0)
return list.get(0);
else
return '#';
}
}

### 55.链表中的入口结点

/*
public class ListNode {
int val;
ListNode next = null;

ListNode(int val) {
this.val = val;
}
}
*/
import java.util.HashSet;
public class Solution {

{
HashSet<ListNode> set = new HashSet<>();
}

}
}

public class Solution {
{
//第一步：如果有环，则算出环的长度；
while(p1 != p2 && p2 != null){
p1 = p1.next;
p2 = p2.next;
if(p2 == null) return null;
p2 = p2.next;
}
if(p2 == null) return null;
int count = 1;
while(p1.next != p2){
p1 = p1.next;
count++;
}
//第二步：找到环的入口
while(count-- > 0)
p2 = p2.next;
while(p1!=p2){
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
}

### 56.删除链表中重复的结点这道题纠结了很久！！！很简单的递归就能实现，有点类似于动态规划

/*
public class ListNode {
int val;
ListNode next = null;

ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
{
}
}
}

### 57.二叉树的下一个结点

/*
int val;

this.val = val;
}
}
*/
public class Solution {
{
if(pNode == null) return null;
if(pNode.right != null){
while(node.left != null)
node = node.left;
return node;
}
while(pNode.next != null){
if(pNode.next.right != pNode)
return pNode.next;
pNode = pNode.next;
}
return null;
}
}

### 58.对称的二叉树

/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;

public TreeNode(int val) {
this.val = val;

}

}
*/
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
return isSymmetrical(pRoot,pRoot);
}
public boolean isSymmetrical(TreeNode n1,TreeNode n2){
if(n1 == null && n2 == null) return true;
if(n1 == null || n2 == null) return false;
if(n1.val != n2.val) return false;
return isSymmetrical(n1.left,n2.right) && isSymmetrical(n1.right,n2.left);
}
}

### 59.==之字形打印二叉树==

import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
if(pRoot == null) return result;
int layer = 1;
Stack<TreeNode> odd = new Stack<>();
Stack<TreeNode> even = new Stack<>();
odd.push(pRoot);
while(!odd.empty()||!even.empty()){
ArrayList<Integer> list = new ArrayList<>();
if((layer & 1) == 1){//位运算，判断是否为奇数;等价于layer%2
while(!odd.empty()){
TreeNode node = odd.pop();
if(node.left != null) even.push(node.left);
if(node.right != null) even.push(node.right);
}
}else{
while(!even.empty()){
TreeNode node = even.pop();
if(node.right != null) odd.push(node.right);
if(node.left != null) odd.push(node.left);
}
}
layer++;
}
return result;
}
}

### 60.把二叉树打印成多行

import java.util.ArrayList;
public class Solution {
ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
if(pRoot == null) return result;
ArrayList<Integer> list = new ArrayList<>();
queue.offer(pRoot);//将根节点加入队列
int elementsCount = 1;//用于记录每一层的元素个数
TreeNode node = queue.poll();
elementsCount--;
if(node.left != null) queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
if(elementsCount == 0){
list = new ArrayList<>();
elementsCount = queue.size();
}
}
return result;
}
}

### 61.序列化二叉树

/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;

public TreeNode(int val) {
this.val = val;

}

}
*/
public class Solution {
String Serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
if(root == null)
sb.append("$,"); else{ sb.append(root.val+","); sb.append(Serialize(root.left)); sb.append(Serialize(root.right)); } return sb.toString(); } int index = -1; TreeNode Deserialize(String str) { if(str == null || str == "") return null; String[] strArray = str.split(","); if(strArray.length == 0) return null; return DeserializeCore(strArray); } TreeNode DeserializeCore(String[] strArray){ TreeNode node = null; index++; if(!strArray[index].equals("$")){
node = new TreeNode(Integer.parseInt(strArray[index]));
node.left = DeserializeCore(strArray);
node.right = DeserializeCore(strArray);
}
return node;
}
}

### 62.二叉搜索树的第K个结点

import java.util.ArrayList;
public class Solution {
ArrayList<TreeNode> list = new ArrayList<>();
TreeNode KthNode(TreeNode pRoot, int k)
{
if(k < 1 || pRoot == null) return null;
LDR(pRoot);
if(list.size() < k) return null;
return list.get(k-1);
}

void LDR(TreeNode pRoot){
if(pRoot.left != null)
LDR(pRoot.left);
if(pRoot.right!=null)
LDR(pRoot.right);
}
}

### 63.数据流中的中位数

import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(new Comparator<Integer>(){
@Override
public int compare(Integer i1,Integer i2){
return i2-i1;
}
});
public void Insert(Integer num) {
minHeap.offer(num);
if(minHeap.size()>maxHeap.size()){
maxHeap.offer(minHeap.poll());
}else{
maxHeap.offer(minHeap.poll());
minHeap.offer(maxHeap.poll());
}
}
public Double GetMedian() {
if(minHeap.size()==0&&maxHeap.size()==0)
return null;
if(minHeap.size() == maxHeap.size())
return (double)(minHeap.peek()+maxHeap.peek())/2.0;
return (double)maxHeap.peek();
}
}

### 64.滑动窗口的最大值

import java.util.LinkedList;
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> result = new ArrayList<>();
if(num.length<1||size<1||size>num.length)
return result;
for(int i = 0;i<num.length;i++){
while(!deque.isEmpty() && num[deque.peekLast()] <= num[i])
deque.pollLast();
deque.offerLast(i);
if(i>=size-1){
while(i-deque.peekFirst()>size-1)
deque.pollFirst();
}
}
return result;
}
}

### 65.矩阵中的路径

public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
if(matrix == null || rows<1 || cols<1 || str == null) return false;
boolean[][] visited = new boolean[rows][cols];
int pathLength = 0;
for(int row = 0;row<rows;row++)
for(int col = 0 ;col<cols;col++){
if(hasPathCore(matrix,rows,cols,row,col,str,visited,pathLength))
return true;
}
return false;
}
public boolean hasPathCore(char[] matrix,int rows,int cols,int row,int col,char[] str,boolean[][] visited,int pathLength){
if(pathLength == str.length) return true;
boolean hasPath = false;
if(row>=0 && col>=0 && row<rows && col<cols && visited[row][col]==false && matrix[row*cols+col] == str[pathLength]){
pathLength++;
visited[row][col] = true;
hasPath = hasPathCore(matrix,rows,cols,row+1,col,str,visited,pathLength)
||hasPathCore(matrix,rows,cols,row-1,col,str,visited,pathLength)
||hasPathCore(matrix,rows,cols,row,col+1,str,visited,pathLength)
||hasPathCore(matrix,rows,cols,row,col-1,str,visited,pathLength);
if(!hasPath){
pathLength--;
visited[row][col] = false;
}
}
return hasPath;
}
}

### 66.机器人的运动范围

public class Solution {
public int movingCount(int threshold, int rows, int cols) {
if (threshold < 1 || rows < 1 || cols < 1) return 0;
boolean[][] visited = new boolean[rows][cols];
return movingCountCore(threshold, 0, 0, rows, cols, visited);

}

public int movingCountCore(int threshold, int row, int col, int rows, int cols, boolean[][] visited) {
int count = 0;
if (check(threshold, row, col, rows, cols, visited)) {
visited[row][col] = true;
count = 1 + movingCountCore(threshold, row + 1, col, rows, cols, visited)
+ movingCountCore(threshold, row - 1, col, rows, cols, visited)
+ movingCountCore(threshold, row, col + 1, rows, cols, visited)
+ movingCountCore(threshold, row, col - 1, rows, cols, visited);
}
return count;

}

public boolean check(int threshold, int row, int col, int rows, int cols, boolean[][] visited) {
if (row < 0 || col < 0 || row >= rows || col >= cols || visited[row][col])
return false;
int num = 0;
while (col != 0 || row != 0) {
num += col % 10;
num += row % 10;
col /= 10;
row /= 10;
}
if (num > threshold)
return false;
return true;
}

}

posted @ 2018-04-26 22:24 郭耀华 阅读(...) 评论(...) 编辑 收藏