ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

leecode

2022-06-03 00:33:48  阅读:164  来源: 互联网

标签:index arr int 复杂度 question leecode 排序


面试 leecode

面试 刷题 leecode java版数据结构  

一、idea leecode插件安装及配置

 

1. 安装

IDEA插件安装套路

 

2. 配置

原配置

//code fileName 
[$!{question.frontendQuestionId}]${question.title}
//code template
${question.content}

${question.code}
//templact constant
${question.title}	题目标题	示例:两数之和
${question.titleSlug}	题目标记	示例:two-sum
${question.frontendQuestionId}	题目编号
${question.content}	题目描述
${question.code}	题目代码
$!velocityTool.camelCaseName(str)	转换字符为大驼峰样式(开头字母大写)
$!velocityTool.smallCamelCaseName(str)	转换字符为小驼峰样式(开头字母小写)
$!velocityTool.snakeCaseName(str)	转换字符为蛇形样式
$!velocityTool.leftPadZeros(str,n)	在字符串的左边填充0,使字符串的长度至少为n
$!velocityTool.date()	获取当前时间

改成如下:

  1. //code fileName 

  2. $!velocityTool.camelCaseName(${question.titleSlug}) 

  3. //code template 

  4. ${question.content} 

  5. public class $!velocityTool.camelCaseName(${question.titleSlug}){ 

  6.     public static void main(String[] args) { 

  7.         Solution solution = new $!velocityTool.camelCaseName(${question.titleSlug})().new Solution(); 

  8.          


  9.  

  10. ${question.code} 


 

3. 问题

 

3-1. 题目中文乱码

idea安装文件vmoptions里增加-Dfile.encoding=utf-8

 

二、B占左神7天刷题

 

1. 面试技巧(P1)

 

1-1. 刷题5大问题

  1. 书看不懂,吃灰
  2. 简单题过了,中难题写不出来,题看不明白
  3. 问题问题关联上某个算法和结构,搜到帖子,看不懂,想起了书(算法导论)
  4. 中等题也能写出来,难的算法题,还是门都没找到
  5. 不学不看算法,不做算法的工作,某个特定业务,某个算法比你的代码性能提高数倍。
  • 帖子难懂
  • 书难懂
  • 知识体系不足
 

2. 复杂度和简单排序算法(P2)

 

2-1. 复杂度

 

2-1-1. 时间复杂度

  1. 常数时间复杂度:如果和数据量没关系,叫做常数操作就是流程中的行为节点(int a=arr[i])
  2. 时间复杂度是算法流程中,常数操作数量的指标,发生多少常数操作
  3. 常数操作数量的表达式(int b=list.get(i) )只要高阶项,不要系数,然后就是时间复杂度O(f(n))
  4. 算法流程好坏先看时间复杂度,再看不同数据样本下的常数项时间:不同结构执行时间不同。比如找数数组要比list快。
 

2-1-2. 简单排序算法

  • 常数操作(流程中)
    1. 找数
    2. 比较大小
    3. 交换
  • 常数操作次数(常数操作数量)
    1. 找数N+N-1+N-2+...
    2. 比较N+N-1+N-2+...
    3. swap:N次
      一共常数操作次数表达式:aN^2+bN+c
  • 根据表达式获取复杂度原则舍弃bN+C忽略a得到的是N2得到O(N2) O在数学上是上限的含义

总结:评估性能的两个指标:时间复杂度,常数项执行时间

 

两个常数项时间不同的代码要实际跑才能看出优劣跟空间有关系
两个常数项时间不同的代码要实际跑才能看出优劣跟空间有关系

 

O最差,(-) 是平均,Ω是最优时间复杂度插入排序的最优是O(N)

 

2-1-3. 二分法O(logN)其实就是2为底

  1. 有序数组,某个数是否存在
  2. 在一个有序数组中,找>=某个数最左侧的位置
  3. 局部最小值问题
 

2-1-4. 对数器的概念和使用

  1. 有一个想要测的方法a
  2. 实现复杂度不好但是容易实现的方法b
  3. 实现一个随机样本产生器
  4. 把方法a和方法b跑相同的随机样本,看看结果是否一样
  5. 如果有一个随机样本使得对比结果不一致,打印样本进行人工干预,改对方法a或者方法b
  6. 当样本数量很多时对比测试一样正确,可以确认方法a已经正确。
 

2-1-5. 递归行为和递归行为时间复杂度的估算(P3认识O(NlogN)的排序)

用递归方法找一个数组中的最大值,系统上到底怎么做的?
master工时的使用

 

master公式
master公式

 

悬而未决的方法会压倒栈里去

 
2-1-5-1. master公式表达式说明
  • T(N) 母问题的数据量是N:案例为arr的长度N
  • N/b是子问题的规模都是N/b:案例是N/2;子问题数据是等量规模的。
  • a是子问题被调用次数:案例是调用2次
  • O(N^d)除去调用之外剩下的过程时间复杂度:案例是直接使用math函数返回是常数时间复杂度O(1);d=0
  1. public class Code08_GetMax { 

  2.     public static int getMax(int[] arr) { 

  3.         return process(arr,0,arr.length-1); 


  4.  

  5.     private static int process(int[] arr, int L, int R) { //process母问题规模N 

  6.         if(L==R){//arr[L...R]范围上只有一个数直接返回 

  7.             return arr[L]; 


  8.         /* 

  9.         * mid=(L+R)/2 中点一般这样计算,但是数组长度太大L+R可能溢出,mid可能算出负值下标 

  10.         * 可以写成mid=L+((R-L)/2) 除2可以换成位运算右移一位 

  11.         * */ 

  12.         int mid=L+((R-L)>>1);//中点 

  13.         int leftMax=process(arr,L,mid);//子问题规模N/2 

  14.         int rightMzx=process(arr,mid+1,R);//子问题调用次数是2次 

  15.         return Math.max(leftMax,rightMzx); 



 

不符合master公式案例
不符合master公式案例

 

如果logb^a<d 时间复杂度是O(N^d)如下图手写第一种就是上图master公式书写形式

 

master公式手写形式
master公式手写形式

 

 
2-1-5-2. 对数与指数

如果a^x =N(a>0,且a≠1),那么数x叫做以a为底N的对数,记作x=logaN,读作以a为底N的对数,其中a叫做对数的底数,N叫做真数。(上述master公式案例x=1所以常数时间复杂度是O(1))

 

2-1-6. MergeSort过程 归并排序时间复杂度O(NlogN)

  1. 分成左右两侧有序的子数组:2T(N/2)阶段
  2. 再顺序合并两个数据得到有序的数组:O(N)阶段

master
T(N)=2T(N/2)+O(N)
公式a=2,b=2,d=1符合loga^b=d时间复杂度是O(NlogN)

本地排局部数据落存有序分片其实就是有序的子数组,子数组后续合一进行归并排序合并不同机器数据。

让其整体有序的过程里用了外排序方法。额外空间复杂度O(N)

 
2-1-6-1. 小和问题(左侧比自己小的数)

 

小和数找数逻辑
小和数找数逻辑

 

最终1是小和数两次,2两次,3两次,4一次
最终和是1+1+3+2+2+3+4=16

左右数相等的时候,一定要先拷贝右组的数而且不产生小和。否则就不易知道有组有多少数比这个相等的数大。

 
2-1-6-1-1. 逆序对(左边数比右边数大则两个数构成一个逆序对)

所有数据的处理都要考虑漏重乱序

 

2-2. 快速排序

最坏划分partition的值最偏O(N^2),如果划分值是中点就会O(NlogN)

 

快排3.0和普通快排导致复杂度优化的逻辑差别
快排3.0和普通快排导致复杂度优化的逻辑差别

 

 

2-2-1. 荷兰国旗问题

 

荷兰国旗问题
荷兰国旗问题

 

 

交换逻辑当要6和5比较比5大左侧i不动,右侧j交换然后左移
交换逻辑当要6和5比较比5大左侧i不动,右侧j交换然后左移

 

小于区域推着等于区域往右走撞上右侧区域往左走的位置:每次就会确认下被比较的数(默认从右边第一个数做第一个被比较的数叫base num case)的位置!!递归下去就会确认下所有被比较的数也就是所有的数的位置。

快排的空间复杂度o(logN) 最差是o(N)

 

3. 堆,桶排序及排序总结(P4)

 

3-1. 堆

  1. 堆结构就是用数组实现的完全二叉树结构
  2. 完全二叉树中如果每棵子树最大值在顶部就是大根堆:有序
  3. 完全二叉树中如果每棵子树的最小值在顶部就是小根堆:有序
  4. 堆结构的heap Insert与heap ify操作
  5. 堆结构的增大和减少
  6. 优先级队列结构,就是堆结构

 

数组顺序和二叉树对应位置
数组顺序和二叉树对应位置

 

 

插入数据找插入树大根堆的位置heap Insert
插入数据找插入树大根堆的位置heap Insert

 

  1. //某个数出现在index上,往上继续移动 

  2. public static void heapInsert(int[] arr,int index){ 

  3.     while(arr[index]>arr[(index-1)/2]){ 

  4.     swap(arr,index,(index-1)/2); 

  5.     index=(index-1)/2; 



  6.  //某个数在index位置,能否往下移动 

  7.     /* 

  8.     *从任何位置都可以做heapify;heapSize限制数组大小,能确认左右孩子是否存在,越界不存在 

  9.     *1. 找数中的最大值(放到顶部成堆) 

  10.     * 2. 剩下的数据调整成大根堆 

  11.     * */ 

  12.     private static void heapify(int[] arr, int index, int heapSize) { 

  13.         int left=index*2+1;//左孩子的下标 

  14.         while (left < heapSize) {//下方还有孩子的时候,left越界就没孩子,left小于右孩子下标 

  15.             //两个孩子中,谁值大,把下标给largest 

  16.             int largest=left+1<heapSize&&arr[left+1]>arr[left]?left+1:left; 

  17. //            父和孩子之间,谁值大,把下标给largest 

  18.             largest=arr[largest]>arr[index]?largest:index; 

  19.             if(largest==index){ 

  20.                 break; 


  21.             swap(arr,largest,index); 

  22.             index=largest; 

  23.             left=index*2+1; 



左右孩子树最大值都比自己小或者自己没有左右孩子数就排序完毕成大根堆。

heapify往下调整,heapInsert往上调整数

 

两个方法的功能
两个方法的功能

 

为什么时间复杂度都是logN因为无论是插入还是移除后调整成大根堆都是调整树的高度高度和数的数量N的关系就是logN函数

 

时间复杂度和高度和数的数量关系
时间复杂度和高度和数的数量关系

 

堆的调整都是高度的调整所以是logN

 

如果数都存在通过heapify(从右往左往下)调整出一个大根堆
如果数都存在通过heapify(从右往左往下)调整出一个大根堆

 

满二叉树:最底层节点=N/2,每个节点heapify往下移动0次,但是循环了一次进行了1次操作代价是1

倒数第二层:N/4,代价是2;如下图

 

复杂度公式得出的过程
复杂度公式得出的过程

 

 

如果数不是一个个增加而是都有可以搞成大根堆如下复杂度
如果数不是一个个增加而是都有可以搞成大根堆如下复杂度

 

 

3-1-1. 几乎有序数组排序:准备k的小根堆时间复杂度o(N*logK)

 
3-1-1-1. 以10为底
  • 当0<n<10 的时候 nlogn<n
  • 当n=10 的时候 nlogn=n
  • 当n>10 的时候 nlogn>n

也就是说log函数的幂>底数时N*logN会>N;时间复杂度偏高。当幂和底数(底数不能是0和1)相同log函数值为1得O(1);

 
3-1-1-2. 手写堆的需求场景
  • 手写堆的场景需求:形成堆的数据需要指定位置的数据进行修改,手写可以以最少代价减少heapify,heapinsert次数;
  • 但是系统的优先级队列不支持,这种调整数据的需求,因为它的代价太高要重新所有数据进行多次的heapify
 

3-2. 比较器(第三天内容)

 

3-2-1. 比较器的使用

  1. 比较器(JAVA)的实质就是重载比较运算符(C++)
  2. 比较器可以很好的应用在特殊标准的排序上
  3. 比较器可以很好的应用在根据特殊标准排序的结构上
 

3-3. 排序总结

  • 基于比较排序
  • 不基于比较排序与数据状况有关
 

3-3-1. 计数排序

 

不基于比较排序案例
不基于比较排序案例

 

 

3-3-2. 基数排序

  • 比如按照进制数据结构状况的数进行排序17变成017,100等进行排序保证数据位数同等级。

 

桶的排序时间复杂度是O(N)空间复杂度O(M)
桶的排序时间复杂度是O(N)空间复杂度O(M)

 

桶的排序需要基于样本数据满足桶的划分才能用桶排序。

 

桶的排序流程
桶的排序流程

 

  1. package leecode.zuochengyun.dayof7; 

  2.  

  3. /** 

  4.  * create-date:2022/5/27 

  5.  * author:guojia.ma 

  6.  * 不通过比较的排序1。计数排序2.基数排序:此处案例桶排序 

  7.  */ 

  8. public class Code02_RadixSort { 

  9. //    only for no-neagtive value 

  10.     public static void radixSort(int[] arr) { 

  11.         if(arr==null||arr.length<2){ 

  12.             return; 


  13.         radixSort(arr,0,arr.length-1,maxbits(arr)); 


  14. //arr[begin..end]排序 

  15.     private static void radixSort(int[] arr, int L, int R, int digit) { 

  16.         final int radix=10; 

  17.         int i=0,j=0; 

  18. //        有多少个数准备多少个辅助空间 

  19.         int[] bucket=new int[R-L+1]; 

  20.         for (int d = 0; d <=digit; d++) {//有多少位就每个数字进出桶多少次 

  21. //            10个空间 

  22. //            count[0] 当前位(d位)是0的数字有多少个 

  23. //            count[1] 当前位(d位)是(0和1)的数字有多少个 

  24. //            count[i] 当前位(d位)是(0~i)的数字有多少个 

  25.             int[] count=new int[radix];//count[0..9] 

  26.  

  27.             for ( i = 0; i < radix; i++) { 

  28.                 j=getDigit(arr[i],d); 

  29.                 count[j]++; 


  30.             for ( i = 0; i < radix; i++) {//累加和做词频 

  31.                 count[i]=count[i]+count[i-1]; 


  32.             for ( i = R; i >=L ; i--) {//数组从右往左遍历数字出桶 

  33.                 j=getDigit(arr[i],d ); 

  34.                 bucket[count[j]-1]=arr[i];//辅助数组 

  35.                 count[j]--; 


  36.             for (i = L,j =0; i<=R;i++,j++) { 

  37.                 arr[i]=bucket[j];//把bucket出桶的结果数怼回到原数组, 


  38.         }//循环其他位进行入桶出桶怼回原数组 


  39.  

  40.     private static int getDigit(int x, int d) { 

  41.         return ((x/((int)Math.pow(10,d-1)))%10); 


  42.  

  43.     private static int maxbits(int[] arr) { 

  44.         int max=Integer.MIN_VALUE; 

  45.         for (int i = 0; i < arr.length; i++) { 

  46.             max=Math.max(max,arr[i]); 


  47.         int res=0; 

  48.         while (max!=0){ 

  49.             res++; 

  50.             max/=10;//最大值有多少十进制位 


  51.         return res; 


  52.  


  53.  

标签:index,arr,int,复杂度,question,leecode,排序
来源: https://www.cnblogs.com/bchjazh/p/16339376.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有