55.链表中环的入口结点
- 题目描述:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
- 解题思路:使用HashMap保存遍历过的结点,当hashmap中保存了这个结点再次遍历到时,这个结点就是换的入口结点。
public ListNode EntryNodeOfLoop(ListNode pHead) {
HashMap<ListNode, Integer> map = new HashMap<>();
ListNode pNode = pHead;
while (pNode != null) {
if (map.containsKey(pNode)) {
return pNode;
} else {
map.put(pNode, 1);
pNode = pNode.next;
}
}
return null;
}
56.删除链表中重复的结点
- 题目描述:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
- 解题思路:首先想到的是匹配的思想,成对成对的删除,但是这样的话三个重复的结点就会保留一个不符合题意,首先该题中对重复结点的定义是结点中的value属性值重复,同时因为是排序链表,我们只需使用map记录重复的第一个结点的对象以及重复的个数即可。
ublic static ListNode deleteDuplication(ListNode pHead)
{
if (pHead == null){
return null;
}
HashMap<Integer,Integer> map = new HashMap<>();
ListNode pNode = pHead;
while (pNode != null){
if (map.containsKey(pNode.val)){
int value = map.get(pNode.val);
map.put(pNode.val,value+1);
}else{
map.put(pNode.val,1);
}
pNode = pNode.next;
}
pNode = pHead;
ListNode next = pNode.next;
ListNode pre = null;
while (pNode != null){
if (map.get(pNode.val) > 1){
for (int i = 1 ; i < map.get(pNode.val);i++){
next = next.next;
}
if (pre == null){
pNode = next;
pHead = pNode;
next = pNode.next;
}
else {
pre.next = next;
pNode = next;
if(next != null){
next = next.next;
}
}
}
else{
pre = pNode;
pNode = next;
if(next != null){
next = next.next;
}
}
}
return pHead;
}
- 二叉树的下一个结点
- 题目描述:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
- 解题思路:见注释
public TreeLinkNode GetNext(TreeLinkNode node) {
if (node == null) return null;
if (node.right != null) { //如果有右子树,则找右子树的最左节点
node = node.right;
while (node.left != null) node = node.left;
return node;
}
while (node.next != null) { //没右子树,则找第一个当前节点是父节点左孩子的节点
if (node.next.left == node) return node.next;
node = node.next;
}
return null; //退到了根节点仍没找到,则返回null
}
58.对称的二叉树
- 题目描述:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
- 解题思路:首先根节点以及其左右子树,左子树的左子树和右子树的右子树相同。左子树的右子树和右子树的左子树相同即可,采用递归。非递归也可,采用栈或队列存取各级子树根节点
boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot == null){
return true;
}
return comRoot(pRoot.left, pRoot.right);
}
private boolean comRoot(TreeNode left, TreeNode right) {
// TODO Auto-generated method stub
if(left == null) return right==null;
if(right == null) return false;
if(left.val != right.val) return false;
return comRoot(left.right, right.left) && comRoot(left.left, right.right);
}
59.按之字形顺序打印二叉树
- 题目描述:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
- 解题思路:分层处理使用两个栈。
public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
int layer = 1;
//s1存奇数层节点
Stack<TreeNode> s1 = new Stack<>();
s1.push(pRoot);
//s2存偶数层节点
Stack<TreeNode> s2 = new Stack<>();
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
while (!s1.empty() || !s2.empty()) {
if (layer%2 != 0) {
ArrayList<Integer> temp = new ArrayList<>();
while (!s1.empty()) {
TreeNode node = s1.pop();
if(node != null) {
temp.add(node.val);
System.out.print(node.val + " ");
s2.push(node.left);
s2.push(node.right);
}
}
if (!temp.isEmpty()) {
list.add(temp);
layer++;
System.out.println();
}
} else {
ArrayList<Integer> temp = new ArrayList<>();
while (!s2.empty()) {
TreeNode node = s2.pop();
if(node != null) {
temp.add(node.val);
System.out.print(node.val + " ");
s1.push(node.right);
s1.push(node.left);
}
}
if (!temp.isEmpty()) {
list.add(temp);
layer++;
System.out.println();
}
}
}
return list;
}
60.序列化二叉树
- 题目描述:请实现两个函数,分别用来序列化和反序列化二叉树
- 解题思路:
public int index = -1;
String Serialize(TreeNode root) {
StringBuffer sb = new StringBuffer();
if(root == null){
sb.append("#,");
return sb.toString();
}
sb.append(root.val + ",");
sb.append(Serialize(root.left));
sb.append(Serialize(root.right));
return sb.toString();
}
TreeNode Deserialize(String str) {
index++;
int len = str.length();
if(index >= len){
return null;
}
String[] strr = str.split(",");
TreeNode node = null;
if(!strr[index].equals("#")){
node = new TreeNode(Integer.valueOf(strr[index]));
node.left = Deserialize(str);
node.right = Deserialize(str);
}
return node;
}