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. 另一棵树的子树