剑指offer题解8

剑指offer题解8

34 两个链表的第一个公共结点

题目描述
输入两个链表,找出它们的第一个公共结点。

分析:

  1. 方法一:使用Set,记录是否出现过该节点
  2. 方法二:因为如果有公共的节点,那么从这个节点之后,这两个链表共享一系列的节点;计算出两个链表的长度,然后长的链表先走一段路程,使得两个链表长度一样,那么从这个时候开始他么一起遍历,第一个相同的节点就是公共节点。
  3. 方法三:假如p1由x,z组成,p2由y,z组成,z为共享的部分,如果有一种方法,使得两个链表每次走一步,都走x+y+z步,而且停留在z的开始的位置,那么我们就找到了这个节点。方法:当一个节点到了尾部,那么它就从另一个链表开始的位置开始继续遍历即可。

//方法一:
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode p1=pHead1,p2=pHead2;
        HashSet<ListNode> set=new HashSet<>();
        while(p1!=null||p2!=null){
            if(p1!=null){
                if(set.contains(p1)){
                    return p1;
                }
                set.add(p1);
                 p1=p1.next;
            }
            if(p2!=null){
                if(set.contains(p2)){
                    return p2;
                }
                set.add(p2);
                p2=p2.next;
            }
        }
        return null;
    }
}



//方法二

public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode p1=pHead1,p2=pHead2;
        int len1=len(p1);
        int len2=len(p2);
        int offset=Math.abs(len1-len2);
        if(len1>len2){
            p1=walk(offset,p1);
        }else{
            p2=walk(offset,p2);
        }
        while(p1!=p2){
            p1=p1.next;
            p2=p2.next;
        }
        return p1;
    }
    private static ListNode walk(int offset,ListNode list){
        while(offset--!=0){
                list=list.next;
            }
        return list;
    }
    private static int len(ListNode list){
        int len=0;
        while(list!=null){
            len++;
            list=list.next;
        }
        return len;
    }



//方法三

public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode p1=pHead1,p2=pHead2;
        while(p1!=p2){
            p1= p1==null?pHead2:p1.next;
            p2= p2==null?pHead1:p2.next;
        }
        return p1;
    }

35 数字在排序数组中出现的次数

题目描述
统计一个数字在排序数组中出现的次数。

分析:

  1. 方法一:找到这个数,然后向两边扩展,最坏复杂度O(n)
  2. 方法二:找到第一个出现的位置,找到最后一个出现的位置,都使用二分法,最坏复杂度O(logN)

//方法一
public class Solution {
    public int GetNumberOfK(int [] array , int k) {
       int l=0,r=array.length,mid=0,count=0;
        while(l<r){
            mid=(r-l)/2+l;
            int curr=array[mid];
            if(curr==k){
                break;
            }else if(curr>k){
                r=mid-1;
            }else{
                l=mid+1;
            }
        }
        if(array.length==0||array[mid]!=k){
            return 0;
        }
        int p=mid;
        while(p>=0&&array[p--]==k){
             count++;
        }
        p=mid+1;
        while(p<array.length&&array[p++]==k){
             count++;
        }
        return count;
        
    }
}



//方法二
public class Solution {
    public int GetNumberOfK(int [] array , int k) {
       if(array==null||array.length==0){
           return 0;
       }
        int l=getFirstK(array,0,array.length-1,k);
        int r=getLastK(array,0,array.length-1,k);
        if(l==-1||r==-1){
            return 0;
        }
        return r-l+1;
        
    }
    
    
    private static int getFirstK(int[] array,int l,int r,int k){
        while(l<=r){
            int mid=(l+r)/2;
            if(array[mid]>k){
                r=mid-1;
            }else if(array[mid]<k){
                l=mid+1;
            }else{
                if(mid<=0||array[mid-1]!=k){
                    return mid;
                }else{
                    r=mid-1;
                }
            }
        }
        return -1;
    }
    
    private static int getLastK(int[] array,int l,int r,int k){
        while(l<=r){
            int mid=(l+r)/2;
            if(array[mid]>k){
                r=mid-1;
            }else if(array[mid]<k){
                l=mid+1;
            }else{
                if(mid>=array.length-1||array[mid + 1] != k){
                    return mid;
                }else{
                    l=mid+1;
                }
            }
        }
        return -1;
    }
    
}

36 二叉树的深度

题目描述
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

分析:遍历即可


public class Solution {
    
    public int TreeDepth(TreeNode root) {
        if(root==null){
            return 0;
        }
        int lDepth=TreeDepth(root.left);
        int rDepth=TreeDepth(root.right);
        return Math.max(lDepth,rDepth)+1;
    } 
    
}

37 判断是否是是平衡二叉树

题目描述
输入一棵二叉树,判断该二叉树是否是平衡二叉树。

分析:递归判断左右节点的深度即可

public class Solution {
    private  boolean isBalance=true;
    public boolean IsBalanced_Solution(TreeNode root) {
        getDeep(root);
        return isBalance;
    }
    
    private  int getDeep(TreeNode root){
        if(root==null){
            return 0;
        }
        int lDeep=getDeep(root.left)+1;
        int rDeep=getDeep(root.right)+1;
        if(Math.abs(lDeep-rDeep)>1){
            isBalance=false;
        }
        return Math.max(lDeep,rDeep);
    }
}

猜你喜欢

转载自blog.csdn.net/gentlezuo/article/details/90904167