【刷题笔记】剑指Offer刷题笔记

剑指Offer

  • 剑指Offer 03
    • 题目描述
    • 思路一
    • 思路二
    • 思路三
  • 剑指Offer 04
    • 题目描述
    • 思路
  • 剑指Offer 05
    • 题目描述
    • 思路一
    • 思路二
  • 剑指Offer 06
    • 题目描述
    • 思路一
    • 思路二
  • 剑指Offer 07
    • 题目描述
    • 预备知识
    • 解题思路
  • 剑指Offer 09
    • 题目描述
    • 预备知识
    • 解题思路
    • 拓展
      • 用数组实现队列的操作
      • 用两个队列实现栈
  • 剑指Offer 10-1
    • 题目描述
    • 解题思路
  • 剑指Offer 10-2
    • 题目描述
    • 解题思路
  • 剑指Offer 11
    • 题目描述
    • 预备知识
      • 排序
      • 查找
    • 思路
  • 剑指Offer 12
    • 题目描述
    • 思路
  • 剑指Offer 13
    • 题目描述
    • 思路
  • 剑指Offer 14-1
    • 题目描述
    • 思路
      • 贪心
  • 剑指Offer 14-2
    • 题目描述
    • 思路
      • 动态规划
      • 贪心算法
  • 剑指Offer 15
    • 题目描述
    • 思路
      • 无符号数
      • 有符号数
  • 剑指Offer 16
    • 题目描述
    • 思路
      • 暴力穷举
      • 递归
  • 剑指Offer 17
    • 题目描述
    • 思路
  • 剑指Offer 18
    • 题目描述
    • 思路
  • 剑指Offer 19
    • 题目描述
    • 思路
  • 剑指Offer 20
    • 题目描述
    • 思路
  • 剑指Offer 21
    • 题目描述
    • 思路
  • 剑指Offer 22
    • 题目描述
    • 思路
    • 拓展
  • 剑指Offer 24
    • 题目描述
    • 思路
  • 剑指Offer 25
    • 题目描述
    • 思路
  • 剑指Offer 26
    • 题目描述
    • 思路
  • 剑指Offer 27
    • 题目描述
    • 思路
  • 剑指Offer 28
    • 题目描述
    • 思路
  • 剑指Offer 29
    • 题目描述
    • 思路
  • 剑指Offer 20
    • 题目描述
    • 思路
  • 剑指Offer 21
    • 题目描述
    • 思路
  • 剑指Offer 22
    • 题目描述
    • 思路
  • 剑指Offer 23
    • 题目描述
    • 思路
  • 剑指Offer 24
    • 题目描述
    • 思路
  • 剑指Offer 25
    • 题目描述
    • 思路
  • 剑指Offer 26
    • 题目描述
    • 思路
  • 剑指Offer 27
    • 题目描述
    • 思路
  • 剑指Offer 28
    • 题目描述
    • 思路
  • 剑指Offer 29
    • 题目描述
    • 思路
  • 剑指Offer 20
    • 题目描述
    • 思路
  • 剑指Offer 21
    • 题目描述
    • 思路
  • 剑指Offer 22
    • 题目描述
    • 思路
  • 剑指Offer 23
    • 题目描述
    • 思路
  • 剑指Offer 24
    • 题目描述
    • 思路
  • 剑指Offer 25
    • 题目描述
    • 思路
  • 剑指Offer 26
    • 题目描述
    • 思路
  • 剑指Offer 27
    • 题目描述
    • 思路
  • 剑指Offer 28
    • 题目描述
    • 思路
  • 剑指Offer 29
    • 题目描述
    • 思路
  • 剑指Offer 20
    • 题目描述
    • 思路
  • 剑指Offer 21
    • 题目描述
    • 思路
  • 剑指Offer 22
    • 题目描述
    • 思路
  • 剑指Offer 23
    • 题目描述
    • 思路
  • 剑指Offer 24
    • 题目描述
    • 思路
  • 剑指Offer 25
    • 题目描述
    • 思路
  • 剑指Offer 26
    • 题目描述
    • 思路
  • 剑指Offer 27
    • 题目描述
    • 思路
  • 剑指Offer 28
    • 题目描述
    • 思路
  • 剑指Offer 29
    • 题目描述
    • 思路

剑指Offer 03

题目描述

【刷题笔记】剑指Offer刷题笔记_第1张图片

思路一

0到n-1范围内,长度为n,若不重复,必定涵盖所有0到n-1的值,将数组进行排序,小的数字放在数组的前面,排序过程中,如果碰到相同的数字输出。

复杂度分析:时间复杂度O(nlogn)/空间复杂度O(1)
LeetCode没通过

思路二

0到n-1范围内,长度为n,Java中的set特性为无序且不重复,创建一个和数组等长的HashSet,将数组的数依次放进set,添加失败时,输出该重复数。HashSet中的add()方法,添加成功时返回true

复杂度分析:时间复杂度O(n)/空间复杂度O(n)

思路三

0到n-1范围内,长度为n,若不重复,必定涵盖所有0到n-1的值,将数组调整为nums[i] = i即元素值等于其索引值的情况。

复杂度分析:时间复杂度O(n)/空间复杂度O(1)

剑指Offer 04

题目描述

【刷题笔记】剑指Offer刷题笔记_第2张图片

思路

【刷题笔记】剑指Offer刷题笔记_第3张图片如图所示①②为两个较大值,从①出发,进行比较,比target大,上移减小,比target小,右移增大。

剑指Offer 05

题目描述

【刷题笔记】剑指Offer刷题笔记_第4张图片

思路一

String的方法replace(“AA”,“BB”)

思路二

String生成之后不可以更改,用一个StringBuilder来接受String,charAt(i)接收字符,判断是否为空格,然后替换

剑指Offer 06

题目描述

【刷题笔记】剑指Offer刷题笔记_第5张图片

思路一

使用Stack,push()和pop()方法

思路二

先获取链表的长度,然后再使用数组来接受链表的值

剑指Offer 07

题目描述

【刷题笔记】剑指Offer刷题笔记_第6张图片

预备知识

前序遍历:先根节点,在左子节点,最后右子节点
中序遍历:先左子节点,在根节点,最后右子节点
后序遍历:先左节点,在右子节点,最后根节点

如图所示的二叉树:
【刷题笔记】剑指Offer刷题笔记_第7张图片

前序遍历:10,6,4,8,14,12,16
中序遍历:4,6,8,10,12,14,16
后序遍历:4,8,6,12,16,14,10

解题思路

前序遍历中,第一个是根节点,中序遍历中,在根节点前的就是左子树,在根节点后的就是右子树。在左、右子树中重复上述过程(递归),就可以生成最终的树

public class Resolution{
     
	public TreeNode buildTree(int[] preorder, int[] inorder){
     
		Map<Integer,Integer> map = new HashMap();
		for(int i = 0; i < inorder.length;i++){
     
			map.put(inorder[i],i);
		}
		return builderTreeHelper(preorder,0,preorder.length,inorder,0,inorder.length,map);
	}
	
	private TreeNode buildTreeHelper(int[] preorder,int p_start,int p_end,int[] inorder,int i_start,int i_end,Map<Integer,Integer> map){
     
		if(p_start == p_end){
     
			return null;
		}
		int root_val = preorder[p_start];
		TreeNode root = new TreeNode(root_val);
		int i_dx = map.get(root_val);
		int left_num = i_dx - i_start;
		root.left = buildTreeHelper(preorder,p_start+1,p_start+1+left_num,inorder,i_start,i_dx,map);
		root.right = builderTreeHelper(preorder,p_start+1+left_num,p_end,inorder,i_dx+1,i_end,map);
		return root;
		
	} 
}

剑指Offer 09

题目描述

【刷题笔记】剑指Offer刷题笔记_第8张图片

预备知识

栈:特点是后进先出,最后被压入(push)、最先被弹出(pop)
队列:特点是先进先出

解题思路

两个栈模拟一个队列:

①模拟向队列插入元素:将元素依次压入stack1栈内

②模拟向队列删除元素:因为栈的元素时后进先出,所以现在位于stack1栈顶的时队列的队尾,将stack1栈的所有元素依次弹出、压入stack2内,这样stack2就是队头是栈顶,依次pop即可
/*
该实现方法效率不佳,原因在于每次执行完一次删除操作之后,就又还原了队列
*/
public CQueue{
     
	
	//声明变量stack1、stack2
	private Stack<Integer> stack1;
	private Stack<Integer> stack2;
	
	public cQueue(){
     
		//构造器内实例化stack1、2
		stack1 = new stack<>();
		stack1 = new stack<>();
	}

	public void appendTail(int value) {
     
		stack1.push(value);
	}

	public int deleteHead(){
     
		if(stack1.isEmpty())
			return -1;
		while(!stack1.isEmpty()){
     
			stack2.push(stack1.pop());
		}
		int val = stack2.pop();
		while(!stack2.isEmpty()){
     
			stack1.push(stack2.pop())
		}
		return val;
	}
}
/*
高效方法:删除之后,不还原,如果要删除,就接着删除,新加进来的元素放在stack1中,stack2中的元素没了以后,在进行一次整体压入
*/
class CQueue {
     

    private Stack<Integer> stack1;
    private Stack<Integer> stack2;

    public CQueue() {
     

        stack1 = new Stack<>();
        stack2 = new Stack<>();

    }
    
    public void appendTail(int value) {
     
        stack1.push(value);
    }
    
    public int deleteHead() {
     
        if(stack2.isEmpty()){
     
            if(stack1.isEmpty()){
     
                return -1;
            }
            while(!stack1.isEmpty()){
     
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }
}

拓展

用数组实现队列的操作

class CQueue {
     

    int[] arr = new int[10000];
	int end = 0;
	int start = 0;
	
    public CQueue() {
     
    }
    
    public void appendTail(int value) {
     
    /*
	Java里面 i++和++i之间的区别:
	i++ 先赋值在运算,例如 a=i++,先赋值a=i,后运算i=i+1,所以结果是a==1
	++i 先运算在赋值,例如 a=++i,先运算i=i+1,后赋值a=i,所以结果是a==2
	*/
        arr[end++] = value;
    }
    
    public int deleteHead() {
     
        if(start == end){
     
        	return -1;
        }else{
     
        	return arr[start++];
        }
    }
}

用两个队列实现栈

①向栈内压入元素:
直接向队列1加入元素即可
②栈向外弹出元素:
队列1将前n-1个元素按顺序删除并添加至队列2中,队列1中第n个元素返回。

剑指Offer 10-1

题目描述

【刷题笔记】剑指Offer刷题笔记_第9张图片

解题思路

方法1:递归(力扣官网不通过,超时)

class Fibnum{
     
	public int getFibnum(int n){
     
		if(n < 0){
     
			return -1;
		}else if(n ==0 || n == 1){
     
			return n;
		}else{
     
			return getFibnum(n-1)+getFibnum(n-2);
		}
	}
}

方法2:把递归用遍历来实现

方法①存在的问题是:
当 n = 10 时,需要计算n = 9和n = 8时结果
	对于n = 9:
		需要计算n = 8(重复计算)和n = 7,在项数增大时,会出现很多个重复计算过的中间结果,浪费了资源。
		这就是导致力扣不通过的原因
class Solution{
     
	public int getFib(int n){
     
		
		int a = 0;
		int b = 1;
		int fibRes = 0;
		
		if(n < 0){
     
			return -1;
		}
		if(n == 0 || n == 1){
     
			return n;
		}
		for(i = 2;i <= n;i++){
     
			fibRes = a + b;
			a = b;
			b = fibRes;
		}
		return fibRes;
	}
}

剑指Offer 10-2

题目描述

【刷题笔记】剑指Offer刷题笔记_第10张图片

解题思路

一级台阶时,有1种跳法

两级台阶时,有2种跳法

台阶数 n>= 2时:
	情况① 第一次先跳一级,剩下n-1级台阶数的跳法
	情况② 第一次先跳两级,剩下n-2级台阶数的跳法
	综上:f(n) = f(n-1) + f(n-2)

剑指Offer 11

题目描述

【刷题笔记】剑指Offer刷题笔记_第11张图片

预备知识

排序

https://blog.csdn.net/weixin_38328533/article/details/111726180

查找

思路

若在排序和部分排序的数组中,查找某数或者统计某个数出现的次数,一般使用二分查找

旋转数组是部分排序,两个排序的子数组,用二分法分别对两个子数组进行查找。
【刷题笔记】剑指Offer刷题笔记_第12张图片

两个特殊情况:

原数组: 0,1,1,1,1
旋转数组1:1,0,1,1,1
旋转数组2:1,1,1,0,1
在最前面的指针、最后面的指针、中间的指针,三者指的数组的数是相同的时候,此时二分法失效,需要使用顺序查找。
class Solution {
     
    public int minArray(int[] numbers) {
     
        
        if(numbers.length < 0){
     
            return -1;
        }

        int start = 0;
        int end = numbers.length - 1;
        int mid = 0;

        while(numbers[start] >= numbers[end]){
     
            
            if(start + 1 == end){
     
                mid = end;
                break;
            }

            mid = (start + end)/2;
            if(numbers[start] == numbers[mid] && numbers[end] == numbers[mid]){
     
                return FindInOrder(numbers,start,end);
            }
            if(numbers[start] <= numbers[mid]){
     
                start = mid;
            }else if(numbers[end] >= numbers[mid]){
     
                end = mid;
            }
        }
        return numbers[mid];
    }

    private int FindInOrder(int[] numbers,int start,int end){
     
        int res = numbers[start];
        for(int i = start + 1;i < end;i++){
     
            if(res > numbers[i]){
     
                res = numbers[i];
            }
        }
        return res;
    }
}

剑指Offer 12

题目描述

【刷题笔记】剑指Offer刷题笔记_第13张图片

思路

class Solution {
     
    private boolean[][] visited; 

    public boolean exist(char[][] board, String word) {
     

        visited = new boolean[board.length][board[0].length]; 
        
        for(int i = 0; i < board.length; i++){
     
            for(int j = 0; j < board[i].length; j++){
     
                if(word.charAt(0) == board[i][j] && search(board,word,i,j,0)){
     
                    return true;
                } 
            }
        }
        
        return false;
    }

    private boolean search(char[][] board, String word, int i, int j, int index){
     
        
        if(index == word.length())
            return true;
        
        //如果当前的方格不属于word的序列或者被走过
        if(board[i][j] != word.charAt(index) || visited[i][j])
            return false;
        
        if(i < 0 || i >= board.length || j < 0 || j >= board[i].length)
            return false;
        
        //标记已走过
        visited[i][j] = true;

        boolean up = search(board,word,i-1,j,index+1);
        boolean down = search(board,word,i+1,j,index+1);
        boolean left = search(board,word,i,j-1,index+1);
        boolean right = search(board,word,i,j+1,index+1);

        if(up || down || left || right)
            return true;
        
        //没有走过
        visited[i][j] = false;
        return false;
    }
}

剑指Offer 13

题目描述

【刷题笔记】剑指Offer刷题笔记_第14张图片

思路

使用回溯法,方格看为m*n的矩阵

class Solution {
     
    int count = 0;
    public int movingCount(int m, int n, int k) {
     
        boolean[][] visited = new boolean[m][n];
        backTrack(visited,0,0,m,n,k);
        
        return count;
    }

    private void backTrack(boolean[][] visited, int i, int j, int m, int n, int k){
     
        if(i < m && j < n && !visited[i][j] && (i/10 + i%10 + j/10 + j%10)<= k){
     

            count++;
            visited[i][j] = true;
            backTrack(visited, i+1, j, m, n, k);
            backTrack(visited, i, j+1, m, n, k);
        }
    }
}

剑指Offer 14-1

题目描述

【刷题笔记】剑指Offer刷题笔记_第15张图片

思路

贪心

class Solution {
     
    public int cuttingRope(int n) {
     

        if(n <= 3){
     
            return n-1;
        }
        
        int a = n/3;
        int b = n%3;
		if(b == 0)
			return (int)Math.pow(3,a);
		if(b == 1){
     
			a = a-1;
        	return (int)Math.pow(3,a)*4;
        }
        
        return (int)Math.pow(3,a-1) *3 *2;
    }
}

剑指Offer 14-2

题目描述

【刷题笔记】剑指Offer刷题笔记_第16张图片

思路

动态规划

class Solution {
     
    public int cuttingRope(int n) {
     
        int[] res = new int[n+1];

        if(n < 2)
            return n-1;
        
        res[2] = 1;

        for(int i = 3; i <= n; i++){
     
            for(int j = 2; j < i; j++){
     
                res[i] = Math.max(res[i],Math.max((j * res[i-j]),j * (i - j)));

            }
        }

        return res[n];
    }
}

贪心算法

class Solution {
     
    public int cuttingRope(int n) {
     

        if(n <= 3){
     
            return n-1;
        }
        long res = 1;
        int a = n/3;
        int b = n%3;
        for(int i = 1; i < a; i++){
     
            res = (res *3)% 1000000007;
        }
        if(b == 0)
            return (int) (res *3 %1000000007);
        if(b == 1)
            return (int) (res *4 %1000000007);
        return (int)(res *3*2 %1000000007);
    }
}

剑指Offer 15

题目描述

【刷题笔记】剑指Offer刷题笔记_第17张图片

思路

无符号数

public class Solution {
     
    // you need to treat n as an unsigned value
    
    public int hammingWeight(int n) {
     
        int count = 0;
        while(n != 0){
     
            count += n & 1;
            //这里移位操作需要使用 >>>
            // >> 代表有符号数移位
            // >>>代表无符号移位
            //如果使用>>,可能会导致死循环,因为负数的首位是1,右移补1,无法退出循环
            n = n >>> 1;
        }
        return count;
    }
}

有符号数

public class Solution {
     
    // you need to treat n as an unsigned value
    
    public int hammingWeight(int n) {
     
        int count = 0;
        while(n != 0){
     
			//假设 n = 1100; n-1 = 1011;
			//n & (n-1) = 1000;
			//n & (n-1)自动去除最低位上的1,在不等于0之前,去除几次,加几次,就可以得到1的个数
            n= n & (n-1);
            count++;
        }
        return count;
    }
}

剑指Offer 16

题目描述

【刷题笔记】剑指Offer刷题笔记_第18张图片

思路

暴力穷举

//leetcode 官网不通过
class Solution {
     
    public double myPow(double x, int n) {
     
        double res = 1.0;
        if(x == 0 && n == 0){
     
            return -1.0;
        }
        if(x == 0){
     
            return 0.0;
        }
        if(n < 0){
     
            n = -n;
            x = 1.0/x;
        }
        for(int i = 1; i <= n; i++){
     
            res = res * x;
        }
        return res;
    }
}

递归

【刷题笔记】剑指Offer刷题笔记_第19张图片

public class Soulution{
     
	public double myPow(double x, int n){
     
		double res = 1.0;
		
		//x为0,n<0时,需要x为倒数在做n次方,0不能为分母,故报错;
		if(x == 0 && n < 0){
     
			return -1.0;
		}
		if(n == -1){
     
			x = 1.0/x;
		}
		if(n == 0){
     
			return 1.0;
		}
		if(n == 1){
     
			return x;
		}
		
		double half = myPow(x,n/2);
		double mod = myPow(x,n%2);
		res = half * half * mod;
		return res;
	}
}

剑指Offer 17

题目描述

【刷题笔记】剑指Offer刷题笔记_第20张图片

思路

class Solution {
     
    public int[] printNumbers(int n) {
     

       int num = (int) Math.pow(10,n)-1;
       int[] res = new int[num];
       
       for(int i = 0; i < num; i++){
     
           res[i] = i+1;
       }
       return res;
    }
}

剑指Offer 18

题目描述

【刷题笔记】剑指Offer刷题笔记_第21张图片

思路

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
     
    public ListNode deleteNode(ListNode head, int val) {
     

        ListNode findHead = new ListNode(0);
        findHead.next = head;
        ListNode tmp = findHead;

        while(tmp.next != null){
     

            if(tmp.next.val == val){
     
                tmp.next = tmp.next.next;
                break;
            }
            tmp = tmp.next;
        }
        return findHead.next;
    }
}

剑指Offer 19

题目描述

思路

剑指Offer 20

题目描述

【刷题笔记】剑指Offer刷题笔记_第22张图片

思路

字符串表示整数的形式为:A.BeEC
A代表整数部分,B代表小数部分,C代表指数部分
A,C可为 0-9、+ 、-
B只能为0-9

class Solution {
     
    public boolean isNumber(String s) {
     

        //trim()方法会去掉两边多余的空格
        s = s.trim();

        boolean hasNum = false;
        boolean hasE = false;
        boolean hasPoint = false;

        boolean hasNumAfterE = true;

        int len = s.length();

        if(len == 0 || s == null){
     
            return false;
        }
        for(int i = 0; i < len; i++){
     
            
            char charAtIndexI = s.charAt(i); 

            if(charAtIndexI >= '0' && charAtIndexI <= '9'){
     
                hasNum = true;
                hasNumAfterE = true;
            }else if(charAtIndexI == '.'){
     
                if(hasPoint || hasE){
     
                    return false;
                }
                hasPoint = true;
            }else if(charAtIndexI == 'e' || charAtIndexI == 'E'){
     
                
                if(!hasNum || hasE){
     
                    return false;
                }
                hasE = true;
                hasNumAfterE = false;
            }else if(charAtIndexI == '+' || charAtIndexI == '-'){
     
                if(i != 0 && s.charAt(i-1) != 'e' && s.charAt(i-1) != 'E'){
     
                    return false;
                }
            }else{
     
                return false;
            }
        }
        return hasNumAfterE && hasNum;
    }
}

剑指Offer 21

题目描述

【刷题笔记】剑指Offer刷题笔记_第23张图片

思路

使用两个指针,一个从前往后找偶数,一个从后往前找奇数,找到以后,交换位置,知道两个指针换位置

class Solution {
     
    public int[] exchange(int[] nums) {
     

        int start = 0;
        int end = nums.length - 1;
        int tmp;

        while(start < end){
     

            if(start < end && nums[start] % 2 == 1){
     
                start++;
            }

            if(start < end && nums[end] % 2 == 0){
     
                end--;
            }

            if(start < end){
     

                tmp = nums[end];
                nums[end] = nums[start];
                nums[start] = tmp;
            }
        }

        return nums;
    }
}

剑指Offer 22

题目描述

【刷题笔记】剑指Offer刷题笔记_第24张图片

思路

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
     
    public ListNode getKthFromEnd(ListNode head, int k) {
     

        ListNode fast = head;
        ListNode slow = head;

        if(head == null){
     
            return head;
        }

        while(k > 0){
     
            fast = fast.next;
            k--;
        }

        while(fast != null){
     
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

拓展

求链表的中间节点,链表长度为奇数,返回最中间的值,链表长度为偶数,返回中间两个值的任意一个即可

两个指针,一次一步,一次两步

遇到一个指针遍历链表不能解决问题的,一般采用双指针,指针快慢速度不同。

剑指Offer 24

题目描述

【刷题笔记】剑指Offer刷题笔记_第25张图片

思路

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
     
    public ListNode reverseList(ListNode head) {
     
    
        ListNode fast = head;
        ListNode slow = null;

        while(fast != null){
     
            ListNode tmp = fast.next;
            fast.next = slow;
            slow = fast;
            fast = tmp;
        }

        return slow;
    }
}

剑指Offer 25

题目描述

【刷题笔记】剑指Offer刷题笔记_第26张图片

思路

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
     
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
     
        //鲁棒性检测:
        
        //1.都是空指针
        ListNode res = new ListNode(0);
        ListNode tmp = res;
        while(l1 != null && l2 != null){
     
            if(l1.val < l2.val){
     
                tmp.next = l1;
                l1 = l1.next;
            }else{
     
                tmp.next = l2;
                l2 = l2.next;
            }
            tmp = tmp.next;
        }
        //2.一个空,一个不空
        //三元运算符,满足要求冒号前的结果,不满足,冒号后的结果
        tmp.next = l1 == null? l2:l1;
        return res.next;
    }
}

剑指Offer 26

题目描述

【刷题笔记】剑指Offer刷题笔记_第27张图片

思路

两步走:第一步在树A中寻找与树B根节点值相同的节点,第二步,判断该节点处向下的树的左右子树与B是否相同

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
     
    public boolean isSubStructure(TreeNode A, TreeNode B) {
     
        
        if(A == null || B == null)
            return false;

        return dfs(A, B) || isSubStructure(A.left,B) || isSubStructure(A.right, B);
    }

    private boolean dfs(TreeNode A, TreeNode B){
     
        
        if(B == null)  
            return true;
        if(A == null)
            return false;
        
        return A.val == B.val && dfs(A.left,B.left) && dfs(A.right,B.right);
    }
}

剑指Offer 27

题目描述

思路

剑指Offer 28

题目描述

思路

剑指Offer 29

题目描述

思路

剑指Offer 20

题目描述

思路

剑指Offer 21

题目描述

思路

剑指Offer 22

题目描述

思路

剑指Offer 23

题目描述

思路

剑指Offer 24

题目描述

思路

剑指Offer 25

题目描述

思路

剑指Offer 26

题目描述

思路

剑指Offer 27

题目描述

思路

剑指Offer 28

题目描述

思路

剑指Offer 29

题目描述

思路

剑指Offer 20

题目描述

思路

剑指Offer 21

题目描述

思路

剑指Offer 22

题目描述

思路

剑指Offer 23

题目描述

思路

剑指Offer 24

题目描述

思路

剑指Offer 25

题目描述

思路

剑指Offer 26

题目描述

思路

剑指Offer 27

题目描述

思路

剑指Offer 28

题目描述

思路

剑指Offer 29

题目描述

思路

剑指Offer 20

题目描述

思路

剑指Offer 21

题目描述

思路

剑指Offer 22

题目描述

思路

剑指Offer 23

题目描述

思路

剑指Offer 24

题目描述

思路

剑指Offer 25

题目描述

思路

剑指Offer 26

题目描述

思路

剑指Offer 27

题目描述

思路

剑指Offer 28

题目描述

思路

剑指Offer 29

题目描述

思路

你可能感兴趣的:(剑指Offer,数据结构与算法,java)