auto commit
This commit is contained in:
parent
3a86098be5
commit
d2e33dd46b
286
notes/算法.md
286
notes/算法.md
@ -83,6 +83,8 @@ public class ThreeSum {
|
|||||||
|
|
||||||
通过将数组先排序,对两个元素求和,并用二分查找方法查找是否存在该和的相反数,如果存在,就说明存在三元组的和为 0。
|
通过将数组先排序,对两个元素求和,并用二分查找方法查找是否存在该和的相反数,如果存在,就说明存在三元组的和为 0。
|
||||||
|
|
||||||
|
应该注意的是,只有数组不含有相同元素才能使用这种解法,否则二分查找的结果会出错。
|
||||||
|
|
||||||
该方法可以将 ThreeSum 算法增长数量级降低为 O(N<sup>2</sup>logN)。
|
该方法可以将 ThreeSum 算法增长数量级降低为 O(N<sup>2</sup>logN)。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@ -94,18 +96,19 @@ public class ThreeSumFast {
|
|||||||
for (int i = 0; i < N; i++)
|
for (int i = 0; i < N; i++)
|
||||||
for (int j = i + 1; j < N; j++) {
|
for (int j = i + 1; j < N; j++) {
|
||||||
int target = -nums[i] - nums[j];
|
int target = -nums[i] - nums[j];
|
||||||
int index = binarySearch(nums, target);
|
int index = BinarySearch.search(nums, target);
|
||||||
// 应该注意这里的下标必须大于 j,否则会重复统计。
|
// 应该注意这里的下标必须大于 j,否则会重复统计。
|
||||||
if (index <= j)
|
if (index > j)
|
||||||
continue;
|
|
||||||
while (index < N && nums[index++] == target)
|
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
private static int binarySearch(int[] nums, int target) {
|
```java
|
||||||
|
public class BinarySearch {
|
||||||
|
public static int search(int[] nums, int target) {
|
||||||
int l = 0, h = nums.length - 1;
|
int l = 0, h = nums.length - 1;
|
||||||
while (l <= h) {
|
while (l <= h) {
|
||||||
int m = l + (h - l) / 2;
|
int m = l + (h - l) / 2;
|
||||||
@ -142,23 +145,38 @@ public class ThreeSumFast {
|
|||||||
public class RatioTest {
|
public class RatioTest {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
int N = 500;
|
int N = 500;
|
||||||
int K = 7;
|
int loopTimes = 7;
|
||||||
long preTime = -1;
|
double preTime = -1;
|
||||||
while (K-- > 0) {
|
while (loopTimes-- > 0) {
|
||||||
int[] nums = new int[N];
|
int[] nums = new int[N];
|
||||||
long startTime = System.currentTimeMillis();
|
StopWatch.start();
|
||||||
int cnt = ThreeSum.count(nums);
|
int cnt = ThreeSum.count(nums);
|
||||||
long endTime = System.currentTimeMillis();
|
System.out.println(cnt);
|
||||||
long time = endTime - startTime;
|
double elapsedTime = StopWatch.elapsedTime();
|
||||||
double ratio = preTime == -1 ? 0 : (double) time / preTime;
|
double ratio = preTime == -1 ? 0 : elapsedTime / preTime;
|
||||||
System.out.println(N + " " + time + " " + ratio);
|
System.out.println(N + " " + elapsedTime + " " + ratio);
|
||||||
preTime = time;
|
preTime = elapsedTime;
|
||||||
N *= 2;
|
N *= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class StopWatch {
|
||||||
|
private static long start;
|
||||||
|
|
||||||
|
public static void start(){
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double elapsedTime() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
return (now - start) / 1000.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 注意事项
|
## 注意事项
|
||||||
|
|
||||||
### 1. 大常数
|
### 1. 大常数
|
||||||
@ -187,25 +205,39 @@ public class RatioTest {
|
|||||||
|
|
||||||
First-In-Last-Out
|
First-In-Last-Out
|
||||||
|
|
||||||
|
```java
|
||||||
|
public interface MyStack<Item> extends Iterable<Item> {
|
||||||
|
MyStack<Item> push(Item item);
|
||||||
|
|
||||||
|
Item pop() throws Exception;
|
||||||
|
|
||||||
|
boolean isEmpty();
|
||||||
|
|
||||||
|
int size();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 1. 数组实现
|
### 1. 数组实现
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import java.util.Iterator;
|
public class ResizingArrayStack<Item> implements MyStack<Item> {
|
||||||
|
|
||||||
public class ResizingArrayStack<Item> implements Iterable<Item> {
|
|
||||||
// 栈元素数组
|
// 栈元素数组
|
||||||
private Item[] a = (Item[]) new Object[1]; // 只能通过转型来创建泛型数组
|
private Item[] a = (Item[]) new Object[1]; // 只能通过转型来创建泛型数组
|
||||||
// 元素数量
|
// 元素数量
|
||||||
private int N = 0;
|
private int N = 0;
|
||||||
|
|
||||||
public void push(Item item) {
|
@Override
|
||||||
|
public MyStack<Item> push(Item item) {
|
||||||
check();
|
check();
|
||||||
a[N++] = item;
|
a[N++] = item;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Item pop() throws Exception {
|
public Item pop() throws Exception {
|
||||||
if (isEmpty())
|
if (isEmpty())
|
||||||
throw new Exception("stack is empty");
|
throw new Exception("stack is empty");
|
||||||
|
|
||||||
Item item = a[--N];
|
Item item = a[--N];
|
||||||
check();
|
check();
|
||||||
a[N] = null; // 避免对象游离
|
a[N] = null; // 避免对象游离
|
||||||
@ -229,10 +261,12 @@ public class ResizingArrayStack<Item> implements Iterable<Item> {
|
|||||||
a = tmp;
|
a = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return N == 0;
|
return N == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return N;
|
return N;
|
||||||
}
|
}
|
||||||
@ -240,57 +274,29 @@ public class ResizingArrayStack<Item> implements Iterable<Item> {
|
|||||||
@Override
|
@Override
|
||||||
public Iterator<Item> iterator() {
|
public Iterator<Item> iterator() {
|
||||||
// 返回逆序遍历的迭代器
|
// 返回逆序遍历的迭代器
|
||||||
return new ReverseArrayIterator();
|
return new Iterator<Item>() {
|
||||||
}
|
private int i = N;
|
||||||
|
|
||||||
private class ReverseArrayIterator implements Iterator<Item> {
|
@Override
|
||||||
private int i = N;
|
public boolean hasNext() {
|
||||||
|
return i > 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public Item next() {
|
||||||
return i > 0;
|
return a[--i];
|
||||||
}
|
}
|
||||||
|
};
|
||||||
@Override
|
|
||||||
public Item next() {
|
|
||||||
return a[--i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
ResizingArrayStack<Integer> stack = new ResizingArrayStack();
|
|
||||||
stack.push(1);
|
|
||||||
stack.push(2);
|
|
||||||
stack.push(3);
|
|
||||||
stack.push(4);
|
|
||||||
System.out.println(stack.isEmpty());
|
|
||||||
System.out.println(stack.size());
|
|
||||||
System.out.println(stack.pop());
|
|
||||||
System.out.println(stack.pop());
|
|
||||||
for (Integer item : stack)
|
|
||||||
System.out.println(item);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```html
|
|
||||||
false
|
|
||||||
4
|
|
||||||
4
|
|
||||||
3
|
|
||||||
2
|
|
||||||
1
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 链表实现
|
### 2. 链表实现
|
||||||
|
|
||||||
需要使用链表的头插法来实现,因为头插法中最后压入栈的元素在链表的开头,它的 next 指针指向前一个压入栈的元素,在弹出元素使就可以通过 next 指针遍历到前一个压入栈的元素从而让这个元素称为新的栈顶元素。
|
需要使用链表的头插法来实现,因为头插法中最后压入栈的元素在链表的开头,它的 next 指针指向前一个压入栈的元素,在弹出元素使就可以通过 next 指针遍历到前一个压入栈的元素从而让这个元素称为新的栈顶元素。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class ListStack<Item> {
|
public class ListStack<Item> implements MyStack<Item> {
|
||||||
|
|
||||||
private Node top = null;
|
private Node top = null;
|
||||||
private int N = 0;
|
private int N = 0;
|
||||||
|
|
||||||
@ -299,22 +305,17 @@ public class ListStack<Item> {
|
|||||||
Node next;
|
Node next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
@Override
|
||||||
return N == 0;
|
public MyStack<Item> push(Item item) {
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return N;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void push(Item item) {
|
|
||||||
Node newTop = new Node();
|
Node newTop = new Node();
|
||||||
newTop.item = item;
|
newTop.item = item;
|
||||||
newTop.next = top;
|
newTop.next = top;
|
||||||
top = newTop;
|
top = newTop;
|
||||||
N++;
|
N++;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Item pop() throws Exception {
|
public Item pop() throws Exception {
|
||||||
if (isEmpty())
|
if (isEmpty())
|
||||||
throw new Exception("stack is empty");
|
throw new Exception("stack is empty");
|
||||||
@ -323,28 +324,36 @@ public class ListStack<Item> {
|
|||||||
N--;
|
N--;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```java
|
@Override
|
||||||
public static void main(String[] args) throws Exception {
|
public boolean isEmpty() {
|
||||||
ListStack<Integer> stack = new ListStack();
|
return N == 0;
|
||||||
stack.push(1);
|
}
|
||||||
stack.push(2);
|
|
||||||
stack.push(3);
|
|
||||||
stack.push(4);
|
|
||||||
System.out.println(stack.isEmpty());
|
|
||||||
System.out.println(stack.size());
|
|
||||||
System.out.println(stack.pop());
|
|
||||||
System.out.println(stack.pop());
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```html
|
@Override
|
||||||
false
|
public int size() {
|
||||||
4
|
return N;
|
||||||
4
|
}
|
||||||
3
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Item> iterator() {
|
||||||
|
return new Iterator<Item>() {
|
||||||
|
private Node cur = top;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return cur != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item next() {
|
||||||
|
Item item = cur.item;
|
||||||
|
cur = cur.next;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 队列
|
## 队列
|
||||||
@ -355,6 +364,88 @@ First-In-First-Out
|
|||||||
|
|
||||||
这里需要考虑 first 和 last 指针哪个作为链表的开头。因为出队列操作需要让队首元素的下一个元素成为队首,所以需要容易获取下一个元素,而链表的头部节点的 next 指针指向下一个元素,因此可以让 first 指针链表的开头。
|
这里需要考虑 first 和 last 指针哪个作为链表的开头。因为出队列操作需要让队首元素的下一个元素成为队首,所以需要容易获取下一个元素,而链表的头部节点的 next 指针指向下一个元素,因此可以让 first 指针链表的开头。
|
||||||
|
|
||||||
|
```java
|
||||||
|
public interface MyQueue<Item> extends Iterable<Item> {
|
||||||
|
int size();
|
||||||
|
|
||||||
|
boolean isEmpty();
|
||||||
|
|
||||||
|
MyQueue<Item> add(Item item);
|
||||||
|
|
||||||
|
Item remove() throws Exception;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class ListQueue<Item> implements MyQueue<Item> {
|
||||||
|
private Node first;
|
||||||
|
private Node last;
|
||||||
|
int N = 0;
|
||||||
|
|
||||||
|
private class Node {
|
||||||
|
Item item;
|
||||||
|
Node next;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return N == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MyQueue<Item> add(Item item) {
|
||||||
|
Node newNode = new Node();
|
||||||
|
newNode.item = item;
|
||||||
|
newNode.next = null;
|
||||||
|
if (isEmpty()) {
|
||||||
|
last = newNode;
|
||||||
|
first = newNode;
|
||||||
|
} else {
|
||||||
|
last.next = newNode;
|
||||||
|
last = newNode;
|
||||||
|
}
|
||||||
|
N++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item remove() throws Exception {
|
||||||
|
if (isEmpty())
|
||||||
|
throw new Exception("queue is empty");
|
||||||
|
Node node = first;
|
||||||
|
first = first.next;
|
||||||
|
N--;
|
||||||
|
if (isEmpty())
|
||||||
|
last = null;
|
||||||
|
return node.item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Item> iterator() {
|
||||||
|
return new Iterator<Item>() {
|
||||||
|
Node cur = first;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return cur != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item next() {
|
||||||
|
Item item = cur.item;
|
||||||
|
cur = cur.next;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Queue<Item> {
|
public class Queue<Item> {
|
||||||
private Node first;
|
private Node first;
|
||||||
@ -401,25 +492,6 @@ public class Queue<Item> {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
Queue queue = new Queue();
|
|
||||||
queue.add(1);
|
|
||||||
queue.add(2);
|
|
||||||
System.out.println(queue.remove());
|
|
||||||
System.out.println(queue.remove());
|
|
||||||
queue.add(3);
|
|
||||||
queue.add(4);
|
|
||||||
System.out.println(queue.size());
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```html
|
|
||||||
1
|
|
||||||
2
|
|
||||||
2
|
|
||||||
```
|
|
||||||
|
|
||||||
# 三、排序
|
# 三、排序
|
||||||
|
|
||||||
待排序的元素需要实现 Java 的 Comparable 接口,该接口有 compareTo() 方法,可以用它来判断两个元素的大小关系。
|
待排序的元素需要实现 Java 的 Comparable 接口,该接口有 compareTo() 方法,可以用它来判断两个元素的大小关系。
|
||||||
|
Loading…
x
Reference in New Issue
Block a user