1.点击右上角的 File ,打开 Settings
2.选择 Version Control --> Commit ,取消 Before Commit 下的两个选项(如下图)
3.点击 Settings页面右下角 Apply 应用,然后点击 OK 即可
Mybatis标签collection一对多的使用 一、colleciton 标签二、collection使用方法1. 方法一: 嵌套结果映射2. 方法二: 嵌套select 查询 三、 association 一对一 一、colleciton 标签 Mybatis的 collection 是一对多的使用的, 在 resultMap 标签内使用
当一个Bean中有 一个list属性需要关联查询出来的使用就用collection 标签
如下
查询用户结果 需要关联出 角色集合
用户
@Data public class User { private Integer id; private String name; private List<Role> roles; } 角色
@Data public class Role { private Integer id; private Integer userId; private String name; private String type; } sql
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL COMMENT '名称', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4; CREATE TABLE `role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL COMMENT '用户id', `name` varchar(255) DEFAULT NULL COMMENT '角色名称', `type` varchar(255) DEFAULT NULL COMMENT '角色类型', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4; 二、collection使用方法 1.
1、使用 su 切换至root账户 打开Linux虚拟机,
可以看到刚开始是普通用户user登录,当你像切换回root用户,你可以敲 su 然后回车,要求输入密码、输入密码后回车就进入了root用户.
root用户切换到普通用户,输入exit,然后回车
2、开启 虚拟机的root账户 默认情况是没有开启root账户的,root账户是禁用状态
1、首先执行:sudo passwd root 命令初始化root用户密码
2、修改 sshd_config 文件 开启root访问权限
执行编辑命令:
sudo vim /etc/ssh/sshd_config 3、在 sshd_config 文件里的 Authentication 部分去掉注释:
4、编辑完毕后,重启ssh服务,执行如下命令:
sudo systemctl restart sshd 5、最后尝试以root用户登陆,显示登陆成功,并且用户为root账户。
(1)RNN循环神经网络处理带有序列的数据:例如自然语言、股市金融数据等
(2)RNN结构:x1和h0运算后的结果h1再送入下一个RNN Cell中,下图所示的RNN Cell都是相同的。
(3)RNN Cell中的运算如下图所示,Whh的维度为hidden_size x hidden_size,Wih的维度为hidden_size x input_size,由此可以得出一个RNN Cell需要的参数为input_size和hidden_size
(4)构建RNN Cell:假设batchSize=1,seqLen=3表示输入的序列有3个,inputSize为输入维度,hiddenSize为隐层维度
根据以上假设,构建RNN的代码如下:
import torch batch_size = 1 seq_len = 3 input_size = 4 hidden_size = 2 cell = torch.nn.RNNCell(input_size=input_size, hidden_size=hidden_size) # (seq, batch, features) dataset = torch.randn(seq_len, batch_size, input_size) hidden = torch.zeros(batch_size, hidden_size) for idx, input in enumerate(dataset): print('=' * 20, idx, '=' * 20) print('Input size: ', input.shape) hidden = cell(input, hidden) print('outputs size: ', hidden.shape) print(hidden) Input size为[1,4],hidden size为[1,2],输出结果:
git.exe push --progress "origin" master:master
Enumerating objects: 113, done.
Counting objects: 100% (113/113), done.
Delta compression using up to 12 threads
Compressing objects: 100% (57/57), done.
Writing objects: 100% (62/62), 17.99 MiB | 3.83 MiB/s, done.
Total 62 (delta 45), reused 0 (delta 0), pack-reused 0
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: is denied, because it will make the index and work tree inconsistent
一. 读卡规则 当服务器有多个GPU时,设置CUDA_VISIBLE_DEVICES 环境变量可以改变CUDA程序所能使用的GPU设备。在默认情况下,标号为0的显卡为主卡,如主机中有4块显卡,那么每张显卡的默认标号为[0,1,2,3]。多卡设置规则如下:
Environment Variable SyntaxResultsCUDA_VISIBLE_DEVICES=1Only device 1 will be seenCUDA_VISIBLE_DEVICES=0,1Devices 0 and 1 will be visibleCUDA_VISIBLE_DEVICES="0,1"Same as above, quotation marks are optionaCUDA_VISIBLE_DEVICES=0,2,3lDevices 0, 2, 3 will be visible;device 1 is masked CUDA应用运行时,CUDA将遍历当前可见的设备,并从零开始为可见设备编号。第一种情况,卡1设置为主卡,但CUDA遍历时会设置为可见编号0。最后一种情况,设备0,2,3将显示为设备0,1,2。如果将字符串的顺序更改为“2,3,0”,则设备2,3,0将分别被设置为0,1,2。如果为CUDA_VISIBLE_DEVICES 设置了不存在的设备,所有实际设备将被隐藏,CUDA 应用将无法使用GPU设备;如果设备序列是存在和不存在设备的混合,那么不存在设备前的所有存在设备将被重新编号,不存在设备之后的所有设备将被屏蔽。当前可见的(重新编号后的)设备可使用CUDA 程序来查看。
举例:
import torch print(torch.cuda.current_device()) 运行:
结果:
虽然指定使用设备为卡1,但CUDA会编号为0,因此显示的编号还是0
二. 设置GPU 1. 临时设置 1.1. 直接设置
export CUDA_VISIBLE_DEVICES=1 1.2. 运行bash脚本时指定GPU
CUDA_VISIBLE_DEVICES=gpu_ids sh test.sh 1.3. 在代码中指定GPU
import os os.environ['CUDA_VISIBLE_DEVICES'] = gpu_ids 1.4. 运行程序时指定GPU
CUDA_VISIBLE_DEVICES=gpu_ids python test.py 注意:这种设置方法一定要在第一次使用 cuda 之前进行设置
目录
顺序表
链表
二叉树
图(V是顶点个数,E是边的条数)
1.存储空间:
2.BFS和DFS的时间复杂度
3.最小生成树时间复杂度
4.最短路径时间复杂度
查找的平均查找长度(ASL)
排序
顺序表 算法操作时间复杂度空间复杂度描述插入O(n)\需要移动元素,移动结点的平均次数n/2删除O(n)\需要移动元素,移动结点的平均次数(n-1)/2按值查找O(n)\指针移动查找对应元素 链表 算法操作时间复杂度空间复杂度描述头插法创建O(n)\ 插入时间为O(1),总时间复杂度为O(n)
尾插法创建O(n)\ 插入时间为O(1),总时间复杂度为O(n)按值查找O(n)\指针移动查找对应元素 按序查找 O(n)\指针移动到对应位置插入O(1)\需要从头查找则花费主要用于查找O(n)删除O(1)\需要从头查找则花费主要用于查找O(n) 二叉树 算法操作时间复杂度空间复杂度描述二叉树创建O(n)O(n) 类似先序遍历
二叉树遍历O(n)O(n) 递归遍历操作二叉排序树插入O(n)\\ 二叉排序树删除 O(n)\\ 图(V是顶点个数,E是边的条数) 1.存储空间: 存储结构存储空间邻接矩阵 O(n^2)
邻接表 无向图O(|V|+2|E|),有向图O(|V|+|E|)
2.BFS和DFS的时间复杂度 广度优先遍历BFS深度优先遍历DFS邻接矩阵存储O(|V|^2)O(|V|^2)邻接表存储O(|V|+|E|) O(|V|+|E|)
3.最小生成树时间复杂度 普里姆算法克鲁斯卡尔算法时间复杂度O(|V|^2)O(|E|log|E|) 注:普利姆算法不依赖E,适合求解边稠密图的最小生成树;克鲁斯卡尔适合边稀疏而顶点较多的图
4.最短路径时间复杂度 迪杰斯特拉算法弗洛伊德算法时间复杂度O(|V|^2)O(|V|^3) 5.拓扑排序:由于输出每个顶点的同时还要删除以它为起点的边,故拓扑排序的时间复杂度为O(|V|+|E|)
查找的平均查找长度(ASL) 1.顺序查找
注:若题目未明确提出是成功还是不成功的ASL,则平均查找长度是成功和不成功的平均值:
ASL平均 =(ASL成功+ASL不成功)/2
2.有序的顺序查找
3.折半查找 4.分块查找 排序
题目来源:https://leetcode.cn/problems/next-greater-element-iii/
大致题意:
给一个32位的整数,返回将整数各位数字重新排列后能组成大于原整数的最小值,如果不存在这样的最小值,则返回 -1
思路 假设整数中有高位数为 i ,低位数为 j,如果 i < j,那么交换 i 和 j 就一定得到大于原整数的值
如果遍历整数每一位的值,很容易找到满足低位数值大于高位数值的情况,难点在于交换后的值是不是大于原整数的最小值
已知交换大于高位数值的低位数值后,一定会使整数值更大,那么交换的位数越低,增加的数值也就越小。比如千位和百位的值都小于个位数的值,将个位数与百位数交换得到的值一定小于将个位数与千位数交换的值 (3486,交换个位与百位得到 3684,交换个位与千位得到 6483)
于是可以从低位遍历到高位,当遍历到首个高位数小于低位数时进行交换。那么应该注意到,如上述例子 3486,在遍历到百位时,百位小于十位,如果将这两位交换的值为 3846,要小于百位与个位交换。所以实际交换时,应该使用大于当前高位值的最小数与其交换。同时,由于在遍历到该高位之前,遇到的数都是递增的(否则在遍历到该位之前就会出现高位小于低位的情况),所以可以直接从末尾遍历求得第一个大于该位的值即为最小的大于该位的值
但是此时交换后的值仍可能不是所有数位全排列后的大于原值的最小值,比如 2302431,按照上述规则找到并交换后的值为 2303421,但是最小值应该是 2303412。
可见,在上述例子中,变化的是与高位交换位置到最低位的数字,首先可以知道在高位的值更大以后,低位的值哪怕都为 0 也比之前的大,所以应该尽量降低低位的值,那么在遍历时与高位交换的位置到最低位都满足递增关系,于是可以直接将这一段数字反转得到最小值
所以解题思路可以概括为
遍历数字,存下每一位的值从低位向高位遍历,如果遍历到当前位的值小于上一位,那么从低位开始遍历找到第一个大于当前位的值,然后将两个值交换,并退出循环;否则继续遍历,直至数字遍历结束判断数字遍历指针是否结束,若结束表明未交换,直接返回 -1反转交换位置到最低位的数字获取交换后的数字判断交换后数字与原数字的大小关系,如果交换后数字小于原数字(表示出现了越界)则返回 -1,否则返回交换后数字 class Solution { public int nextGreaterElement(int n) { // 存原数字 int pre = n; StringBuffer sb = new StringBuffer(); // 获取每一位的值 while (n > 0) { sb.append(n % 10); n /= 10; } char[] nums = sb.
在注册页面中需要对用户名和两次输入的密码进行验证,其中用户名是唯一的,不能重复,而两次输入的密码必须相同。并且要求用户名的格式是:字母开头,后跟字母或数字,长度至少6位,密码由数字组成,长度在6到10位之间。 main.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html> <head> <title>表单验证</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <script type="text/javascript"> var httpRequest=null; // 创建XHR对象 function createXHR(){ if(window.XMLHttpRequest){ //Mozilla,Safari,Opera,IE7等 httpRequest = new XMLHttpRequest(); // console.log("XMLHttpRequest!"); //打印调试信息 } else if(window.ActiveXObject){ try{ httpRequest = new ActiveXObject("Msxml2.XMLHTTP"); //IE较新版本 // console.log("Msxml2.XMLHTTP!"); } catch(e){ try { httpRequest = new ActiveXObject("Microsoft.XMLHTTP");//IE较老版本 // console.log("Microsoft.XMLHTTP!"); } catch(e){ httpRequest = null; } } } if(!httpRequest){ alert("fail to create httpRequest"); } } // 发送请求 function sendRequest(url, params, method, handler){ createXHR(); if(!
文章目录 前言一、基本思路二、编码实现三、使用测试界面如图所示功能测试 前言 写这个小工具的原因是因为在工作中需要将两个excel里面的数据合并一个新的文件,起初尝试通过WPS进行合并,但是奈何WPS需要收费,所以就自己动手写一个,说干就干,于是乎就有了这个用python写的小工具
一、基本思路 通过excel文件的路径,读取每个文件当前活跃表格的标题,创建一个新的文件 “合并内容.xlsx” 文件,将要合并的两个文件的标题写入到新创建的文件中,当然重复的标题也会自动过滤的,然后将第一个文件的列标题和新创建的文件的列标题进行对比,如果存在新创建的文件中,然后通过迭代,将整列数据都写入到新创建的文件中,然后通过计算出新创建的文件的行数,在进行第二个文件的写入,步骤同第一个文件的写入一样
采用python的tkiner框架编写,界面简单,操作方便,可以将具有不同列名的两个excel表格文件 合并到一个新的excel文件中
二、编码实现 具体的代码实现如下,代码格式上,大家可以自己调整,也可以在原有的基础上进行添加新的功能:
from openpyxl import load_workbook from openpyxl import Workbook from tkinter import * from tkinter import filedialog import tkinter.messagebox #获取文件1的路径 def upload_file1(file1_entry): select_file1 = tkinter.filedialog.askopenfilename() file1_entry.insert(0,select_file1) #获取文件2的路径 def upload_file2(file2_entry): select_file2 = tkinter.filedialog.askopenfilename() file2_entry.insert(0,select_file2) def merge_file(result_text,file1_path,file2_path): result_text.insert('end',"开始合并\n") try: # 读取excel文件 excel_file1 = load_workbook(filename=file1_path) excel_file2 = load_workbook(filename=file2_path) write_excel_file = Workbook() sheet1 = excel_file1.active sheet2 = excel_file2.active ac_write_excel_obj = write_excel_file.active result_text.insert('end', "
下载地址
CSS3按钮动画特效代码。在该特效中,提供了8种按钮动画特效。每种特效在鼠标悬停到按钮上面的时候,都会触发按钮动画。
dd:
1. 什么叫生命周期 每个 Vue 实例(如Vue组件)从创建到销毁的整个过程称作 生命周期。
2. 什么是生命周期函数(钩子) 2.1 钩子函数概念 生命周期函数是Vue实例在生命周期中的特定时间点会自动执行的函数。
Vue实例在被创建时要经过一系列的初始化过程(需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等)。这个过程中会运行一些叫做生命周期的函数(钩子),以供用户在不同阶段添加自己的代码。
2.2 每个阶段对应的钩子函数 钩子函数按照组件生命周期的过程分为,创建阶段=>挂载阶段=>更新阶段=>销毁阶段。
创建阶段:beforeCreate()、created()挂载阶段:beforeMount()、mounted()更新阶段:beforeUpdate()、updated()销毁阶段:beforeDestroy()、destroyed() 2.3 父子组件钩子函数在三个阶段的代码执行顺序 挂载:父亲created> 子created > 子mounted> 父亲mounted>更新:父亲beforeUpdate > 子beforeUpdated > 子updated > 父亲updated销毁:父亲beforeDestroy> 子beforeDestroy > 子destroyed> 父destroyed 3. Vue实例的核心工作 将模板内容编译,替换掉原有的html节点
编译模板(将模板字符串-> 生成render()函数,返回对象虚拟DOM(VNode))挂载(使用虚拟DOM对象生成真实DOM对象,替换指定的DOM节点) 模板的确定:render函数 > template > 容器指定的模板挂载点:el 的值,或手动挂载 vm.$mount('#app') 4. 生命周期的四个阶段 4.1 创建 beforeCreate() 特点:Vue创建前,this指向创建的实例,el和data还未初始化,date和methods的数据不能访问。数据观察、数据监听事件机制都未形成(不能获得DOM节点)。
create() 特点:Vue创建后,data、methods初始化完成,是最早可以调用data和method的时段,一般在此对数据进行初始化。此阶段亦不能获得DOM节点。
用途:常用于简单的ajax请求、页面的初始化
在beforeCreate和created间,完成$data的代理
4.2 挂载 beforeMount():页面还是旧的 特点:挂载开始前被调用。beforeMount之前,会找到对应的template,并编译成render函数。模板已经在内存中编译好了,但是未挂载到页面中
注:这个阶段是过渡性的,一般一个项目只能用到一两次。
Mounted():页面是新的 特点:Vue载入后,(完成创建vm.$el,和双向绑定); 只要执行完mounted,整个Vue实例就已经初始化完成,此时组件已经脱离创建阶段, 进入到了运行阶段。
用途:实例挂载到DOM上,此时可以通过DOM API获取到新的DOM节点,$ref属性可以访问常用于获取VNode信息和操作,ajax请求
本期简绍MyBatis相关内容~
目录
1.mybatis相关介绍
1.1什么是mybatis
1.2为什么要学mybatis
2.mybatis实战操作
2.1项目创建
2.1.1准备数据表
2.1.2创建一个mybatis项目
2.2使用mybatis进行增删查改操作
2.2.1查询操作
2.2.2使用springboot进行单元测试介绍
2.2.3修改操作
2.2.4删除操作
2.2.5增添操作
1.mybatis相关介绍 1.1什么是mybatis MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
1.2为什么要学mybatis 因为对于后端开发来说,程序主要是由后端程序和数据库两部分来组成的。而这两个部分要进行通讯,就需要有连接数据库的工具,前面我们已经学过了JDBC,但正是因为JDBC相对于MyBatis太过繁琐,所以我们就要开始学习MyBatis。
2.mybatis实战操作 2.1项目创建 2.1.1准备数据表 ①创建一个如下的数据库和数据表:
-- 创建数据库 drop database if exists mycnblog; create database mycnblog DEFAULT CHARACTER SET utf8mb4; -- 使用数据数据 use mycnblog; -- 创建表[用户表] drop table if exists userinfo; create table userinfo( id int primary key auto_increment, username varchar(100) not null, password varchar(32) not null, photo varchar(500) default 'default.
Android中常用的布局方式有以下几种: 线性布局LinearLayout
相对布局RelativeLayout
表格布局TableLayout
层布局FrameLayout
绝对布局AbsoluteLayout
网格布局GridLayout
用的相对较多的是线性布局和相对布局。接下来重点演示这两种布局
其中,表格布局是线性布局的子类。网格布局是android 4.0后新增的布局。
(一)线性布局LinearLayout 线性布局中最重要的属性:orientation
horizontal(水平布局)和vertical(垂直布局)两种方式
属性名
orientation 布局方式,有horizontal(水平布局)和vertical(垂直布局)两种方式
id 组件名称
layout_width 该组件的宽度
layout_height 该组件的高度
layout_weight 权重
layout_gravity 该组件(在父容器)中的对齐方式
gravity 该组件所含子组件在其内部的对齐方式
background 设置背景图片或填充颜色
效果图 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="@color/gray" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_marginTop="20dp" android:layout_width="match_parent" android:orientation="horizontal" android:layout_height="wrap_content"> <TextView android:text="权重1" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"/> <TextView android:text="权重2" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"/> <TextView android:text="权重3" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"/> <TextView android:text="权重4" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"/> <TextView android:text="权重5" android:layout_width="0dp" android:layout_weight="1" android:layout_height="
参考博客:C语言条件判断语句:if、else if、else_南雨兮-CSDN博客_else
引言:给大家推荐一个超好用的软件,此软件也是优秀博主开发,主要是针对在我们开发过程中会不断的收集资料,而经过时间的洗礼,这些资料慢慢变得庞大起来。但是就出现了个问题:你2年前收集的资料,你在某天打开发现只有一个文件名,根本不知道具体里面干了什么,如果你有耐心,一个个打开重新编译,很好!你是牛人,但是这样做就是既繁琐、又无助,那么问题来了,有什么好办法,解决这个问题呢?
以下这个博客帮你解决了这个问题:
Qt版本企业级界面_清风徐来Groot的博客-CSDN博客
可能大家都习惯于收集资料,但是大家却忘了更主要的是如何去复习,就像我们上学时期,可能
会去写笔记,但是时间一长,压根也不记得自己记了什么东西,所以需要一个移动的笔记本,图形化的效果图来帮助大家记住:里面有个试用版本,可以下下来试试看,体验下!!!
精灵球Plus介绍_清风徐来Groot的博客-CSDN博客
欢迎大家来咨询:
qq:2868466750@qq.com 清风徐来Groot
2848043454@qq.com 一、用法简介:
if语句用法:
if (表达式) { 执行语句 } else if 语句的用法:
if (表达式) { 执行语句 } else if (表达式) { 执行语句 } else if (表达式) { 执行语句 } else 语句的用法:
if (表达式) { 执行语句 } else if (表达式) { 执行语句 } else { 执行语句 } if与else if的区别:就是if可以只要满足条件就执行,但是else if会发现即使第一个执行了,第二个满足条件依然不会执行。就像是一个互斥的现象。
#include <iostream> #include <string> #include <stdio.h> using namespace std; //以下就是通过if语句来看出不同 int main() { int i = 1; if (i == 1) { i++; cout << "
IDEA中导入Maven工程或项目 本文简单讲述了IDEA中导入Maven工程或项目。为了减轻读者压力笔者将 IDEA 相关应用技巧分解成了多篇文章置于主页 IDEA 专栏,若本文没有帮助到您,请去主页 IDEA 专栏检索吧 😏。
文章目录 IDEA中导入Maven工程或项目一、IDEA中导入Maven工程(Module)二、IDEA中导入Maven项目(Project) 一、IDEA中导入Maven工程(Module) ⓵ 新建一个空的项目project作为工作空间
⓶ 在项目结构中导入工程(Model)
⓷ 选择要导入的工程(Model)
⓸ 选择导入方式
⓹ 设置导入的Model所使用的JDK
⓺ 导入后视图
二、IDEA中导入Maven项目(Project) ⓵ 已经有项目打开的情况下导入
⓶ 选择要导入的项目(Project)
⓷ 选择导入方式
⓸ 选择打开项目方式
⓹ 设置项目所使用的的JDK
说明:项目导入之后,源码还是存放在原来的项目中,只是在当前项目中打开(引用)一下工程而已。
目录
一、为什么使用自定义tabBar
二、使用步骤
1.修改pages.json文件
1.封装组件
2.tabBar页面引入组件
3.给子组件传值
4.登录页判断
5.隐藏原生tabBar
一、为什么使用自定义tabBar 目前的业务需求是根据不同的角色展示不同的底部tabBar
二、使用步骤 1.修改pages.json文件 开启自定义组件"custom": true,把list里面只留下页面路径
1.封装组件 <template> <view class="tab-bar"> <view class="content"> <view class="one-tab" v-for="(item, index) in tabBarList" :key="index" @click="selectTabBar(item.pagePath)"> <view> <view class="tab-img"> <image v-if="routePath === item.pagePath" class="img" :src="item.selectedIconPath"></image> <image v-else class="img" :src="item.iconPath"></image> </view> </view> <view v-if="routePath === item.pagePath" class="tit selectTexts">{{ item.text }}</view> <view v-else class="tit texts">{{ item.text }}</view> </view> </view> </view> </template> <script> export default { props: { // 底部导航栏数据 tabBarList: { type: Array, required: true }, // 当前页面路径 routePath: { type: String, required: true } }, data() { return {}; }, methods: { selectTabBar(path) { this.
题目来源:https://leetcode.cn/problems/kth-largest-element-in-an-array/
大致题意:
找出未排序数组中第 k 大的元素
思路 如果要找出数组中第 k 大的元素,最简单的方法就是直接排序,然后按照索引取出第 k 大的元素即可
不过题目并未要求将数组排序,直接排序会有冗余操作
较优的方法由根据堆排序的思想,每轮选出当前堆最大元素,时间复杂度为 O(log n),经过 k 次后选出的最大元素即为第 k 大元素,这样时间复杂度为 O(k * log n)
上述方法也有缺陷,因为其相当于将最大的 k 个元素全部排序了
快排的分界方法,方法每执行一次就会确定一个元素在排序后数组中的位置
于是可以使用快排的分界方法来求第 k 大的元素,每次分界方法执行后确定的位置与 k 的关系有:
当前位置等于 k,那么当前位置对应元素即为第 k 大元素当前位置小于 k,那么第 k 大元素应该在当前位置右侧,接下只用在右侧元素中找即可当前位置大于 k,那么第 k 大元素应该在当前位置左侧,接下只用在左侧元素中找即可 具体实现时,可以通过两个标志位 start 和 end 表示待寻找元素所在范围,初始时为 0 和 n - 1,接下来根据分界方法的分界位置与 k 的关系更新两个标志位
代码:
public class FindKthLargest { public int findKthLargest(int[] nums, int k) { int n = nums.
文章目录 一、指纹识别特定关键字识别Powered by CMS*** 识别CMSmeta标签识别 特定文件及路径识别响应头信息识别指纹识别工具WhatWeb工具Wappalyzer指纹识别 二、敏感路径探测三、互联网信息收集历史漏洞信息收集SVN GIT 文件SVN代码泄露GIT代码泄露 网盘信息收集 一、指纹识别 了解指纹识别之前,我们首先来了解一下网站可能用到的应用程序都有哪些,中间件,CMS,web框架等,指纹识别就是对网站的这些相关信息进行收集,因为很多开发者为了提高开发效率,都会使用不同的CMS系统,web框架,中间件等技术,但是这些CMS系统,Web框架,中间件也会存在不同的漏洞,而且这些框架,中间件,CMS系统都能在网上找到源码,当开发者或者企业偷懒,没有大改框架, 或者大概CMS,会泄露很多信息,通过这些框架和CMS系统源代码,找到网站的突破口
特定关键字识别 CMS的首页文件,特定文件可能会包含了CMS类型及版本信息,访问这些文件,会返回不同的信息,扫描工具根据不同的返回信息与自己的数据库进行正则匹配,来判别不同的CMS类型
Powered by CMS*** 识别CMS 我们通过访问网站,根据网站返回的信息中的Powered by ***CMS,可以识别网站使用的CMS类型
meta标签识别 很多CMS会留下痕迹在网站的meta 的 content字段,我们通过访问网站,根据网站返回的代码中,查看meta标签的content字段的值,可以判别CMS类型
特定文件及路径识别 不同的CMS网站,有不同的CMS网站结构及文件,可以通过不同CMS特定的文件及路径来识别CMS,如WordPress 特定文件路径:/wp-admin, /wp-includes等,Dede CMS网站的robots.txt文件可能包含了CMS特定的文件路径,扫描工具根据自己的特征数据库,与响应的信息进行正则匹配,来判别CMS的类型
另外,也可以利用不同CMS的静态文件,这些特定文件的MD5值作为指纹信息来判断CMS的类型
响应头信息识别 应用程序会在响应头的Server、X-Powered-By、Set-Cookie等字段返回Banner信息或者自定义的数据字段,通过响应头返回的信息,可以对应用进行识别,如有的Waf设备也可以通过响应头信息进行判别,这些信息不一定准确,因为可以自定义数据字段
指纹识别工具 为了提高效率,也可以通过指纹识别工具,来进行指纹探测,常用的指纹识别工具有WhatWeb,Wappalyzer,御剑等
WhatWeb工具 WhatWeb工具是开源的,使用Ruby编写,不仅可以识别包括内容管理系统CMS,博客平台,中间件,Javascript,Web服务框架,网站服务器,嵌入式设备等的web技术,也可以识别版本号,电子邮件地址,账户ID,脚本,SQL等
Wappalyzer指纹识别 Wappalyzer是一个浏览器插件,可以探测网站的指纹信息,能识别不同的Web技术,CMS,web框架等,使用JavaScript编写,支持火狐,谷歌等浏览器,大家可以去火狐或者google插件管理中进行添加,我们只要访问网站,Wappalyzer就可以自动识别网站的指纹信息,通过点击插件,就可以查看,非常方便
二、敏感路径探测 很多网站都会因为错误配置,而导致有的敏感路径没有设置防护,这样我们可以通过访问网站的敏感路径,获取更多关于网站的敏感信息,有利于我们进一步进行渗透测试,常见的敏感路径如:robots.txt文件,备份文件(.bak)文件,后台登录页面,phpinfo文件,upload file页面等等,通过这些敏感路径,有时候可以使我们达到事半功倍的效果
常用的敏感路径探测工具有BurpSuit,御剑,wwwscan等
有的网站会对网站的请求头信息进行判断,我们可以使用BurpSuit工具,自定义HTTP的请求 头,然后通过instruder模块,加上字典文件,来进行目录探测
三、互联网信息收集 现在的互联网信息庞大,我们可以通过互联网对信息进行收集,包括网站的历史漏洞信息,.svn .git 文件泄露,网盘信息等信息进行收集
历史漏洞信息收集 很多网站的版本迭代更新,都会对旧版本的网站进行修复,修复某些功能模块等等,我们可以通过第三方网站查看网站的旧版本的历史漏洞,包括漏洞的详细利用方式,但是有的网站在更新的时候,并没有对旧的版本的网站漏洞进行修复,哪么一份很详细的攻击过程都可以在互联网上找到
SVN GIT 文件 SVN 和 GIT 工具都是对网站版本进行管理的工具,通过SVN和GIT工具可以使开发者共同协作工作,提升开发效率,但是在使用这两个工具对网站进行开发的时候,都会在项目的目录下面生成一个.svn 或者.git隐藏文件,这两个隐藏的文件包含了网站的源代码,如果开发者没有删除这两个隐藏文件,就可以通过下载这两个隐藏文件,对目标网站的源代码进行审计,查找漏洞,包括数据库的配置文件,或者管理员的用户名和密码,
SVN代码泄露 如果目标网站没有删除站点目录下的.svn文件,就可以直接访问目标网站的.svn路径,查看网站的目录结构以及文件内容
工具推荐使用SvnExploit,下载地址
https://github.com/admintony/svnExploit
python SvnExploit.py -u 目标网站 --dump 下载之后的文件都会保存在当前的dbs目录底下
LeetCode 6227. 下一个更大元素 IV
名次树
class Solution { public: vector<int> secondGreaterElement(vector<int>& nums) { int n = nums.size(); vector<int> p(n); iota(p.begin(), p.end(), 0); sort(p.begin(), p.end(), [&](int a, int b){ return nums[a] > nums[b]; }); set<int> S; S.insert(n + 1), S.insert(n + 2); vector<int> res(n, -1); for(int i = 0; i < n; i ++) { int j = i + 1; while(j < n && nums[p[i]] == nums[p[j]]) j ++; for(int k = i; k < j; k ++) { auto it = S.