算法4第1章代码及习题讲解

本文深入讲解了算法基础知识,包括最大公约数的递归与迭代计算方法、二分查找算法、二进制转换、栈的应用如表达式求值、括号匹配、中后缀表达式转换与求值、Josephus问题解决方法、链表与双向链表实现细节、ThreeSum问题的多种解决方案及其复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求最大公约数

计算两个非负整数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);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值