2021-6-4剑指笔记01

Posted 轻舟一曲

tags:

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

笔记01

_11_数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

示例 1:

输入: [7,5,6,4]
输出: 5

限制:

0 <= 数组长度 <= 50000

package LeetCode;

import org.junit.Test;
import sun.plugin2.gluegen.runtime.CPU;

import java.util.Arrays;

public class _11_数组中的逆序对 
    /*
    归并排序:在合并的时候进行统计
    * */
    public int reverseCount=0;
    public int reversePairs(int[] nums)
        if (nums==null||nums.length==0) return 0;
        copy=new int[nums.length];
        mergeSort(nums,0,nums.length-1);
        return reverseCount;
    
    //分
    public void mergeSort(int[] nums,int s,int e)
        if (s>=e) return;
        //[0,mid],[mid+1,e]
        int mid=(s+e)>>1;
        //后序遍历
        mergeSort(nums,s,mid);
        mergeSort(nums,mid+1,e);
        merge(nums,s,mid,e);
    
    //合并:需要用到辅助数组,双指针
    public int[] copy=null;
    public void merge(int[] nums,int s,int mid,int e)
        //复制数组
        int i=s;
        int j=mid+1;
        for (;i<=mid;i++) copy[i]=nums[i];
        for (;j<=e;j++) copy[j]=nums[j];
        int k=s;
        i=s;
        j=mid+1;
        for (;i<=mid&&j<=e;k++)//双指针,两份数组已经有序
            if (copy[i]>copy[j])
                nums[k]=copy[j];
                j++;
                reverseCount+=mid-i+1;
            
            else //不存在逆序
                nums[k]=copy[i];
                i++;
            
        
        //处理两数组剩余部分
        for (;i<=mid;i++) nums[k++]=copy[i];
        for (;j<=e;j++) nums[k++]=copy[j];
    




    @Test
    public void test()
       int[] nums=4,5,6,7;
        int i = reversePairs(nums);
        System.out.println(i);
    



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

输入两个链表,找出它们的第一个公共节点。

如下面的两个链表:

在节点 c1 开始相交。

示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。

注意:

如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

package LeetCode;

import java.util.ArrayDeque;

public class _12_两链表的第一个公共节点 
    public class ListNode 
       int val;
       ListNode next;
       ListNode(int x) 
           val = x;
           next = null;
       
    
    /*
    两种方法:
    方法一:逆向思维,从后开始往前比较,要用到栈,O(m+n) O(m)
    方法二:快慢指针
    * */
    public ListNode getIntersectionNode01(ListNode headA, ListNode headB) 
       if (headA==null||headB==null) return null;
        ArrayDeque<ListNode> dequeA = new ArrayDeque<>();
        ArrayDeque<ListNode> dequeB = new ArrayDeque<>();
        ListNode A=headA;
        ListNode B=headB;
        while (A!=null)
            dequeA.addFirst(A);
            A=A.next;
        
        while (B!=null)
            dequeB.addFirst(B);
            B=B.next;
        
        ListNode temp=null;
        while (!dequeA.isEmpty()&&!dequeB.isEmpty())
            if (dequeA.getFirst()!=dequeB.getFirst())//有个bug就是当只有一个节点时不进这个判断
                break;
            
            temp=dequeA.removeFirst();
            dequeB.removeFirst();
        
        return temp;
    

    public ListNode getIntersectionNode(ListNode headA, ListNode headB)
        if (headA==null||headB==null) return null;
        int countA=0;
        int countB=0;
        ListNode A=headA;
        ListNode B=headB;
        while (A!=null)
            countA++;
            A=A.next;
        
        while (B!=null)
            countB++;
            B=B.next;
        
        A=headA;
        B=headB;
        ListNode common=null;
        if (countA>countB)
            for (int i = 0; i < countA - countB; i++) 
                A=A.next;
            
            while (A!=null)
                if (A==B)
                    common=A;
                    break;
                
                A=A.next;
                B=B.next;
            
        
        else 
            for (int i = 0; i < countB - countA; i++) 
                B=B.next;
            
            while (A!=null)
                if (A==B)
                    common=A;
                    break;
                
                A=A.next;
                B=B.next;
            
        
        return common;
    

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

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

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: 0

限制:

0 <= 数组长度 <= 50000

package LeetCode;

import org.junit.Test;

public class _13_一个数字在排序数组中出现的次数 
    /*
    用二分查找算法找到第一个k和最后一个k出现的位置
    * */
    @Test
    public void  test()
        int[] a=2,2;
        int search = search(a, 2);
        System.out.println(search);
    

    public int search(int[] nums, int target) 
        if (nums==null) return 0;
        if (nums.length==0) return 0;
        int first=getFirstK(nums,0,nums.length-1,target);
        int last=getLastK(nums,0,nums.length-1,target);
        //如果没有k
        if (first==-1&&last==-1) return 0;
        //如果有k
        else if (first==last) return 1;
        else return last-first+1;
    
    public int getFirstK(int[] nums,int s,int e,int target)
        int mid=0;
        while (s<=e)
            mid=(s+e)>>1;
            if (nums[mid]>target) e=mid-1;
            else if (nums[mid]<target) s=mid+1;
            else 
                if (mid-1>=0&&nums[mid-1]==target) e=mid-1;
                else break;
            
        
        if (s>e) mid=-1;
        return mid;
    
    public int getLastK(int[] nums,int s,int e,int target)
        int mid=0;
        while (s<=e)
            mid=(s+e)>>1;
            if (nums[mid]>target) e=mid-1;
            else if (nums[mid]<target) s=mid+1;
            else 
                if (mid+1<=nums.length-1&&nums[mid+1]==target) s=mid+1;
                else break;
            
        
        if (s>e) mid=-1;
        return mid;
    


_14_0到n减1中缺失的数字

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

示例 1:

输入: [0,1,3]
输出: 2
示例 2:

输入: [0,1,2,3,4,5,6,7,9]
输出: 8

限制:

1 <= 数组长度 <= 10000

package LeetCode;

public class _14_0到n减1中缺失的数字 
    /*
    方法一:先求出0~n-1的和(n-1)*n/2,再求数组,做差即可  O(N)
    方法二:利用数组递增  二分  找出第一个数组元素与下标不同的
    * */
    public int missingNumber(int[] nums) 
        if (nums==null) return -1;
        if (nums.length==0) return -1;
        int s=0;
        int e=nums.length-1;
        int mid=0;
        while (s<=e)
            mid=(s+e)>>1;
            if (mid==nums[mid]) s=mid+1;
            else if (mid!=nums[mid])
                if (mid-1>=0&&mid-1!=nums[mid-1]) e=mid-1;
                else break;//找出第一个不等
            
        
        //程序有个bug,就是[0] 输出0
        if (mid==nums[mid]) mid=mid+1;
        return mid;
    

_15_二叉搜索树的第k大节点

给定一棵二叉搜索树,请找出其中第k大的节点。

示例 1:

输入: root = [3,1,4,null,2], k = 1
3
/
1 4

2
输出: 4
示例 2:

输入: root = [5,3,6,2,4,null,null,1], k = 3
5
/
3 6
/
2 4
/
1
输出: 4

限制:

1 ≤ k ≤ 二叉搜索树元素个数

package LeetCode;

import org.junit.Test;

import javax.swing.tree.TreeNode;
import java.util.ArrayDeque;

public class _15_二叉搜索树的第k大节点 
    public class TreeNode 
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x)  val = x; 
    

    //中序遍历的稍微变形
    public int K=0;
    public int numK=-1;
    public int kthLargest(TreeNode root, int k) 
        if (root==null) return -1;
        K=k;
        order(root);
        return numK;
    
    public void order(TreeNode root)
        if (root==null)  return;
        order(root.right);
        K--;
        if (K==0)
            numK=root.val;
            return;
        
        order(root.left);
    



_16_二叉树的深度

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

例如:

给定二叉树 [3,9,20,null,null,15,7],

3

/
9 20
/
15 7
返回它的最大深度 3 。

提示:

节点总数 <= 10000

package LeetCode;

import org.junit.Test;

public class _16_二叉树的深度 
    public class TreeNode 
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x)  val = x; 
    

    /*
    采用递归,后序遍历的方法:
    根节点的深度=(左子树的深度,右子树的深度)的最大值+1
    * */
    public int maxDepth(TreeNode root) 
        if (root==null) return 0;
        int left=maxDepth(root.left);
        int right=maxDepth(root.right);
        int max= Math.max(left, right)+1;
        return max;
    


_17_平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

示例 1:

给定二叉树 [3,9,20,null,null,15,7]

3

/
9 20
/
15 7
返回 true 。

示例 2:

给定二叉树 [1,2,2,3,3,null,null,4,4]

   1
  / \\
 2   2
/ \\

3 3
/
4 4
返回 false 。

限制:

0 <= 树的结点个数 <= 10000

package LeetCode;

import org.junit.Test;

public class _17_平衡二叉树 
    public class TreeNode 
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x)  val = x; 
    

    //判断一颗树是否为平衡二叉树
    public boolean isBalanced(    TreeNode root)
        if (root==null) return true;//空的时候为平衡
        int[] depth= 0剑指offer-数字在排序数组中出现的次数

LeetCode Java刷题笔记—572. 另一棵树的子树

LeetCode Java刷题笔记—572. 另一棵树的子树

2021-6-13-剑指笔记01

2021-6-13-剑指笔记01

2021-6-13-剑指笔记01