【剑指Offer36-二叉搜索树与双向循环链表(C++附带完整测试)】

题目:
在这里插入图片描述
在这里插入图片描述
嗯。。这题呢我大概想了两种方法。第一种是递归时直接更改,第二种是先遍历得到序列,然后再统一修改。两种方法的时间复杂度上面差不了很多。

首先,对于一棵二叉搜索树(排序树),中序遍历可以得到排序序列。因此,我们就很容易可以想到第一种方法。中序遍历一遍,然后使用一个数组存储指向每个节点的指针。然后从头到尾修改left和right指针就可以了。

第二种方法就是在中序遍历递归的时候修改,使用一个指针pre来记录上一个节点,来完成整个链表的融合。最后只需要略微调整首尾节点就可以了。

具体细节看代码吧
包括了建立二叉树的过程:
C++代码附带测试:

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

class Node {
public:
    int val;
    Node* left;
    Node* right;

    Node() {}

    Node(int _val) {
        val = _val;
        left = nullptr;
        right = nullptr;
    }

    Node(int _val, Node* _left, Node* _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};

Node* createTree(vector<int> a,int i){
	if(a[i]==-1){
		return nullptr;
	}
	
	Node* root = new Node(a[i]);
	int leftson = i*2+1;
	int rightson = i*2+2;
	
	if(leftson>a.size()-1){
		root->left = nullptr;
	}else{
		root->left = createTree(a,leftson);
	}
	
	if(rightson>a.size()-1){
		root->right = nullptr;
	}else{
		root->right = createTree(a,rightson);
	}
	
	return root;
}

void inorder(Node* root){
	if(root==nullptr){
		return;
	}
	inorder(root->left);
	cout<<root->val<<" ";
	inorder(root->right);
}

class Solution {
public:
//    Node* treeToDoublyList(Node* root) {//第一种 
//    	if(root==nullptr){
//    		return nullptr;
//		}
//        getArray(root);
//        for(int i=1;i<sortPath.size();i++){
//        	sortPath[i]->left = sortPath[i-1];
//		}
//		for(int i=sortPath.size()-2;i>=0;i--){
//        	sortPath[i]->right = sortPath[i+1];
//		}
//		sortPath[0]->left = sortPath[sortPath.size()-1];
//		sortPath[sortPath.size()-1]->right = sortPath[0];
//		
//		return sortPath[0];
//    }
    
    Node *head = nullptr;
    Node *pre = nullptr;
    Node* treeToDoublyList(Node* root) {
    	if(root==nullptr){
    		return nullptr;
		}
		inorder(root);
		head->left = pre;
		pre->right = head;
		return head;
    }
    
    bool haveCircle(Node* head){//双指针判定是否有环
    	if(head==nullptr){
    		return false;
		}
		Node* ptr1 = head;
		Node* ptr2 = head->right->right;
		while(ptr1!=nullptr&&ptr2!=nullptr){
			if(ptr1==ptr2){
				return true;
			}
			ptr1 = ptr1->right;
			ptr2 = ptr2->right->right;
		}
		return false;
	}
private:
	vector<Node*> sortPath;
	void getArray(Node* root){
		if(root==nullptr){
			return;
		}
		getArray(root->left);
		sortPath.push_back(root);
		getArray(root->right);
	}
	void inorder(Node* root){
		if(root==nullptr){
			return;
		}
		inorder(root->left);
		if(pre==nullptr){
			head = root;
		}
		else{
			pre->right = root;
		}
		root->left = pre;
		pre = root;//这里不能用pre->right 
		inorder(root->right);
	}
};

int main(){
	vector<int> a = {4,2,5,1,3};
	Node* root = createTree(a,0);
	inorder(root);
	Solution solution;
	Node* head = solution.treeToDoublyList(root);
	Node* ptr = head;
	cout<<endl;
	cout<<solution.haveCircle(head)<<endl;
//	while(ptr!=nullptr){//朴素的判别方式 
//		cout<<ptr->val<<" ";
//		ptr = ptr->right;
//	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值