Skip to content

Commit 49a3e8d

Browse files
committed
feat: add basic knowledge
1 parent 90c2646 commit 49a3e8d

File tree

7 files changed

+227
-0
lines changed

7 files changed

+227
-0
lines changed

basic/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# 算法
2+
3+
## 常见的排序算法
4+
5+
- 冒泡排序
6+
- 插入排序

basic/sort/BubbleSort.java

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
public class BubbleSort {
2+
private static void swap(int[] nums, int i, int j) {
3+
int t = nums[i];
4+
nums[i] = nums[j];
5+
nums[j] = t;
6+
}
7+
8+
public static void main(String[] args) {
9+
int[] nums = {1, 2, 7, 9, 5, 8};
10+
boolean hasChange = true;
11+
for (int i = 0; i < nums.length - 1 && hasChange; ++i) {
12+
hasChange = false;
13+
for (int j = 0; j < nums.length - 1 - i; ++j) {
14+
if (nums[j] > nums[j + 1]) {
15+
swap(nums, j, j + 1);
16+
hasChange = true;
17+
}
18+
}
19+
}
20+
}
21+
}

basic/sort/InsertionSort.java

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
public class InsertionSort {
2+
3+
public static void main(String[] args) {
4+
int[] nums = { 1, 2, 7, 9, 5, 8 };
5+
6+
for (int i = 1, j, current; i < nums.length; ++i) {
7+
current = nums[i];
8+
for (j = i - 1; j >=0 && nums[j] > current; --j) {
9+
nums[j + 1] = nums[j];
10+
}
11+
nums[j + 1] = current;
12+
}
13+
}
14+
}

basic/sort/README.md

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# 常见的排序算法
2+
3+
## 冒泡排序
4+
5+
定义一个布尔变量 `hasChange`,用来标记每轮是否进行了交换。在每轮遍历开始时,将 `hasChange` 设置为 false。
6+
7+
### 代码示例
8+
9+
```java
10+
for (int i = 0; i < nums.length - 1; ++i) {
11+
for (int j = 0; j < nums.length - 1 - i; ++j) {
12+
if (nums[j] > nums[j + 1]) {
13+
swap(nums, j, j + 1);
14+
}
15+
}
16+
}
17+
```
18+
19+
### 算法分析
20+
21+
空间复杂度 O(1)、时间复杂度 O(n^2)。
22+
23+
分情况讨论:
24+
25+
1. 给定的数组按照顺序已经排好:只需要进行 `n-1` 次比较,两两交换次数为 0,时间复杂度为 O(n),这是最好的情况。
26+
2. 给定的数组按照逆序排列:需要进行 `n*(n-1)/2` 次比较,时间复杂度为 O(n^2),这是最坏的情况。
27+
3. 给定的数组杂乱无章。在这种情况下,平均时间复杂度 O(n^2)。
28+
29+
因此,时间复杂度是 O(n^2),这是一种稳定的排序算法。
30+
31+
> 稳定是指,两个相等的数,在排序过后,相对位置保持不变。
32+
33+
## 插入排序
34+
35+
与冒泡排序对比:
36+
37+
- 在冒泡排序中,经过每一轮的排序处理后,数组后端的数是排好序的。
38+
- 在插入排序中,经过每一轮的排序处理后,数组前端的数是拍好序的。
39+
40+
插入排序算法的基本思想是:不断将尚未排好序的数插入到已经排好序的部分。
41+
42+
### 代码示例
43+
44+
```java
45+
for (int i = 1, j, current; i < nums.length; ++i) {
46+
current = nums[i];
47+
for (j = i - 1; j >=0 && nums[j] > current; --j) {
48+
nums[j + 1] = nums[j];
49+
}
50+
nums[j + 1] = current;
51+
}
52+
```
53+
54+
### 算法分析
55+
56+
空间复杂度 O(1),时间复杂度 O(n^2)。
57+
58+
分情况讨论:
59+
60+
1. 给定的数组按照顺序排好序:只需要进行 n-1 次比较,两两交换次数为 0,时间复杂度为 O(n),这是最好的情况。
61+
2. 给定的数组按照逆序排列:需要进行 `n*(n-1)/2` 次比较,时间复杂度为 O(n^2),这是最坏的情况。
62+
3. 给定的数组杂乱无章:在这种情况下,平均时间复杂度是 O(n^2)。
63+
64+
因此,时间复杂度是 O(n^2),这也是一种稳定的排序算法。
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
class Solution {
2+
/**
3+
* 贪心算法
4+
*/
5+
public int findMaximizedCapital(int k, int W, int[] Profits, int[] Capital) {
6+
// 首先检查是否存在所有项目都可投资且初始资本 W >= max(Capital) 的情况。如果是,返回利润中前 k 个最大元素的和。
7+
boolean speedUp = true;
8+
for (int c : Capital) if (W < c) speedUp = false;
9+
if (speedUp) {
10+
PriorityQueue<Integer> heap = new PriorityQueue<>();
11+
for (int p : Profits) {
12+
heap.add(p);
13+
if (heap.size() > k) heap.poll();
14+
}
15+
for (int h : heap) W += h;
16+
return W;
17+
}
18+
19+
int idx;
20+
int n = Profits.length;
21+
for (int i = 0; i < Math.min(k, n); ++i) {
22+
idx = -1;
23+
// 找到获取利润最多的项目
24+
for (int j = 0; j < n; ++j) {
25+
if (W >= Capital[j]) {
26+
if (idx == -1) idx = j;
27+
else if (Profits[idx] < Profits[j]) idx = j;
28+
}
29+
}
30+
// 找不到合适的项目
31+
if (idx == -1) break;
32+
// 累计当前项目的利润到总利润中,并把当前项目标记为"不可用"(设置成最大整数)
33+
W += Profits[idx];
34+
Capital[idx] = Integer.MAX_VALUE;
35+
}
36+
return W;
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class H2O {
2+
3+
private Semaphore h = new Semaphore(2);
4+
private Semaphore o = new Semaphore(0);
5+
public H2O() {
6+
7+
}
8+
9+
public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
10+
11+
// releaseHydrogen.run() outputs "H". Do not change or remove this line.
12+
h.acquire();
13+
releaseHydrogen.run();
14+
o.release();
15+
}
16+
17+
public void oxygen(Runnable releaseOxygen) throws InterruptedException {
18+
19+
// releaseOxygen.run() outputs "O". Do not change or remove this line.
20+
o.acquire(2);
21+
releaseOxygen.run();
22+
h.release(2);
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
class FizzBuzz {
2+
private int n;
3+
4+
public FizzBuzz(int n) {
5+
this.n = n;
6+
}
7+
8+
private Semaphore fSema = new Semaphore(0);
9+
private Semaphore bSema = new Semaphore(0);
10+
private Semaphore fbSema = new Semaphore(0);
11+
private Semaphore nSema = new Semaphore(1);
12+
13+
// printFizz.run() outputs "fizz".
14+
public void fizz(Runnable printFizz) throws InterruptedException {
15+
for (int i = 3; i <= n; i = i + 3) {
16+
if (i % 5 != 0) {
17+
fSema.acquire();
18+
printFizz.run();
19+
nSema.release();
20+
}
21+
}
22+
}
23+
24+
// printBuzz.run() outputs "buzz".
25+
public void buzz(Runnable printBuzz) throws InterruptedException {
26+
for (int i = 5; i <= n; i = i + 5) {
27+
if (i % 3 != 0) {
28+
bSema.acquire();
29+
printBuzz.run();
30+
nSema.release();
31+
}
32+
}
33+
}
34+
35+
// printFizzBuzz.run() outputs "fizzbuzz".
36+
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
37+
for (int i = 15; i <= n; i = i + 15) {
38+
fbSema.acquire();
39+
printFizzBuzz.run();
40+
nSema.release();
41+
}
42+
}
43+
44+
// printNumber.accept(x) outputs "x", where x is an integer.
45+
public void number(IntConsumer printNumber) throws InterruptedException {
46+
for (int i = 1; i <= n; i++) {
47+
nSema.acquire();
48+
if (i % 3 == 0 && i % 5 == 0) {
49+
fbSema.release();
50+
} else if (i % 3 == 0) {
51+
fSema.release();
52+
} else if (i % 5 == 0) {
53+
bSema.release();
54+
} else {
55+
printNumber.accept(i);
56+
nSema.release();
57+
}
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)