输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = "abc" 输出:["abc","acb","bac","bca","cab","cba"]
限制:
1 <= s 的长度 <= 8
- 字符串
- 回溯
著书三年倦写字,如今翻书不识志,若知倦书悔前程 ,无如渔樵未识时
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = "abc" 输出:["abc","acb","bac","bca","cab","cba"]
限制:
1 <= s 的长度 <= 8
回溯基本操作了
回溯基本操作了
class Solution {
private List<String> list;
private Integer length;
public String[] permutation(String s) {
list = new ArrayList<>();
length = s.length();
boolean[] visited = new boolean[s.length()];
dfs(s.toCharArray(),visited,0,new char[s.length()]);
String[] res = new String[list.size()];
int i = 0;
for (String s1 : list) {
res[i] = s1;
i++;
}
return res;
}
private void dfs(char[] charArr,boolean[] visited,int index,char[] newCharArr){
if (index==length){
list.add(new String(newCharArr));
return;
}
Set<Character> sameChar = new HashSet<>();
for (int i = 0; i < charArr.length; i++) {
if (visited[i]){
continue;
}
if (sameChar.contains(charArr[i])){
continue;
}
sameChar.add(charArr[i]);
visited[i] = true;
newCharArr[index] = charArr[i];
dfs(charArr,visited,index+1,newCharArr);
visited[i] = false;
}
}
}
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true
,否则返回 false
。假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:
5 / \ 2 6 / \ 1 3
示例 1:
输入: [1,6,3,2,5] 输出: false
示例 2:
输入: [1,3,2,6,5] 输出: true
提示:
数组长度 <= 1000
分段验证
分段验证
class Solution {
public boolean verifyPostorder(int[] postorder) {
return validate(postorder,0,postorder.length-1);
}
private boolean validate(int[] postorder, int left ,int right){
//如果左指针大于等于右指针了,说明当前节点以及没有子节点了,自然是符合条件的】
if (left>=right || left < 0 || right < 0) return true;
//找到这段数组对应的根节点,根据后序遍历的特性,即为这段数组的最后一位
int rootNum = postorder[right];
//初始赋值
int leftEnd = -1;
int rightStart = -1;
//开始遍历
for (int i = left; i < right; i++) {
if (postorder[i] < rootNum){
//如果这个值小于根节点的值,说明这个节点应该是在左子树中
leftEnd = i;
}
if (postorder[i] > rootNum && rightStart == -1){
//如果这个值大于根节点的值,说明这个节点应该是右子树上的
//且rightStart == -1 表示是第一次碰到的
rightStart = i;
}
}
//此时如果符合条件的话,应该是 leftEnd 在 rightStart 的左边一位
//或者 没有左子树:leftEnd == -1 且rightStart == left
//或者 没有右子树:rightStart == -1 且leftEnd == right-1
boolean validateResult = (leftEnd>-1 && rightStart> -1 && leftEnd+1== rightStart)
|| ( leftEnd == -1 && rightStart == left )
|| ( rightStart == -1 && leftEnd == right-1);
//自身验证完了,还要对分割好了的子序列的有效性判断
if (validateResult){
return validate( postorder, left, leftEnd ) && validate( postorder, rightStart, right-1 );
}
return false;
}
}
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例 1:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] Output: [3,9,20,null,null,15,7]
示例 2:
Input: preorder = [-1], inorder = [-1] Output: [-1]
限制:
0 <= 节点个数 <= 5000
注意:本题与主站 105 题重复:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ Related Topics
👍 830👎 0
学二叉树入门必做题
关键信息
前中后序遍历
左右两个子节点的顺序不变都是先左子节点,后右子节点,区别就在于根节点是先遍历,还是中间,还是最后
这分别就是前中后序遍历
相关特性
现有如图这个一对前序遍历和中序遍历结果
根据相关特效,前序遍历的第一个就是根节点,所以我们知道了,根节点为3
又中序遍历中左侧只有一个,所以左子树只有一个节点9,右子树部分暂时不知道只知道剩下部分为右侧的前序和中序遍历结果,二叉树如下
再接下来,我们把右子树部分的按照同样的逻辑处理
我们知道了右子树的根节点为20,20的左子树只有一个节点15,右子树只有一个节点7
这样我们就重新构建完成了整棵二叉树
class Solution {
int[] preorder;
int[] inorder;
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
this.inorder = inorder;
int len = preorder.length-1;
return buildTree(0,len,0,len);
}
public TreeNode buildTree( int preL, int preR, int inL, int inR){
if (preL > preR){
return null;
}
TreeNode node = new TreeNode(preorder[preL]);
int len = 0;
for (int i = inL; i <= inR; i++) {
if (inorder[i] == preorder[preL]){
len = i - inL;
}
}
node.left = buildTree(preL+1,preL+len,inL,inL+len-1);
node.right = buildTree(preL+len+1,preR,inL+len+1,inR);
return node;
}
}
给你一个整数数组 nums
,返回 数组 answer
,其中 answer[i]
等于 nums
中除 nums[i]
之外其余各元素的乘积 。
题目数据 保证 数组 nums
之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请不要使用除法,且在 O(n)
时间复杂度内完成此题。
示例 1:
输入: nums =[1,2,3,4]
输出:[24,12,8,6]
示例 2:
输入: nums = [-1,1,0,-3,3] 输出: [0,0,9,0,0]
提示:
2 <= nums.length <= 105
-30 <= nums[i] <= 30
nums
之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内
进阶:你可以在 O(1)
的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)
前缀和(积)
class Solution {
public int[] productExceptSelf(int[] nums) {
int len = nums.length;
int[] arrL = new int[len];
int[] arrR = new int[len];
arrL[0] = 1;
arrR[len-1] = 1;
for (int i = 1; i < nums.length; i++) {
arrL[i] = nums[i-1] * arrL[i-1];
int rIdx = len-i-1;
arrR[rIdx] = nums[rIdx+1] * arrR[rIdx+1];
}
int[] res = new int[len];
for (int i = 0; i < res.length; i++) {
res[i] = arrL[i] * arrR[i];
}
return res;
}
}
class Solution {
public int[] productExceptSelf(int[] nums) {
int[] res = new int[nums.length];
res[0] = 1;
for (int i = 1; i < nums.length; i++) {
res[i] = res[i-1] * nums[i-1];
}
int preR = nums[nums.length-1];
for (int r = nums.length-2; r >= 0; r--) {
res[r] *= preR;
preR *= nums[r];
}
return res;
}
}
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点2
和节点8
的最近公共祖先是6。
示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 输出: 2 解释: 节点2
和节点4
的最近公共祖先是2
, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
注意:本题与主站 235 题相同:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
二叉搜索树特性
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (p.val > q.val){
return lowestCommonAncestor(root,q,p);
}
if (root.val == p.val || root.val == q.val){
return root;
}
if (root.val > p.val && root.val > q.val){
return lowestCommonAncestor(root.left,p,q);
}
if (root.val < p.val && root.val < q.val){
return lowestCommonAncestor(root.right,p,q);
}
return root;
}
}
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (p.val > q.val){
return lowestCommonAncestor(root,q,p);
}
TreeNode cur = root;
while ((cur.val > p.val && cur.val >q.val) || (cur.val < p.val && cur.val <q.val)){
if (cur.val > p.val && cur.val >q.val){
cur = cur.left;
}
if (cur.val < p.val && cur.val <q.val){
cur = cur.right;
}
}
return cur;
}
}
比较简单,不做过多分析了
输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
3 / \ 9 20 / \ 15 7
返回 true
。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1 / \ 2 2 / \ 3 3 / \ 4 4
返回 false
。
限制:
0 <= 树的结点个数 <= 10000
注意:本题与主站 110 题相同:https://leetcode-cn.com/problems/balanced-binary-tree/
DFS深搜模板套用
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
boolean isBalanced = true;
public boolean isBalanced(TreeNode root) {
dfs(root,0);
return isBalanced;
}
public int dfs(TreeNode node, int dep){
if (!isBalanced || null == node){
return dep;
}
dep++;
int leftDep = dfs(node.left,dep);
int rightDep = dfs(node.right,dep);
if (Math.abs(leftDep-rightDep )< 2){
return Math.max(leftDep,rightDep);
}
isBalanced = false;
return Math.max(leftDep,rightDep);
}
}
输入整数数组 arr
,找出其中最小的 k
个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入:arr = [3,2,1], k = 2 输出:[1,2] 或者 [2,1]
示例 2:
输入:arr = [0,1,2,1], k = 1 输出:[0]
限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000
堆排序
此处撰写解题思路
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if (k == 0){
return new int[0];
}
PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
for (int i : arr) {
if (queue.size() < k){
queue.offer(i);
}else if(i < queue.peek()){
queue.poll();
queue.offer(i);
}
}
int[] res = new int[k];
for (int i = 0; i < res.length; i++) {
res[i] = queue.poll();
}
return res;
}
}