auto commit

This commit is contained in:
CyC2018 2018-06-06 20:16:19 +08:00
parent 3a86098be5
commit d2e33dd46b

View File

@ -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() 方法,可以用它来判断两个元素的大小关系。