这里写目录标题
剑指OFFER
1.找出数组中重复的数字
class Solution {
public int duplicateInArray(int[] nums) {
int len = nums.length;
if(nums==null||len==0)
return -1;
for(int i =0;i<len;i++){
if(nums[i]<0||nums[i]>len-1)
return -1;
}
for(int i = 0;i<len;i++){
while(nums[i]!=i){
if(nums[i]==nums[nums[i]])
return nums[i];
int temp = nums[i];
nums[i] = nums[temp];
nums[temp] = temp;
}
}
return -1;
}
}
2.不修改数组找出重复的数字
class Solution {
public int duplicateInArray(int[] nums) {
int l = 1,r = nums.length-1;
while(l < r){
int mid = l+r >> 1;
int s = 0;
for(int x:nums){
if(x>=l&&x<=mid){
s++;
}
}
if(s>mid-l+1){
r = mid;
}else{
l = mid+1;
}
}
return r;
}
}
3. 二维数组中的查找
class Solution {
public boolean searchArray(int[][] arr, int target) {
if(arr.length == 0){
return false;
}
int i = 0, j = arr[0].length-1;
while(i < arr.length&& j >= 0){
if(arr[i][j] == target){
return true;
}
if(arr[i][j] > target){
j--;
}else{
i++;
}
}
return false;
}
}
4.替换空格
class Solution {
public String replaceSpaces(StringBuffer str) {
int x = str.indexOf(" ");
if(x!=-1){
replaceSpaces(str.replace(x,x+1,"%20"));
}
return str.toString();
}
}
class Solution {
public String replaceSpace(String s) {
s = s.replace(" ","%20");
return s;
}
}
class Solution {
public String replaceSpace(String s) {
s = s.replaceAll("\\s","%20");
return s;
}
}
5.从尾到头打印链表
class Solution {
public int[] reversePrint(ListNode head) {
// 先判断链表的数量
ListNode tmp = head;
int cnt = 0;
while(tmp!=null){
tmp = tmp.next;
cnt++;
}
int[] arr = new int[cnt];
for(int i = cnt-1; i >= 0; i--){
arr[i] = head.val;
head = head.next;
}
return arr;
}
}
//leetcode submit region end(Prohibit modification and deletion)
6.重建二叉树
前序遍历:中左右 根据前序遍历可知道根节点
中序遍历:左中右
后序遍历:左右中
解题步骤:
1.根据前序遍历可以知道根节点的位置,第一个值就是根节点的位置;
2.在中序遍历中找到根节点的位置,根节点左边是左子树的中序遍历,根节点右边是右子树的中序遍历。
3.假设左子树的中序遍历的长度为l,则在 前序遍历中,根节点后面的l个数为左子树的前序遍历,剩下的是右子树的前序遍历。
4.有了左右子树的前序遍历和中序遍历,我们可以递归创建出左右子树,然后再创建根节点。
/**
* Definition for a binary tree node.
* class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int[] preorder;
int[] inorder;
HashMap<Integer,Integer> map;
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
this.inorder = inorder;
map = new HashMap<Integer,Integer>();
for(int i = 0; i < inorder.length; i++){
map.put(inorder[i],i);
}
return dfs(0,preorder.length-1,0,inorder.length-1);
}
public TreeNode dfs(int pl,int pr,int il,int ir){
if(pl > pr){
return null;
}
TreeNode res = new TreeNode(preorder[pl]);
int k = map.get(res.val);
res.left = dfs(pl+1,pl+k-il,il,k-1);
res.right = dfs(pl+k-il+1,pr,k+1,ir);
return res;
}
}
7.二叉树的下一个节点
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode father;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode inorderSuccessor(TreeNode p) {
// 存在右孩子,后继就是右子树中最左侧的点
if(p.right!=null){
p = p.right;
while(p.left!=null){
p = p.left;
}
return p;
}
while(p!=null&&p.father!=null&&p!=p.father.left){
p = p.father;
}
return p.father;
}
}
8.用两个栈实现队列
class MyQueue {
Stack <Integer> s1;
Stack <Integer> s2;
/** Initialize your data structure here. */
public MyQueue() {
s1 = new Stack<>();
s2 = new Stack<>();
}
/** Push element x to the back of queue. */
public void push(int x) {
s1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
while(!s2.empty()){
return s2.pop();
}
while(!s1.empty()){
s2.push(s1.pop());
}
return s2.pop();
}
/** Get the front element. */
public int peek() {
while(!s2.empty()){
return s2.peek();
}
while(!s1.empty()){
s2.push(s1.pop());
}
return s2.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
return s1.isEmpty()&&s2.isEmpty();
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
9.斐波那契数列
class Solution {
public int Fibonacci(int n) {
if(n<=0){
return 0;
}
if(n<=2){
return 1;
}
int a = 1, b = 1, c = 0 ;
for(int i = 3; i <= n; i++){
c = a+b;
a = b;
b = c;
}
return c;
}
}
10.旋转数组的最小数字
class Solution {
public int findMin(int[] nums) {
//先去除右边界
int n = nums.length-1;
if(n<0){
return -1;
}
while(nums[0]==nums[n]&&n>0){
n--;
}
if(nums[n]>=nums[0]){
return nums[0];
}
int l = 0, r = n;
while(l < r){
int mid = l + r >> 1;
if(nums[mid]<nums[0]){
r = mid;
}else{
l = mid+1;
}
}
return nums[r] ;
}
}
11.矩阵中的路径
class Solution {
public boolean hasPath(char[][] matrix, String str) {
for(int i=0;i<matrix.length;i++)
{
for(int j=0;j<matrix[i].length;j++)
{
if(dfs(matrix,str,0,i,j))//将每一个字母作为开始看是否匹配
return true;
}
}
return false;
}
public boolean dfs(char[][] matrix,String str,int u,int x,int y){
if(matrix[x][y]!=str.charAt(u)) return false;//第一个不匹配,
if(u==str.length()-1) return true;//已经遍历到字符串后一个字母了
int dx[]=new int[]{-1,0,1,0},dy[]=new int[]{0,1,0,-1};//左,上,右,下的左边计算
char t = matrix[x][y];//取出正在比较的值进行标记
matrix[x][y]='#';
//要进行正式的比较的的逻辑
for(int i=0;i<4;i++){//分别计算四个方向
int a =x+dx[i],b =y+dy[i];
if(a>=0&&a<matrix.length&&b>=0&&b<matrix[a].length)
if(dfs(matrix,str,u+1,a,b)) return true;
}
matrix[x][y]=t;
return false;
}
}
12.机器人的运动范围
class Solution {
int count=0;
public int movingCount(int threshold, int rows, int cols)
{
if(rows==0||cols==0)return 0;
boolean [][] vt=new boolean[rows][cols];
dfs(threshold,rows,cols,0,0,vt);
return count;
}
void dfs(int threshold,int rows,int cols,int x,int y,boolean [][]vt){
if(sum(x)+sum(y)>threshold)return;
int [] dx={-1,0,1,0};
int [] dy={0,1,0,-1};
vt[x][y]=true;
count++;
for(int i=0;i<4;i++){
int nx=x+dx[i];
int ny=y+dy[i];
if(nx>=0&&nx<rows&&ny>=0&&ny<cols&&vt[nx][ny]==false){
dfs(threshold,rows,cols,nx,ny,vt);
}
}
}
int sum(int a){
int b=0;
while(a>0){
b+=a%10;
a/=10;
}
return b;
}
13.剪绳子