提交 1ab76bf1 编写于 作者: qq_36480062's avatar qq_36480062

commit

上级 4b64edd6
package basic.queue;
public class 单调队列 {
public static void main(String[] args) {
}
}
package basic.sort;
import java.util.Arrays;
/**
* 源数组,假设有n个数
* |_______|_______| 划分成n/2
* |___|___|___|___| 划分成n/4
* |_|_|_|_|_|_|_|_| 划分成n/8
* 直到划分成1个数
* 递归层数最多有log n
* 所以时间复杂度是O(N log n)
* 空间复杂度是O(N)
* 需要辅助数组
* 开始l,r指向两个区间的区间首
* 区间首元素较小者放进辅助数组,维护双指针之一
* 重复如上操作
* 直到有一个区间没有数了,直接把另一个还有数的区间放在辅助数组的后面
* 最后把排好序(未完全排好)的数组放回源数组
*/
public class mergeSort {
public static void main(String[] args) {
mergeSort(0, t.length - 1);
System.out.println(Arrays.toString(t));
}
static int[] t = {2, 4, 1, 5, 7, 2};
static int[] q = new int[1000];
static void mergeSort(int l, int r) {
if (l >= r) return;//如果只有1个数或者没有数,就不需要排序
int mid = l + r >> 1;
mergeSort(l, mid);//合并左半部分
mergeSort(mid + 1, r);//合并右半部分
//有一个辅助数组
//k代表源数组取到什么位置
//把排序后(不完全有序)的数组放进辅助数组
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r) {
if (t[i] <= t[j]) {
q[k++] = t[i++];
} else {
q[k++] = t[j++];
}
}
//左半部分如果还有元素,有且只有一个还有元素
while (i <= mid) q[k++] = t[i++];
//右半部分如果还有元素,有且只有一个还有元素
while (j <= r) q[k++] = t[j++];
//放回原数组
for (i = l, j = 0; i <= r; i++, j++) {
t[i] = q[j];
}
}
}
......@@ -12,25 +12,25 @@ public class quickSort {
public static void main(String[] args) {
q[0] = 5;
q[1] = 4;
quick(0, 5);
quick(2, 5);
System.out.println(q[0]);
System.out.println(q[1]);
}
static int[] q = new int[1000005];
static int t = 0;
static int t;
static void quick(int l, int r) {
if (l == r) return;
int x = q[(l + r) / 2], i = l - 1, j = r + 1;
if (l >= r) return;
int x = q[r], i = l - 1, j = r + 1;
while (i < j) {
do {
i++;
} while (q[i] < x&&i<j);
} while (q[i] < x);
do {
j++;
} while (q[j] > x&&i<j);
} while (q[j] > x);
if (i < j) {
t = q[i];
q[i] = q[j];
......@@ -38,6 +38,6 @@ public class quickSort {
}
}
quick(l, j);
quick(j + 1, r);
quick(j+1, r);
}
}
package basic.stack;
import java.util.Scanner;
/**
* 给定一个长度为N的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出-1。
* 输入格式
* 第一行包含整数N,表示数列长度。
* 第二行包含N个整数,表示整数数列。
* 输出格式
* 共一行,包含N个整数,其中第i个数表示第i个数的左边第一个比它小的数,如果不存在则输出-1。
* 数据范围
* 1≤N≤105
* 1≤数列中元素≤109
* 输入样例:
* 5
* 3 4 2 7 5
* 输出样例:
* -1 3 -1 2 2
*/
public class 单调栈 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
int x = 0;
while (n-- != 0) {
x = sc.nextInt();
while (tt != 0 && stk[tt] >= x) tt--;
//tt==0代表找不到比它小的数
if (tt == 0) System.out.print(-1);
else System.out.println(stk[tt]);
stk[++tt] = x;
//stk[0]这个位置什么都不存,到了这个位置代表找不到!!!
}
}
static int[] stk = new int[100010];
static int n, tt = 0;
}
package basic.stack;
import java.util.Scanner;
import java.util.Stack;
/**
* https://www.acwing.com/blog/content/132/
* 第一题
* 题目描述
* 约翰有N头奶牛,编号为1到N。
* 现在这N头奶牛按编号从小到大的顺序站成了一排,
* 其中奶牛 i 的身高为Hi。
* 现在,每头奶牛都向它的右侧望向那些编号较大的奶牛,
* 对于奶牛 i 如果存在一头奶牛 j 满足 i<j
* 并且 Hi<Hj
* ,那么我们称奶牛 i 需要仰视奶牛 j。
* 请你求出每头奶牛的最近仰视对象。
* 输入格式
* 第一行包含整数N。
* 接下来N行,每行包含一个整数Hi
* ,其中第 i 行的数为编号为 i 的奶牛的高度。
* 输出格式
* 共 N 行,每行输出一个整数,其中第 i 行的输出整数表示编号为 i 的奶牛的最近仰视对象的编号,如果不存在仰视对象,则输出0。
* <p>
* 数据范围
* 1≤N≤105
* 1≤Hi≤106
* 输入样例:
* 6
* 3
* 2
* 6
* 1
* 1
* 2
* 输出样例:
* 3
* 3
* 0
* 6
* 6
* 0
* <p>
* 我们可以一步步读入奶牛,对于每一头奶牛而言,
* 判断这一头奶牛可以成为哪些奶牛的仰视对象.
* 于是,我们可以将当前奶牛,不断地和栈顶奶牛比较,如果说它身高大于栈顶奶牛,
* 那么栈顶奶牛的仰视对象一定是当前奶牛,然后将栈顶奶牛出栈,进行下一次比较,
* 直到栈为空或者栈顶奶牛身高高于它.最后再将我们当前奶牛的身高入栈.
* 之所以仰视对象是当前奶牛,因为它是离栈顶奶牛最近的奶牛,而且满足身高大于它.
* 可以略微证明一下,因为如果说栈顶奶牛的仰视对象不是当前这头奶牛,
* 那么在这头奶牛之前,栈顶奶牛肯定已经出栈了,因为必然在此之前,
* 会有奶牛成为栈顶奶牛的仰视对象,然而现在它还在栈中,那么栈顶奶牛的仰视对象,必然是当前这头奶牛.
*
* 这道题目,最有用的性质,就是离自己最近,而且比自己身高高.
* 1. 离自己最近:这个性质其实就是我们所谓的栈的必备性质.
* 2. 身高高:看到这种类型的词汇,一定要第一时间反应,这道题目是不是拥有单调性.
* 经过上面的讨论,我们大致可以确定,这道题目的确拥有单调性,那么想让我们的数据结构栈,就进化成为了单调栈.
*/
public class 奶牛单调栈 {
static class node {
public int x, y;
public node(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 1; i <= n; i++) {
a[i] = sc.nextInt();
}
/**
* 单调栈!
*/
for (int i = 1; i <= n; i++) {
while (st.size() != 0 && a[i] > st.peek().x) {
s[st.pop().y] = i;//i是索引,依照题意写
}
st.push(new node(a[i], i));
}
for (int i = 1; i <= n; i++) {
System.out.println(s[i]);
}
}
static int n;
static int[] s = new int[100005], a = new int[100005];
static Stack<node> st = new Stack<node>();
}
package basic.stack;
import java.util.Scanner;
/**
* https://www.cnblogs.com/gzh-red/p/11019265.html
* https://www.acwing.com/blog/content/132/
* 第二题
* 题目描述
* 某地有 N 个能量发射站排成一行,每个发射站 i 都有不相同的高度 Hi
* ,并能向两边(当然两端的只能向一边)同时发射能量值为 Vi
* 的能量,并且发出的能量只被两边最近的且比它高的发射站接收。
* 显然,每个发射站发来的能量有可能被 0 或 1 或 2 个其他发射站所接受,出于安全考虑,每个发射站接收到的能量总和是我们很关心的问题。
* 由于数据很多,现在只需要你帮忙计算出接收最多能量的发射站接收的能量是多少。
* 输入格式
* 第一行包含整数N。
* 接下来N行,每行包含两个整数Hi
* 和Vi
* ,其中第 i 行的数据为第 i 个发射站的高度和能量值。
* 输出格式
* 输出仅一行,表示接收最多能量的发射站接收到的能量值。
* 数据保证答案不超过231−1
* 数据范围
* 1≤N≤106
* ,
* 1≤Hi≤2∗109,
* 1≤Vi≤10000
* <p>
* 输入样例:
* <p>
* Copy
* 3
* 4 2
* 3 5
* 6 10
* <p>
* 输出样例:
* <p>
* Copy
* 7
* 数据结构
* 既然现在我们已经想到了数据结构来优化算法,那么现在当前最大的问题.无非就是如何利用这个我们学过数据结构来优化这道题目.
* 我们发现这道题目,所有的数字都满足一个非常重要的性质,那就是发出的能量只被两边最近的且比它高的发射站,我们从中间,不但会发现这道题目的条件,还会发现这道题目出题人,偷偷告诉我们的性质.那就是两边最近且比他高.
* 性质分析
* 两边最近: 显然,是一个条件&性质,而且这里面最为重要的性质核心,就是最近这个两个字.
* 看到这里,我们就得让神经系统中的神经元,条件反射地想到,是不是需要后进后出的数据结构栈
* 比他高: 这就是这道题目的第二大精髓思想,单调性,我们通过这道题目的这句话,可以敏锐地察觉到,这道题目需要使用具有单调性质的单调栈.
* 算法步骤
* 这道题目既然是需要使用具有非常秀的单调栈,那么我们到底如何使用呢?
* 那么此时我们就需要根据条件,来确定单调栈,插入栈顶的条件.
* 因为对于一个发射站而言,它可以接收到的能量,就是一组单调递减的高度序列的能量.这里我们需要画图解决问题.
* 综上所述,我们可以开一个单调递减的栈,统计所有高度单调递减的发射站.
* 1. 如果当前这个数字破坏了单调递减,那么它会挡掉比它矮的所有发射站.
* 然后将所有比它能量小的发射站,统统吸取.然后将这些发射站出栈,自己入栈.
* 2. 如果当前发射站,满足单调递减的话,那么栈顶所属的发射站,吸取它的能量.同样自己也需要入栈
*/
public class 能量发射单调栈 {
static class node {
public int x = 0, y = 0;
public node(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 1; i <= n; i++) {
a[i] = sc.nextInt();
b[i] = sc.nextInt();
}
st[++top] = new node(a[1], 1);
for (int i = 2; i <= n; i++) {
while (top != 0 && a[i] > st[top].x) {//0位置没有元素
// 这样写不会空指针
s[i] += b[st[top--].y];
}
if (top != 0)
s[st[top].y] += b[i];
st[++top] = new node(a[i], i);
}
int res = 0;
for (int i = 1; i <= n; i++) {
res = Math.max(res, s[i]);
}
System.out.println(res);
}
private static int[] s = new int[100005];//结果
static node[] st = new node[100000];//看做栈
static int top = 0;//看做栈指针
static int[] a = new int[100005], b = new int[100005];
}
package basic.two;
import java.util.TreeSet;
public class 二分模板 {
public static void main(String[] args) {
TreeSet<Integer> a = new TreeSet<Integer>();
a.add(5);
a.add(4);
a.add(6);
System.out.println(a);
}
static int bsearch(int l, int r) {
......
......@@ -69,19 +69,6 @@ public class LIS {
dp[t] = w;
if (t == len) len++;
}
for (int i = 0; i < nums.length; i++) {
dp[i] = 0;
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
len = Math.max(dp[i], len);
}
return len;
}
}
package 线性dp.LIS模型;
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
import static java.lang.System.in;
public class LIS题解 {
public static void main(String[] args) throws IOException {
n = nextInt();
for (int i = 0; i < n; i++) {
arr[i] = nextInt();
}
System.out.println(lis());
}
static int n;
static int[] arr = new int[100005];
static int[] dp = new int[100005];
static int lis() {
int i = 0, len = 0;
for (int j = 0; j < n; j++) {
i = Arrays.binarySearch(dp, 0, len, arr[j]);
if (i < 0) i = -(i + 1);
dp[i] = arr[j];
if (i == len) len++;
}
return len;
}
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static BufferedReader reader = new BufferedReader(new InputStreamReader(in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException {// 读取下一行字符串
return reader.readLine();
}
static String next() throws IOException {// 读取下一个字符串
while (!tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException {// 读取下一个int型数值
return Integer.parseInt(next());
}
static double nextDouble() throws IOException {// 读取下一个double型数值
return Double.parseDouble(next());
}
}
......@@ -16,14 +16,14 @@ public class Sort {
// count++;
// System.out.println(count);
for (int j = 0; j < 100; j++) {
for (int i = 1; i < 20; i++) {
int[] data = random(20, 200);
countSort(data);
if (data[i] < data[i - 1])
System.out.println("错误");
} }
//
// for (int j = 0; j < 100; j++) {
// for (int i = 1; i < 20; i++) {
// int[] data = random(20, 200);
// countSort(data);
// if (data[i] < data[i - 1])
// System.out.println("错误");
// } }
}
public static int[] random(int size, int f) {
......
......@@ -10,7 +10,7 @@ public class 排序例题 {
// System.out.println(Arrays.toString(data));
// System.out.println(shu(data));
int[] c = {1, 2, 5};
System.out.println(zuiii(c,0,c.length-1));
System.out.println(zuiii(c, 0, c.length - 1));
}
......@@ -258,4 +258,11 @@ public class 排序例题 {
}
/**
* 逆序对
*/
public static void ni() {
}
}
\ No newline at end of file
......@@ -27,6 +27,7 @@ x的负数表示~x+1也可以直接-x
~x+1+x=0
用加法实现减法,所以使用补码来表示负数
````
###位运算的技巧
```
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册