剑指offer36-40

Posted lgh544

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer36-40相关的知识,希望对你有一定的参考价值。

36 两个链表的第一个公共节点

  输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

时间复杂度:O(m+n), m,n分别为链表A,B的长度,最坏情况下,公共结点为最后一个,需要遍历m+n个结点
空间复杂度:O(1)

看下面的链表例子:
0-1-2-3-4-5-null
a-b-4-5-null
代码的ifelse语句,对于某个指针p1来说,其实就是让它跑了连接好的的链表,长度就变成一样了。
如果有公共结点,那么指针一起走到末尾的部分,也就一定会重叠。看看下面指针的路径吧。
p1: 0-1-2-3-4-5-null(此时遇到ifelse)-a-b-4-5-null
p2: a-b-4-5-null(此时遇到ifelse)0-1-2-3-4-5-null
因此,两个指针所要遍历的链表就长度一样了!
如果两个链表存在公共结点,那么p1就是该结点,如果不存在那么p1将会是null。

public class FindFirstCommonNode_36 {

    public static void main(String[] args) {
        FindFirstCommonNode_36 result = new FindFirstCommonNode_36();
        ListNode7 root = new ListNode7(4);
        ListNode7 node1 = new ListNode7(1);
        ListNode7 node2 = new ListNode7(3);
        ListNode7 node3 = new ListNode7(4);
        ListNode7 node4 = new ListNode7(5);
        ListNode7 root2 = new ListNode7(6);
        ListNode7 node6 = new ListNode7(7);
        ListNode7 node7 = new ListNode7(8);
        root.next = node1;
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        root2.next = node6;
        node6.next = node7;
        node7.next = node2;
        
        ListNode7 res = result.FindFirstCommonNode(root,root2);
        if(res != null)
        System.out.println(res.val);
    }
    public ListNode7 FindFirstCommonNode(ListNode7 listNode,ListNode7 listNode2) {
        if(listNode == null || listNode2 == null) return null;
        ListNode7 p1 = listNode;
        ListNode7 p2 = listNode2;
        while(p1 != p2) {
            p1 = p1.next;
            p2 = p2.next;
            if(p1 != p2) {
                if(p1 == null)p1 = listNode2;
                if(p2 == null)p2 = listNode;
            }
        }
        return p1;
    }

}
class ListNode7{
    int val;
    ListNode7 next;
    public ListNode7(int val) {
        this.val = val;
    }
    
}

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

  统计一个数字在排序数组中出现的次数

时间复杂度:O(logN)
空间复杂度:O(1)

 

就是先二叉搜索找一下这个元素的位置,然后再开始遍历搜索一下。

没有写main函数

import java.util.Arrays;
public class Solution {

    public int GetNumberOfK(int [] array , int k) {
        int index = Arrays.binarySearch(array, k);
        if(index<0)return 0;
        int cnt = 1;
        for(int i=index+1; i < array.length && array[i]==k;i++)
            cnt++;
        for(int i=index-1; i >= 0 && array[i]==k;i--)
            cnt++;
        return cnt;

    }
}

38 二叉树的深度

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

//递归
 public int TreeDepth(TreeNode root) {
    if(root==null){
        return 0;
    }
    int left=TreeDepth(root.left);
    int right=TreeDepth(root.right);
    return Math.max(left,right)+1;
}
//非递归:利用队列,count是当前的节点,nextcount是当前深度总的节点。【总是要遍历到当前深度的最后一个节点,深度才加1】

import java.util.LinkedList;
import java.util.Queue;
 public int TreeDepth1(TreeNode root) {
    if(root==null) {
      return 0;
    }
    Queue<TreeNode> q=new LinkedList<TreeNode>();
    q.add(root);
    int d=0,count=0,nextcount=q.size();
    while(q.size()!=0) {
      TreeNode t=q.poll();
      count++;
      if(t.left!=null) {
           q.add(t.left);
      }
      if(t.right!=null) {
           q.add(t.right);
      }
      if(count==nextcount) {
           d++;
           count=0;
           nextcount=q.size();
      }
    }
    return d;
}

39 平衡二叉树(未写main函数)

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

在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
时间复杂度:O(N)
空间复杂度:O(N)
public class Solution {
  public boolean IsBalanced_Solution(TreeNode root) {
        return depth(root) != -1;
    }
    public int depth(TreeNode root){
        if(root == null)return 0;
        int left = depth(root.left);
        if(left == -1)return -1; //如果发现子树不平衡之后就没有必要进行下面的高度的求解了
        int right = depth(root.right);
        if(right == -1)return -1;//如果发现子树不平衡之后就没有必要进行下面的高度的求解了
        if(left - right <(-1) || left - right > 1)
            return -1;
        else
            return 1+(left > right?left:right);
    }

  
}

40 数组中只出现一次的数字

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

时间复杂度:O(n)
空间复杂度:O(n)

import java.util.HashMap;
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        //哈希算法
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        for(int i=0; i < array.length; i++){
            if(map.containsKey(array[i]))
                map.put(array[i],2);
            else
                map.put(array[i],1);
        }
        int count = 0;
        for(int i=0; i < array.length; i++){
            if(map.get(array[i]) == 1){
                if(count == 0){
                    num1[0] =  array[i];
                    count++;
                }else
                    num2[0] =  array[i];
            }
        }

    }
}

 

以上是关于剑指offer36-40的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer(36-40)编程题

LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段

剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)

剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)

LeetCode(剑指 Offer)- 14- I. 剪绳子

LeetCode(剑指 Offer)- 14- I. 剪绳子