一棵二叉树原本是搜索二叉树,但是其中有两个节点调换了位置,使得这棵二叉树不再是搜索二叉树,请按升序输出这两个错误节点的值。(每个节点的值各不相同)
搜索二叉树:满足每个节点的左子节点小于当前节点,右子节点大于当前节点。
样例1图
样例2图
数据范围:,节点上的值满足 ,保证每个value各不相同
进阶:空间复杂度 ,时间复杂度
{1,2,3}
[1,2]
如题面图
{4,2,5,3,1}
[1,3]
/** * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ class Solution { public: /** * * @param root TreeNode类 the root * @return int整型vector */ vector<int> findError(TreeNode* root) { vector<int> nums; //存放中序遍历的结果 Inorder(root,nums); vector<int> copy=nums; sort(copy.begin(),copy.end()); vector<int> res; int len=copy.size(); for(int i=0;i<len;++i) { if(copy[i]!=nums[i]) { res.push_back(copy[i]); if(res.size()==2) break; } } return res; } void Inorder(TreeNode* root, vector<int>& nums) { if(root==nullptr) return ; Inorder(root->left, nums); nums.push_back(root->val); Inorder(root->right, nums); } };
import java.util.*; /* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * } */ public class Solution { int[] result = new int[2]; // 找到的目标节点 int findCount = 0; // 找到目标节点的数量,总数为2 int pre = 0; // 前继节点值 boolean hasPre = false; // 中序遍历是否有前继节点 // 有时候函数太多的时候就将其作为全局变量,或者有些递归函数需要的是变量值的实时情况,这个时候也需要全局变量。 // 想法:中序遍历整个树,然后找到两个降序对,第一个降序对的第一个节点值是较大数,第二个降序对的第二个节点值是较小数 public int[] findError (TreeNode root) { // write code here if (root.left == null && root.right == null) { return new int[]{}; } inorder(root); return result; } private void inorder(TreeNode node) { if (node != null && findCount != 2) { if (node.left != null) { inorder(node.left); } if (hasPre) { if (pre > node.val) { if (findCount == 0) { result[1] = pre; findCount++; } else { result[0] = node.val; findCount++; } } } pre = node.val; hasPre = true; if (node.right != null) { inorder(node.right); } } } }
class Solution { vector<int> path; void dfs(TreeNode* root) { if (root->left) dfs(root->left); path.push_back(root->val); if (root->right) dfs(root->right); } public: vector<int> findError(TreeNode* root) { dfs(root); for (int &i : path) cout << i << ' '; int l = 0, r = path.size() - 1; while (l < r+1) { if (path[l] < path[l+1]) l++; else if (path[r-1] < path[r]) r--; else break; } return {path[r], path[l]}; } };
// 中序遍历,把错位的找出来 public static int[] findError(TreeNode root) { // write code here ArrayList<Integer> res = new ArrayList<>(); midOrder(root, res); ArrayList<Integer> copy = new ArrayList<>(res); copy.sort(Comparator.comparingInt(o -> o)); // 找到乱序的两个位置 int[] ret = new int[2]; for (int i = 0; i < res.size(); i++) { if(!res.get(i).equals(copy.get(i))){ ret[0] = copy.get(i); ret[1] = res.get(i); break; } } return ret; } private static void midOrder(TreeNode root, List<Integer> res) { if (root == null) return; midOrder(root.left, res); res.add(root.val); midOrder(root.right, res); }
import java.util.*; /* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * public TreeNode(int val) { * this.val = val; * } * } */ public class Solution { TreeNode preNode = null; TreeNode firstNode = null; TreeNode secondNode = null; public void inorder(TreeNode node) { if (node == null) { return; } inorder(node.left); if (preNode != null && preNode.val > node.val) { if (firstNode == null) { firstNode = preNode; } secondNode = node; } preNode = node; inorder(node.right); } public int[] findError (TreeNode root) { inorder(root); return firstNode.val < secondNode.val ? new int[] {firstNode.val, secondNode.val} : new int[] {secondNode.val, firstNode.val}; } }
public class Solution { public int[] findError (TreeNode root) { List<Integer> list = new ArrayList<>(); midOrder(list, root); int size = list.size(); int numa = -1, numb = 0; for(int i=1;i<size-1;i++){ if(numa!=0 && list.get(i) < list.get(i-1)) numa = list.get(i); if(numb==0 && list.get(i) > list.get(i+1)) numb = list.get(i); } if(list.get(0) > list.get(1)) numb = list.get(0); if(list.get(size-1) < list.get(size-2)) numa = list.get(size-1); return new int[]{numa, numb}; } public static void midOrder(List<Integer> list, TreeNode root){ if(root != null){ midOrder(list, root.left); list.add(root.val); midOrder(list, root.right); } } }获取二叉树中序遍历的结果,从前往后第一个比后一个数大的数为较大的交换数,从后往前第一个比前一个数小的数为较小的交换数
int minVal=Integer.MIN_VALUE ,p1=0 ,p2=0; public int[] findError (TreeNode root) { // write code here dfs(root); return new int[]{p2 ,p1}; } public void dfs(TreeNode root){ if(root==null){ return; } dfs(root.left); if(minVal>root.val){ if(p1==0){ p1=minVal; p2=root.val; }else{ // 如果第二次出现了逆序,则第二次逆序的小值为错误节点 p2=root.val; } } minVal=root.val; dfs(root.right); }
import java.util.*; /* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * public TreeNode(int val) { * this.val = val; * } * } */ public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param root TreeNode类 the root * @return int整型一维数组 */ public int[] findError (TreeNode root) { // write code here // 中序遍历有序 Deque<TreeNode> queue = new ArrayDeque<>(); List<Integer> list = new ArrayList<>(); TreeNode cur = root; while(cur != null || !queue.isEmpty()) { if(cur != null) { queue.offerLast(cur); cur = cur.left; } else { cur = queue.pollLast(); list.add(cur.val); cur = cur.right; } } int[] res = new int[2]; for(int i = 0; i < list.size() - 1; i++) { if(list.get(i) > list.get(i + 1)) { res[0] = i + 1; break; } } for(int i = list.size() - 1; i > 0; i--) { if(list.get(i) < list.get(i - 1)) { res[1] = i + 1; break; } } return res; } }
#include <vector> class Solution { public: vector<int>list; void find(TreeNode* root) { if(root) { find(root->left); list.push_back(root->val); find(root->right); } } vector<int> findError(TreeNode* root) { find(root); vector<int>ans; int j=0; for(int i=0;i<list.size()-1;i++){ if(list[i]>list[i+1]) { j=i; break; } } ans.push_back(list[j]); int minn=list[j+1]; for(int i=j+1;i<list.size();i++){ minn=min(minn,list[i]); } ans.push_back(minn); sort(ans.begin(),ans.end()); return ans; } };
/** * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * }; */ class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param root TreeNode类 the root * @return int整型vector */ vector<int> v; vector<int> findError(TreeNode* root) { // write code here dfs(root); vector<int> t = v; sort(t.begin(), t.end()); vector<int> idxV; for (int i = 0; i < t.size(); ++i) { if (t[i] != v[i]) { idxV.push_back(t[i]); } } return idxV; } void dfs(TreeNode* root) { if (root == nullptr) return; dfs(root->left); v.push_back(root->val); dfs(root->right); } };
import java.util.*; /* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * public TreeNode(int val) { * this.val = val; * } * } */ public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param root TreeNode类 the root * @return int整型一维数组 */ public int[] findError (TreeNode root) { // write code here if(root==null){ return null; } ArrayList<Integer> list=new ArrayList<>(); mid(root,list); int arr[]=new int[2]; for(int i=0;i<list.size()-1;i++){ for(int j=i+1;j<list.size();j++){ //交换后判断是否递增 int tmp=list.get(i); list.set(i,list.get(j)); list.set(j,tmp); if(isUP(list)==true){ arr[0]=list.get(i); arr[1]=list.get(j); return arr; //不符合递增就变回去进行下一轮判断 }else{ tmp=list.get(i); list.set(i,list.get(j)); list.set(j,tmp); } } } return null; } public void mid(TreeNode root,ArrayList<Integer> list){ if(root==null){ return; } mid(root.left,list); list.add(root.val); mid(root.right,list); } public boolean isUP(ArrayList<Integer> list){ for(int i=1;i<list.size();i++){ if(list.get(i)<list.get(i-1)){ return false; } } return true; } }
package main import . "nc_tools" /* * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */ /** * * @param root TreeNode类 the root * @return int整型一维数组 */ func findError( root *TreeNode ) []int { var a,b int arr:=order(root) for i,x:=range arr{ if i>0&&x<arr[i-1]{ if a==0{ a,b=arr[i-1],x }else{ b=x break } } } if a>b{ return []int{b,a} } return []int{a,b} } func order(root *TreeNode)[]int{ if root==nil{ return nil } ans:=[]int{} ans=append(ans,order(root.Left)...) ans=append(ans,root.Val) ans=append(ans,order(root.Right)...) return ans }
两种情况:
只需要把这两次 记录下来即可
2. 两个交换的节点相邻,那么只会产生一次: pre.val > cur.val
两种情况可以合在一起考虑,即第一次发生 pre.val > cur.val时,记录res = {cur.val,pre.val}
如果后面再发生pre.val > cur.val,则替换 cur.val
public int[] findError (TreeNode root) { // write code here dfs(root); return res; } int[] res = new int[2]; int cnt = 1; TreeNode pre = null; public void dfs(TreeNode cur){ if(cur == null){ return; } dfs(cur.left); if(pre == null){ pre = cur; dfs(cur.right); } else{ if(pre.val > cur.val){ if(cnt > 0){ res[cnt] = pre.val; res[0] = cur.val; } else{ res[cnt] = cur.val; } cnt --; if(cnt <0){ return; } } pre = cur; dfs(cur.right); } }
class Solution { public: /** * * @param root TreeNode类 the root * @return int整型vector */ int curError=0; int error1=-1,error2=-2; int pre=-1; vector<int> findError(TreeNode* root) { // write code here if(!root) return {}; dfs(root); if(error1>error2) swap(error1,error2); return {error1,error2}; } void dfs(TreeNode* root){ if(!root) return; if(curError==2) return; dfs(root->left); if(pre==-1) pre=root->val; else{ if(pre>root->val&&curError==0){ error1=pre; error2=root->val; curError++; } else if(pre>root->val&&curError==1){ error2=root->val; curError++; } } pre=root->val; dfs(root->right); } };
/** * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ class Solution { public: /** * * @param root TreeNode类 the root * @return int整型vector */ TreeNode * rem1 = nullptr;//第一个 不为升序 的 大节点 TreeNode * rem2 = nullptr;//rem1 的相邻节点 TreeNode * rem3 = nullptr;// 第二个 不为升序的 小节点 TreeNode * t_pre = nullptr; vector<int> findError(TreeNode* root) { // write code here if (root == nullptr ) return {}; //vector<TreeNode *> res; moris(root/*, res*/); if (rem3 == nullptr) return {rem2 -> val, rem1 -> val}; return {rem3 -> val,rem1 -> val}; } // 莫里斯遍历: 搭桥拆桥 // 前序和中序 都是: 左子树的节点会到达两次 // ==> 第一次 到达就打印 是前序 第二次到达就打印 是中序 // ==> 右子节点只会到达一次: 到达就打印 // 后续遍历 把所有的left 和right换一下jiuok void moris (TreeNode * root/*,vector<TreeNode *> & res*/) { if (root == nullptr) return ; TreeNode * cur = root; while (cur) { if (cur -> left == nullptr) { //res.push_back(cur); if (t_pre == nullptr) { t_pre = cur; }else { if (cur -> val < t_pre -> val) { if (rem1 == nullptr) { rem1 = t_pre; rem2 = cur; }else { rem3 = cur; } } t_pre = cur; } cur = cur -> right; } else { TreeNode * pre = cur -> left; while (pre -> right != nullptr && pre -> right != cur) { //pre-> right -== null 说明是第一次到达 // pre-> right == cur 说明是第二次到达 pre = pre -> right; } if (pre -> right == nullptr) { //第一次到达 pre -> right = cur; cur = cur -> left; }else { pre -> right = nullptr; if (t_pre == nullptr) { t_pre = cur; }else { if (cur -> val < t_pre -> val) { if (rem1 == nullptr) { rem1 = t_pre; rem2 = cur; }else { rem3 = cur; } } t_pre = cur; } //res.push_back(cur); cur = cur -> right; } } } return ; } };
class Solution { public: /** * * @param root TreeNode类 the root * @return int整型vector */ vector<int> findError(TreeNode* root) { // write code here vector<int> err; search(root, err); vector<int> tmp(err); vector<int> ans; ans.reserve(2); sort(tmp.begin(), tmp.end()); for(int i = 0; i < err.size()-1; ++i) { if(err[i] != tmp[i]) { ans.push_back(tmp[i]); ans.push_back(err[i]); break; } } return ans; } void search(TreeNode* node, vector<int>& err) { if(node == nullptr) return; search(node->left, err); err.push_back(node->val); search(node->right, err); return; } }; 笨方法
class Solution: def findError(self , root: TreeNode) -> List[int]: # write code here def dfs(root): if not root:return dfs(root.left) if root.val !=self.count:self.res.append(root.val) self.count +=1 dfs(root.right) self.res,self.count =[],1 dfs(root) self.res.sort() return self.res