求最大公约数
计算两个非负整数p和q的最大公约数,若q是0,则最大公约数是p.否则将p处于q得到余数r,p和q的最大公约数即为q和r的最大公约数。
public static int gcd(int p, int q) {
if (q == 0) return p;
int r = p % q;
return gcd(q, r);
}
public static int gcd2(int p, int q) {
while(q != 0) {
int r = p % q;
p = q;
q = r;
}
return p;
}
二分查找
public static int indexOf(int[] a, int key) {
int lo = 0;
int hi = a.length - 1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (key < a[mid]) hi = mid - 1;
else if (key > a[mid]) lo = mid + 1;
else return mid;
}
return -1;
}
习题1.1.9 把一个正整数N的二进制表示形式打印出来
类别十进制数,十进制207 % 10 = 7正是个位数,207 /10 = 20;相当于右移一位
二进制也是一样,二进制1000101 % 2 = 1是右边第一位数,1000101 / 2=100010 相当于右移一位,for循环继续获取右边第一位数
public class Ex_1_1_09 {
public static void main(String[] args)
{
int N = 234245;
StdOut.println(Integer.toBinaryString(N)); //java类库的实现方式
String s = "";
for (int n = N; n > 0; n /= 2)
s = (n % 2) + s;
StdOut.println(s);
}
}
Stack的应用,求表达式的值
例如输入:( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) ),输出:101.0
表达式的括号和空格不能少,操作步骤如下
忽略左括号,将操作数压入操作数栈,将运算符压入运算符栈,当遇到右括号时,弹出一个运算符,弹出所需数量的操作数,并将运算符和操作数的运算结果压入操作数栈。
/*************************************************************************
* Compilation: javac Evaluate.java
* Execution: java Evaluate
* Dependencies: Stack.java
*
* Evaluates (fully parenthesized) arithmetic expressions using
* Dijkstra's two-stack algorithm.
*
* % java Evaluate
* ( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )
* 101.0
*
* % java Evaulate
* ( ( 1 + sqrt ( 5 ) ) / 2.0 )
* 1.618033988749895
*
*
*
* Remarkably, Dijkstra's algorithm computes the same
* answer if we put each operator *after* its two operands
* instead of *between* them.
*
* % java Evaluate
* ( 1 ( ( 2 3 + ) ( 4 5 * ) * ) + )
* 101.0
*
* Moreover, in such expressions, all parentheses are redundant!
* Removing them yields an expression known as a postfix expression.
* 1 2 3 + 4 5 * * +
*
*
*************************************************************************/
public class Evaluate {
public static void main(String[] args) {
Stack<String> ops = new Stack<String>();
Stack<Double> vals = new Stack<Double>();
while (!StdIn.isEmpty()) {
String s = StdIn.readString();
if (s.equals("(")) ;
else if (s.equals("+")) ops.push(s);
else if (s.equals("-")) ops.push(s);
else if (s.equals("*")) ops.push(s);
else if (s.equals("/")) ops.push(s);
else if (s.equals("sqrt")) ops.push(s);
else if (s.equals(")")) {
String op = ops.pop();
double v = vals.pop();
if (op.equals("+")) v = vals.pop() + v;
else if (op.equals("-")) v = vals.pop() - v;
else if (op.equals("*")) v = vals.pop() * v;
else if (op.equals("/")) v = vals.pop() / v;
else if (op.equals("sqrt")) v = Math.sqrt(v);
vals.push(v);
}
else vals.push(Double.parseDouble(s));
}
StdOut.println(vals.pop());
}
}
习题1.3.4 Stack的应用,判断括号是否配对完整
例如[()]{}{[()()]()}是完整的, [(])是不完整的
/*************************************************************************
* Compilation: javac Parentheses.java
* Execution: java Parentheses
* Dependencies: In.java Stack.java
*
* Reads in a text file and checks to see if the parentheses are balanced.
*
* % java Parentheses
* [()]{}{[()()]()}
* true
*
* % java Parentheses
* [(])
* false
*
*************************************************************************/
public class Parentheses {
private static final char LEFT_PAREN = '(';
private static final char RIGHT_PAREN = ')';
private static final char LEFT_BRACE = '{';
private static final char RIGHT_BRACE = '}';
private static final char LEFT_BRACKET = '[';
private static final char RIGHT_BRACKET = ']';
public static boolean isBalanced(String s) {
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == LEFT_PAREN) stack.push(LEFT_PAREN);
if (s.charAt(i) == LEFT_BRACE) stack.push(LEFT_BRACE);
if (s.charAt(i) == LEFT_BRACKET) stack.push(LEFT_BRACKET);
if (s.charAt(i) == RIGHT_PAREN) {
if (stack.isEmpty()) return false;
if (stack.pop() != LEFT_PAREN) return false;
}
else if (s.charAt(i) == RIGHT_BRACE) {
if (stack.isEmpty()) return false;
if (stack.pop() != LEFT_BRACE) return false;
}
else if (s.charAt(i) == RIGHT_BRACKET) {
if (stack.isEmpty()) return false;
if (stack.pop() != LEFT_BRACKET) return false;
}
}
return stack.isEmpty();
}
public static void main(String[] args) {
In in = new In();
String s = in.readAll().trim();
StdOut.println(isBalanced(s));
}
}
习题1.3.9 将算术表达式由中序表达式转化成后序表达式
package chapter1_3;
import StdLib.StdIn;
import StdLib.StdOut;
/******************************************************************************
* Compilation: javac InfixToPostfix.java
* Execution: java InfixToPostFix
* Dependencies: Stack.java StdIn.java StdOut.java
*
* Reads in a fully parenthesized infix expression from standard input
* and prints an equivalent postfix expression to standard output.
*
* Windows users: replace [Ctrl-d] with [Ctrl-z] to signify end of file.
*
* % java InfixToPostfix
* ( 2 + ( ( 3 + 4 ) * ( 5 * 6 ) ) )
* [Ctrl-d]
* 2 3 4 + 5 6 * * +
*
* % java InfixToPostfix
* ( ( ( 5 + ( 7 * ( 1 + 1 ) ) ) * 3 ) + ( 2 * ( 1 + 1 ) ) )
* 5 7 1 1 + * + 3 * 2 1 1 + * +
*
* % java InfixToPostfix | java EvaluatePostfix
* ( 2 + ( ( 3 + 4 ) * ( 5 * 6 ) ) )
* [Ctrl-d]
* 212
*
******************************************************************************/
public class InfixToPostfix {
public static void main(String[] args) {
Stack<String> stack = new Stack<String>();
while (!StdIn.isEmpty()) {
String s = StdIn.readString();
if (s.equals("+")) stack.push(s);
else if (s.equals("*")) stack.push(s);
else if (s.equals(")")) StdOut.print(stack.pop() + " ");
else if (s.equals("(")) StdOut.print("");
else StdOut.print(s + " ");
}
StdOut.println();
}
}
习题1.3.11 后序表达式求值
package chapter1_3;
import StdLib.StdIn;
import StdLib.StdOut;
/******************************************************************************
* Compilation: javac EvaluatePostfix.java
* Execution: java EvaluatePostfix < file.txt
* Dependencies: Stack.java StdIn.java StdOut.java
*
* Evaluates postfix expresions using a stack.
*
* Windows users: replace [Ctrl-d] with [Ctrl-z] to signify end of file.
*
* % java EvaluatePostfix
* 3 4 5 + *
* [Ctrl-d]
* 27
*
* % java EvaluatePostfix
* 1 2 3 4 5 * + 6 * * +
* [Ctrl-d]
* 277
*
* % java EvaluatePostfix
* 7 16 16 16 * * * 5 16 16 * * 3 16 * 1 + + +
* [Ctrl-d]
* 30001
*
* % java EvaluatePostfix
* 7 16 * 5 + 16 * 3 + 16 * 1 +
* [Ctrl-d]
* 30001
*
* Known bugs
* ----------
* - No error checking - assumes input is legal postfix expression.
* - All token must be separated by whitespace, e.g., 1 5+ is illegal.
*
******************************************************************************/
public class EvaluatePostfix {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<Integer>();
while (!StdIn.isEmpty()) {
String s = StdIn.readString();
if (s.equals("+")) stack.push(stack.pop() + stack.pop());
else if (s.equals("*")) stack.push(stack.pop() * stack.pop());
else stack.push(Integer.parseInt(s));
}
StdOut.println(stack.pop());
}
}
习题1.3.37 Josephus问题。在这个古老的问题中,N个身陷绝境的人一致同意通过以下方式减少生存的人数。他们围坐在一圈(位置记为0到N-1)并从第1个人开始报数,报到M的人会被杀死,然后从下一个人继续重新报数,直到最后一个人留下,传说Josephus找到了不会被杀死的位置。编写一个Queue的用例,从命令行接受N和M并打印出人们被杀死的顺序。
思路:将N个人放入队列,从队列头部开始报数,将报数的人移除队列并添加到队列尾部,报到M的人直接移除队列,然后继续从队列头部重新报数,直到队列为空。
package chapter1_3;
import StdLib.StdOut;
/******************************************************************************
* Compilation: javac Josephus.java
* Execution: java Josephus m n
* Dependencies: Queue.java
*
* Solves the Josephus problem.
*
* % java Josephus 2 7
* 1 3 5 0 4 2 6
*
******************************************************************************/
public class Josephus {
public static void main(String[] args) {
int m = Integer.parseInt(args[0]);
int n = Integer.parseInt(args[1]);
// initialize the queue
Queue<Integer> queue = new Queue<Integer>();
for (int i = 0; i < n; i++)
queue.enqueue(i);
while (!queue.isEmpty()) {
for (int i = 0; i < m-1; i++)
queue.enqueue(queue.dequeue());
StdOut.print(queue.dequeue() + " ");
}
StdOut.println();
}
}
习题1.3.18~1.3.31 链表练习
package chapter1_3;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class List<Item> implements Iterable<Item> {
int N;
Node first;
Node last;
private class Node {
Item item;
Node next;
}
public List() {
first = null;
last = null;
}
public List(Item[] a) {
for (Item t : a)
append(t);
}
public List(Iterable<Item> coll) {
for (Item t : coll)
append(t);
}
public boolean isEmpty() {
return first == null;
}
public int size() {
return N;
}
public Item first() {
if (isEmpty())
throw new RuntimeException("List is empty");
return first.item;
}
public Item last() {
if (isEmpty())
throw new RuntimeException("List is empty");
return last.item;
}
public void append(Item item) {
Node x = new Node();
x.item = item;
if (isEmpty()) {
first = last = x;
} else {
last.next = x;
last = x;
}
N++;
}
public void prepend(Item item) {
Node x = new Node();
x.item = item;
if (isEmpty()) {
first = last = x;
} else {
x.next = first;
first = x;
}
N++;
}
public Item removeFirst() {
if (isEmpty()) throw new RuntimeException("List is empty");
Item item = first.item;
first = first.next;
N--;
if (isEmpty()) last = null;
return item;
}
/*****************
* Exercise 1.3.19
*****************/
public Item removeLast() {
if (isEmpty()) throw new RuntimeException("List is empty");
if (first == last) return removeFirst();
Item item = last.item;
Node prev = null, curr = first;
while (curr.next != null) {
prev = curr;
curr = curr.next;
}
prev.next = null;
last = prev;
N--;
return item;
}
/*****************
* Exercise 1.3.20
*****************/
public Item delete(int k) {
if (k < 1)
return null;
int i = 1;
Node prev = null, curr = first;
while (i < k && curr != null) {
prev = curr;
curr = curr.next;
i++;
}
if (curr != null) {
if (prev == null)
first = curr.next;
else
prev.next = curr.next;
if (curr.next == null)
last = prev;
N--;
return curr.item;
} else
return null;
}
/*************************************
* Exercise 1.3.21
* (Renamed from find() to contains())
*************************************/
public boolean contains(Item item) {
Node curr = first;
while (curr != null && !curr.item.equals(item))
curr = curr.next;
return curr != null;
}
/*****************
* Exercise 1.3.26
*****************/
public void remove(Item item) {
List<Integer> idx = new List<Integer>();
int i = 1;
for (Item x : this) {
if (x.equals(item))
idx.prepend(i);
i++;
}
for (int k : idx)
delete(k);
}
public void remove2(Item item) {
Node pre = null;
Node curr = first;
while(curr != null) {
if (curr.item.equals(item)) {
if (first == curr)
first = curr.next;
if (last == curr)
last = pre;
if (pre != null)
pre.next = curr.next;
curr = curr.next;
} else {
pre = curr;
curr = curr.next;
}
}
}
/*****************
* Exercise 1.3.30
*****************/
public void reverse() {
reverse(first);
Node tmp = first;
first = last;
last = tmp;
}
private Node reverse(Node n) {
Node dest = null;
Node src = n;
while (src != null) {
Node tmp = src.next;
src.next = dest;
dest = src;
src = tmp;
}
return dest;
}
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
}
public Iterator<Item> iterator() {
return new ListIterator();
}
private class ListIterator implements Iterator<Item> {
private Node current = first;
public boolean hasNext() {
return current != null;
}
public void remove() {
throw new UnsupportedOperationException();
}
public Item next() {
if (!hasNext())
throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
习题1.3.31 双向链表实现
package chapter1_3;
/*************************************************************************
*
* Exercise 1.3.31
*
*************************************************************************/
import java.util.Iterator;
import java.util.NoSuchElementException;
public class DoublyLinkedList<Item> implements Iterable<Item>
{
private int N;
private DoubleNode first;
private DoubleNode last;
private class DoubleNode
{
private DoublyLinkedList<Item> parent = list();
private Item item;
private DoubleNode prev;
private DoubleNode next;
}
private DoublyLinkedList<Item> list()
{
return this;
}
public DoublyLinkedList()
{
first = null;
last = null;
}
public DoublyLinkedList(Item[] a)
{
for (Item t : a)
append(t);
}
public DoublyLinkedList(Iterable<Item> coll)
{
for (Item t : coll)
append(t);
}
public boolean isEmpty()
{
return first == null;
}
public int size()
{
return N;
}
public Item first()
{
if (isEmpty()) throw new RuntimeException("List is empty");
return first.item;
}
public Item last()
{
if (isEmpty()) throw new RuntimeException("List is empty");
return last.item;
}
public DoubleNode node(int k)
{
DoubleNode curr = null;
int i = 1;
if (k > 0)
{
curr = first;
while (i < k && curr != null)
{
curr = curr.next;
i++;
}
}
else if (k < 0)
{
k = -k;
curr = last;
while (i < k && curr != null)
{
curr = curr.prev;
i++;
}
}
return curr;
}
public void prepend(Item item)
{
DoubleNode x = new DoubleNode();
x.item = item;
if (isEmpty()) { first = x; last = x; }
else { x.next = first; first.prev = x; first = x; }
N++;
}
public void append(Item item)
{
DoubleNode x = new DoubleNode();
x.item = item;
if (isEmpty()) { first = x; last = x; }
else { x.prev = last; last.next = x; last = x; }
N++;
}
public void insertBefore(DoubleNode node, Item item)
{
if (node.parent != this) throw new RuntimeException("Node does not belong to list.");
if (node == first)
prepend(item);
else
{
DoubleNode prev = node.prev;
DoubleNode x = new DoubleNode();
x.item = item;
x.prev = prev;
x.next = node;
prev.next = x;
node.prev = x;
N++;
}
}
public void insertAfter(DoubleNode node, Item item)
{
if (node.parent != this) throw new RuntimeException("Node does not belong to list.");
if (node == last)
append(item);
else
{
DoubleNode next = node.next;
DoubleNode x = new DoubleNode();
x.item = item;
x.prev = node;
x.next = next;
next.prev = x;
node.next = x;
N++;
}
}
public Item removeFirst()
{
if (isEmpty()) throw new RuntimeException("List is empty");
Item item = first.item;
first.parent = null;
if (first.next != null) first.next.prev = null;
first = first.next;
N--;
if (first == null) last = null; // to avoid loitering
return item;
}
public Item removeLast()
{
if (isEmpty()) throw new RuntimeException("List is empty");
Item item = last.item;
last.parent = null;
if (last.prev != null) last.prev.next = null;
last = last.prev;
N--;
if (last == null) first = null; // to avoid loitering
return item;
}
public Item remove(DoubleNode node)
{
if (node.parent != this) throw new RuntimeException("Node does not belong to list.");
if (node == first)
return removeFirst();
else if (node == last)
return removeLast();
else
{
node.parent = null;
DoubleNode prev = node.prev,
next = node.next;
prev.next = node.next;
next.prev = node.prev;
N--;
return node.item;
}
}
public String toString()
{
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
}
public Iterator<Item> iterator()
{
return new ListIterator();
}
private class ListIterator implements Iterator<Item>
{
private DoubleNode current = first;
public boolean hasNext() { return current != null; }
public void remove() { throw new UnsupportedOperationException(); }
public Item next()
{
if (!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
}
/**
* Used in unit tests, to verify that the list is double-linked correctly.
*/
public Iterable<Item> reversed()
{
return new ReverseIterable();
}
private class ReverseIterable implements Iterable<Item>
{
public String toString()
{
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
}
public Iterator<Item> iterator()
{
return new ReverseListIterator();
}
private class ReverseListIterator implements Iterator<Item>
{
private DoubleNode current = last;
public boolean hasNext() { return current != null; }
public void remove() { throw new UnsupportedOperationException(); }
public Item next()
{
if (!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.prev;
return item;
}
}
}
/************
* Unit tests
************/
private static void testPrepend()
{
StdOut.println("prepend:");
int[] a = { 2, 4, 6, 8, 10 };
DoublyLinkedList<Integer> lst = new DoublyLinkedList<Integer>();
for (int i = 0; i < a.length; i++)
lst.prepend(a[i]);
showList(lst);
StdOut.println();
}
private static void testAppend()
{
StdOut.println("append:");
int[] a = { 2, 4, 6, 8, 10 };
DoublyLinkedList<Integer> lst = new DoublyLinkedList<Integer>();
for (int i = 0; i < a.length; i++)
lst.append(a[i]);
showList(lst);
StdOut.println();
}
private static void testRemoveFirst()
{
StdOut.println("removeFirst:");
DoublyLinkedList<Integer> lst = new DoublyLinkedList<Integer>(new Integer[] { 6, 8, 12 });
StdOut.println(lst + "[initial]\n");
while (!lst.isEmpty())
{
StdOut.println("removeFirst(): " + lst.removeFirst());
showList(lst);
}
StdOut.println();
}
private static void testRemoveLast()
{
StdOut.println("removeLast:");
DoublyLinkedList<Integer> lst = new DoublyLinkedList<Integer>(new Integer[] { 6, 8, 12 });
StdOut.println(lst + "[initial]\n");
while (!lst.isEmpty())
{
StdOut.println("removeLast(): " + lst.removeLast());
showList(lst);
}
StdOut.println();
}
private static void testRemove()
{
StdOut.println("remove:");
DoublyLinkedList<Integer> lst = new DoublyLinkedList<Integer>(new Integer[] { 2, 4, 6, 8 });
StdOut.println(lst + "[initial]\n");
int[] k = { 2, -1, 1, 1 };
for (int i = 0; i < k.length; i++)
{
StdOut.printf("remove(node(%d)): %d\n", k[i], lst.remove(lst.node(k[i])));
showList(lst);
}
StdOut.println();
}
private static void testInsertBefore()
{
StdOut.println("insertBefore:");
DoublyLinkedList<Integer> lst = new DoublyLinkedList<Integer>(new Integer[] { 2, 4, 6, 8 });
StdOut.println(lst + "[initial]\n");
int[] k = { 3, 2, 1, -1 },
x = { 10, 12, 14, 16 };
for (int i = 0; i < k.length; i++)
{
StdOut.printf("insertBefore(node(%d), %d):\n", k[i], x[i]);
lst.insertBefore(lst.node(k[i]), x[i]);
showList(lst);
}
StdOut.println();
}
private static void testInsertAfter()
{
StdOut.println("insertAfter:");
DoublyLinkedList<Integer> lst = new DoublyLinkedList<Integer>(new Integer[] { 1, 3, 5, 7 });
StdOut.println(lst + "[initial]\n");
int[] k = { 2, -2, -1, 1 },
x = { 9, 11, 13, 15 };
for (int i = 0; i < k.length; i++)
{
StdOut.printf("insertAfter(node(%d), %d):\n", k[i], x[i]);
lst.insertAfter(lst.node(k[i]), x[i]);
showList(lst);
}
StdOut.println();
}
/*******************
* Unit test helpers
*******************/
private static void showList(DoublyLinkedList lst)
{
StdOut.println(lst);
StdOut.println(lst.reversed() + "[in reverse]");
if (!lst.isEmpty())
StdOut.printf("Size: %d, First: %s, Last: %s\n\n", lst.size(), lst.first(), lst.last());
else
StdOut.printf("Size: %d\n\n", lst.size());
}
public static void main(String[] args)
{
// testPrepend();
// testAppend();
// testRemoveFirst();
// testRemoveLast();
// testRemove();
testInsertBefore();
testInsertAfter();
}
}
ThreeSum问题计算数组中3个数相加等于0的组数O(N^3)解法
package chapter1_4;
/******************************************************************************
* Compilation: javac ThreeSum.java
* Execution: java ThreeSum input.txt
* Dependencies: In.java StdOut.java Stopwatch.java
* Data files: https://algs4.cs.princeton.edu/14analysis/1Kints.txt
* https://algs4.cs.princeton.edu/14analysis/2Kints.txt
* https://algs4.cs.princeton.edu/14analysis/4Kints.txt
* https://algs4.cs.princeton.edu/14analysis/8Kints.txt
* https://algs4.cs.princeton.edu/14analysis/16Kints.txt
* https://algs4.cs.princeton.edu/14analysis/32Kints.txt
* https://algs4.cs.princeton.edu/14analysis/1Mints.txt
*
* A program with cubic running time. Reads n integers
* and counts the number of triples that sum to exactly 0
* (ignoring integer overflow).
*
* % java ThreeSum 1Kints.txt
* 70
*
* % java ThreeSum 2Kints.txt
* 528
*
* % java ThreeSum 4Kints.txt
* 4039
*
******************************************************************************/
/**
* The {@code ThreeSum} class provides static methods for counting
* and printing the number of triples in an array of integers that sum to 0
* (ignoring integer overflow).
* <p>
* This implementation uses a triply nested loop and takes proportional to n^3,
* where n is the number of integers.
* <p>
* For additional documentation, see <a href="https://algs4.cs.princeton.edu/14analysis">Section 1.4</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class ThreeSum {
// Do not instantiate.
private ThreeSum() { }
/**
* Prints to standard output the (i, j, k) with {@code i < j < k}
* such that {@code a[i] + a[j] + a[k] == 0}.
*
* @param a the array of integers
*/
public static void printAll(int[] a) {
int n = a.length;
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
for (int k = j+1; k < n; k++) { //相当于在数组中查找-(a[i+a[j]]),可以用二分查找算法,看ThreeSumFast
if (a[i] + a[j] + a[k] == 0) {
StdOut.println(a[i] + " " + a[j] + " " + a[k]);
}
}
}
}
}
/**
* Returns the number of triples (i, j, k) with {@code i < j < k}
* such that {@code a[i] + a[j] + a[k] == 0}.
*
* @param a the array of integers
* @return the number of triples (i, j, k) with {@code i < j < k}
* such that {@code a[i] + a[j] + a[k] == 0}
*/
public static int count(int[] a) {
int n = a.length;
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
for (int k = j+1; k < n; k++) {
if (a[i] + a[j] + a[k] == 0) {
count++;
}
}
}
}
return count;
}
/**
* Reads in a sequence of integers from a file, specified as a command-line argument;
* counts the number of triples sum to exactly zero; prints out the time to perform
* the computation.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
In in = new In(args[0]);
int[] a = in.readAllInts();
Stopwatch timer = new Stopwatch();
int count = count(a);
StdOut.println("elapsed time = " + timer.elapsedTime());
StdOut.println(count);
}
}
TwoSumFast O(NlogN)解法
package chapter1_4;
/******************************************************************************
* Compilation: javac TwoSumFast.java
* Execution: java TwoSumFast input.txt
* Dependencies: In.java Stopwatch.java
* Data files: https://algs4.cs.princeton.edu/14analysis/1Kints.txt
* https://algs4.cs.princeton.edu/14analysis/2Kints.txt
* https://algs4.cs.princeton.edu/14analysis/4Kints.txt
* https://algs4.cs.princeton.edu/14analysis/8Kints.txt
* https://algs4.cs.princeton.edu/14analysis/16Kints.txt
* https://algs4.cs.princeton.edu/14analysis/32Kints.txt
* https://algs4.cs.princeton.edu/14analysis/1Mints.txt
*
* A program with n log n running time. Read in n integers
* and counts the number of pairs that sum to exactly 0.
*
* Limitations
* -----------
* - we ignore integer overflow
*
*
* % java TwoSumFast 2Kints.txt
* 2
*
* % java TwoSumFast 1Kints.txt
* 1
*
* % java TwoSumFast 2Kints.txt
* 2
*
* % java TwoSumFast 4Kints.txt
* 3
*
* % java TwoSumFast 8Kints.txt
* 19
*
* % java TwoSumFast 16Kints.txt
* 66
*
* % java TwoSumFast 32Kints.txt
* 273
*
******************************************************************************/
import java.util.Arrays;
public class TwoSumFast {
// print distinct pairs (i, j) such that a[i] + a[j] = 0
public static void printAll(int[] a) {
int n = a.length;
Arrays.sort(a);
if (containsDuplicates(a)) throw new IllegalArgumentException("array contains duplicate integers");
for (int i = 0; i < n; i++) {
int j = Arrays.binarySearch(a, -a[i]);
if (j > i) StdOut.println(a[i] + " " + a[j]);
}
}
// return number of distinct pairs (i, j) such that a[i] + a[j] = 0
public static int count(int[] a) {
int n = a.length;
Arrays.sort(a); //先将数组排序
if (containsDuplicates(a)) throw new IllegalArgumentException("array contains duplicate integers");
int count = 0;
for (int i = 0; i < n; i++) {
int j = Arrays.binarySearch(a, -a[i]); //找到a[i]的负数,说明a[i]+a[j]=0
if (j > i) count++; //要j > i才行,小于i的在之前的for循环已经记录过了。
}
return count;
}
// returns true if the sorted array a[] contains any duplicated integers
private static boolean containsDuplicates(int[] a) {
for (int i = 1; i < a.length; i++)
if (a[i] == a[i-1]) return true;
return false;
}
public static void main(String[] args) {
In in = new In(args[0]);
int[] a = in.readAllInts();
int count = count(a);
StdOut.println(count);
}
}
ThreeSum问题计算数组中3个数相加等于0的组数O(N^2logN)解法
package chapter1_4;
/******************************************************************************
* Compilation: javac ThreeSumFast.java
* Execution: java ThreeSumFast input.txt
* Dependencies: StdOut.java In.java Stopwatch.java
* Data files: https://algs4.cs.princeton.edu/14analysis/1Kints.txt
* https://algs4.cs.princeton.edu/14analysis/2Kints.txt
* https://algs4.cs.princeton.edu/14analysis/4Kints.txt
* https://algs4.cs.princeton.edu/14analysis/8Kints.txt
* https://algs4.cs.princeton.edu/14analysis/16Kints.txt
* https://algs4.cs.princeton.edu/14analysis/32Kints.txt
* https://algs4.cs.princeton.edu/14analysis/1Mints.txt
*
* A program with n^2 log n running time. Reads n integers
* and counts the number of triples that sum to exactly 0.
*
* Limitations
* -----------
* - we ignore integer overflow
* - doesn't handle case when input has duplicates
*
*
* % java ThreeSumFast 1Kints.txt
* 70
*
* % java ThreeSumFast 2Kints.txt
* 528
*
* % java ThreeSumFast 4Kints.txt
* 4039
*
* % java ThreeSumFast 8Kints.txt
* 32074
*
* % java ThreeSumFast 16Kints.txt
* 255181
*
* % java ThreeSumFast 32Kints.txt
* 2052358
*
******************************************************************************/
import java.util.Arrays;
/**
* The {@code ThreeSumFast} class provides static methods for counting
* and printing the number of triples in an array of distinct integers that
* sum to 0 (ignoring integer overflow).
* <p>
* This implementation uses sorting and binary search and takes time
* proportional to n^2 log n, where n is the number of integers.
* <p>
* For additional documentation, see <a href="https://algs4.cs.princeton.edu/14analysis">Section 1.4</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class ThreeSumFast {
// Do not instantiate.
private ThreeSumFast() { }
// returns true if the sorted array a[] contains any duplicated integers
private static boolean containsDuplicates(int[] a) {
for (int i = 1; i < a.length; i++)
if (a[i] == a[i-1]) return true;
return false;
}
/**
* Prints to standard output the (i, j, k) with {@code i < j < k}
* such that {@code a[i] + a[j] + a[k] == 0}.
*
* @param a the array of integers
* @throws IllegalArgumentException if the array contains duplicate integers
*/
public static void printAll(int[] a) {
int n = a.length;
Arrays.sort(a);
if (containsDuplicates(a)) throw new IllegalArgumentException("array contains duplicate integers");
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
int k = Arrays.binarySearch(a, -(a[i] + a[j]));
if (k > j) StdOut.println(a[i] + " " + a[j] + " " + a[k]);
}
}
}
/**
* Returns the number of triples (i, j, k) with {@code i < j < k}
* such that {@code a[i] + a[j] + a[k] == 0}.
*
* @param a the array of integers
* @return the number of triples (i, j, k) with {@code i < j < k}
* such that {@code a[i] + a[j] + a[k] == 0}
*/
public static int count(int[] a) {
int n = a.length;
Arrays.sort(a);
if (containsDuplicates(a)) throw new IllegalArgumentException("array contains duplicate integers");
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
int k = Arrays.binarySearch(a, -(a[i] + a[j]));
if (k > j) count++;
}
}
return count;
}
/**
* Reads in a sequence of distinct integers from a file, specified as a command-line argument;
* counts the number of triples sum to exactly zero; prints out the time to perform
* the computation.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
In in = new In(args[0]);
int[] a = in.readAllInts();
int count = count(a);
StdOut.println(count);
}
}