> 文章列表 > 刷题笔记【7】| 快速刷完67道剑指offer(Java版)

刷题笔记【7】| 快速刷完67道剑指offer(Java版)

刷题笔记【7】| 快速刷完67道剑指offer(Java版)

在这里插入图片描述

本文已收录于专栏

🌻

《刷题笔记》

文章目录

  • 前言
  • 🎨 1、二叉树中和为某一值的路径
    • 题目描述
    • 思路(深度优先搜索)
  • 🎨 2、复杂链表的复制
    • 题目描述
    • 思路
  • 🎨 3、二叉搜索树与双向链表
    • 题目描述
    • 思路
  • 🎨 4、字符串的排列
    • 题目描述
    • 思路(递归+回溯)

前言

题目来源参考阿秀学长的刷题笔记,小戴只是把 C++的题解改成了 Java版本,并整理了其他思路,便于自己的学习~

如果解题有更好的方法,本文也会及时进行更新~

希望对你有帮助~ 一起加油哇~

🎨 1、二叉树中和为某一值的路径

牛客原题链接

题目描述

输入一颗二叉树的根节点和一个整数,按字典序打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径

思路(深度优先搜索)

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>> res;private ArrayList<Integer> path;public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int expectNumber) {res = new ArrayList<>();path = new ArrayList<>();dfs(root,expectNumber);return res;}public void dfs(TreeNode root,int expectNumber){// 处理树为空if(root == null) return;path.add(root.val);expectNumber -= root.val;if(root.left == null && root.right == null && expectNumber == 0){res.add(new ArrayList<>(path));}// 左右子树递归dfs(root.left,expectNumber);dfs(root.right,expectNumber);// 回溯path.remove(path.size()-1);}
}

🎨 2、复杂链表的复制

牛客原题链接

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

思路

/*
public class RandomListNode {int label;RandomListNode next = null;RandomListNode random = null;RandomListNode(int label) {this.label = label;}
}
*/
public class Solution {public RandomListNode Clone(RandomListNode pHead) {if(pHead == null) return null;RandomListNode cur = pHead;// 遍历原始链表,复制链表节点while(cur != null){// 拷贝节点RandomListNode clone = new RandomListNode(cur.label);// 将新节点插入到被拷贝的节点之后clone.next = cur.next;cur.next = clone;cur = clone.next;}// 遍历原始链表,复制随机节点cur = pHead;RandomListNode clone = pHead.next;while(cur != null){if(cur.random == null){clone.random = null;}else{clone.random = cur.random.next;}cur = cur.next.next;if(clone.next != null){clone = clone.next.next;}}RandomListNode res = pHead.next;// 遍历链表,进行拆分cur = pHead;clone = pHead.next;while(cur != null){cur.next = cur.next.next;cur = cur.next;if(clone.next != null){clone.next = clone.next.next;}clone = clone.next;}return res;}
}

🎨 3、二叉搜索树与双向链表

牛客原题链接

题目描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

思路

/**
public class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}
*/
public class Solution {// 返回的第一个指针,即为最小值,先定为nullpublic TreeNode head = null;// 中序遍历当前值的上一位,初值为最小值,先定为nullpublic TreeNode pre = null;public TreeNode Convert(TreeNode pRootOfTree) {if(pRootOfTree == null){return null;}// 首先递归到最左最小值Convert(pRootOfTree.left);// 找到最小值,初始化head和preif(pre == null){head = pRootOfTree;pre = pRootOfTree;}// 当前节点与上一节点建立连接,将pre设置为当前值else{pre.right = pRootOfTree;pRootOfTree.left = pre;pre = pRootOfTree;}Convert(pRootOfTree.right);return head;}
}

🎨 4、字符串的排列

牛客原题链接

题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba

思路(递归+回溯)

  • 先对字符串按照字典序排序,获取第一个排列情况。
  • 准备一个空串暂存递归过程中组装的排列情况。使用额外的vis数组用于记录哪些位置的字符被加入了。
  • 每次递归从头遍历字符串,获取字符加入:首先根据vis数组,已经加入的元素不能再次加入了;同时,如果当前的元素str[i]与同一层的前一个元素str[i-1]相同且str[i-1]已经用,也不需要将其纳入。
  • 进入下一层递归前将vis数组当前位置标记为使用过。
  • 回溯的时候需要修改vis数组当前位置标记,同时去掉刚刚加入字符串的元素,
  • 临时字符串长度到达原串长度就是一种排列情况。
import java.util.*;
public class Solution {public void recursion(ArrayList<String> res,char[] str,StringBuffer temp,boolean[] vis){if(temp.length() == str.length){res.add(new String(temp));return;}// 遍历所有元素选取一个加入for(int i = 0; i < str.length; i++){// 如果该元素已经被加入,则不需要再加入了if(vis[i]){continue;}if(i > 0 && str[i-1] == str[i] && !vis[i-1]){// 当前元素str[i]与同一层的前一个元素str[i-1]相同且str[i-1]已经被使用continue;}// 标记为使用过vis[i] = true;// 加入临时字符串temp.append(str[i]);recursion(res,str,temp,vis);//回溯vis[i] = false;temp.deleteCharAt(temp.length()-1);}}public ArrayList<String> Permutation(String str) {ArrayList<String> res = new ArrayList<String>();if(str == null || str.length() == 0){return res;}// 转字符数组char[] charStr = str.toCharArray();// 按字典序排序Arrays.sort(charStr);boolean[] vis = new boolean[str.length()];// 标记每个位置的字符是否被使用过Arrays.fill(vis,false);StringBuffer temp = new StringBuffer();// 递归获取recursion(res,charStr,temp,vis);return res;}
}