Leetcode题解(二)

1.binary-tree-postorder-traversal

        由题可知,本题主要求的是二叉树的后序遍历,根据二叉树后序遍历的顺序是先遍历左节点、然后遍历右节点、最后遍历根节点的顺序要求编写,代码如下:

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
import java.util.*;
public class Solution {
	public ArrayList<Integer> postorderTraversal(TreeNode root) {
		ArrayList<Integer> list=new ArrayList<>();
		if(root==null)
			return list;
		postorder(root,list);
		return list;
        
    }
	private static void postorder(TreeNode root,ArrayList<Integer> list)//左右根的顺序进行后续遍历,为便于递归,直接重新
	{
		if(root.left!=null)
			postorder(root.left,list);
		if(root.right!=null)
			postorder(root.right,list);
		list.add(root.val);
	}

}
2.binary-tree-preorder-traversal

        由题目可知,该题求的是二叉树的前序遍历,前序遍历则是根据根左右的顺序进行遍历的,代码如下:

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
import java.util.ArrayList;
public class Solution {
	public ArrayList<Integer> preorderTraversal(TreeNode root) {
		ArrayList<Integer> result=new ArrayList<>();
		if(root==null)
			return result;
		preorder(root,result);
		return result;
        
    }
	private static void preorder(TreeNode root,ArrayList<Integer> list)//左右根的顺序进行后续遍历,为便于递归,直接重新
	{
		list.add(root.val);
		if(root.left!=null)
			preorder(root.left,list);
		if(root.right!=null)
			preorder(root.right,list);
		
	}


}
3.reorder-list

        本题主要是的是另类的翻转链表,将后半部分翻转之后再依次插入前半部分两个结点之间即可。主要考察几个知识点,首先是寻找中间结点,从中间结点断开,分为前后两个链表,然后将后面那个链表翻转,最后将后面链表的元素根据要求插入到前面的链表中。实现代码如下:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public void reorderList(ListNode head) {
		ListNode pre=head;
		ListNode res;
		if(head==null) return;
		ListNode slow=head;
		ListNode fast=head;
		while(fast.next!=null&&fast.next.next!=null)
		{
			slow=slow.next;
			fast=fast.next.next;
		}
		res=slow.next;//后半段的头指针
		slow.next=null;
		ListNode temp=null;
		ListNode mid;
		//翻转链表
		while(res!=null)
		{
			mid=res.next;
			res.next=temp;
			temp=res;
			res=mid;
		}
		ListNode after=temp;//翻转后的链表
		
		while(pre!=null&&after!=null)
		{
			ListNode node1=pre.next;
			ListNode node2=after.next;
			pre.next=after;
			after.next=node1;
			after=node2;
			pre=node1;
		}
    }

        
    
}

4.linked-list-cycle


        这题是判断链表有没有环的问题,不占额外空间且效率比较高的算法是快慢指针的算法,即设置一个快指针一个慢指针,另快指针的速度是慢指针的两倍,然后两个指针都从头结点出发,如果两个指针最终还能相遇,则说明有环。

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {//使用快慢指针的方法来判断是否有环
	public boolean hasCycle(ListNode head) {
        if(head==null) return false;
		ListNode fast=head;
		ListNode slow=head;
		while(fast.next!=null&&fast.next.next!=null)
		{
			fast=fast.next.next;
			slow=slow.next;
            if(fast==slow)
				return true;
		}
		return false;
        
    }

}

5.linked-list-cycle-ii

        本题在判断如果有环的基础上还需要找到环的入口,那么如下图进行计算:

        首先,快慢指针都从O点出发,假设最终在B点相遇,根据两者速度关系,应该慢指针未满一圈就会被赶上,假设快指针跑了n圈然后在B点与慢指针相遇,两者的路程关系为2*(a+b)=a+b+n*(b+c);最后化简为a=(n-1)*(b+c)+c,所以可以发现如果慢指针运动距离为a的路径,将会回到A点,那么可以将快指针变为慢指针,并从O点出发,原来的慢指针从B点同时出发,最终相遇的地点就是A点,也就是环的入口。实现代码如下:
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
	public ListNode detectCycle(ListNode head) {
        if(head==null)
            return null;
		ListNode fast=head;
		ListNode slow=head;
		boolean isCircle=false;
		while(fast.next!=null&&fast.next.next!=null)
		{
			fast=fast.next.next;
			slow=slow.next;
			if(slow==fast)
			{
				isCircle=true;
				break;
			}
		}
		if(isCircle)
		{
			fast=head;
			while(slow!=fast)
			{
				slow=slow.next;
				fast=fast.next;
			}
			return slow;
		}
		return null;
        
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值