算法------编程珠玑(ProgrammingPeals)第四章习题(JAVA)

package code_04_chapter;

import java.math.BigDecimal;

/*
 *Created by William on 2018/6/19 0019
 */
public class QuestionsInChapter4 {
    static int[] ints = new int[10];

    public QuestionsInChapter4() {
        for (int i = 0; i < 10; i++) {
            ints[i] = i;
        }
        ints[9] = 8;
        ints[7] = 8;
    }

    /**
     * 二分搜索
     */
    public int binarySearch(int[] ints, int searchNumber) {
        int left = 0;
        int right = ints.length;
        int middle;
        while (left < right) {
            middle = (right + left) / 2;
            if (ints[middle] == searchNumber) return middle;
            if (ints[middle] < searchNumber) left = middle + 1;
            if (ints[middle] > searchNumber) right = middle - 1;
        }
        return -1;
    }

    public static void main(String[] args) {
        QuestionsInChapter4 questionsInChapter4 = new QuestionsInChapter4();
        System.out.println(questionsInChapter4.binarySearch(ints, 8));
    }

    /**
     * Q2:
     * 返回searchNumber在数组ints中第一次出现的位置。有可能t在数组中出现多次
     */
    static class Q2 {
        public int binarySearch2(int[] ints, int searchNumber) {
            int left = 0;
            int right = ints.length;
            int middle = 0;
            int temp;
            while (left < right) {
                middle = (left + right) / 2;
                if (ints[middle] == searchNumber) {
                    temp = middle;
                    while (ints[temp] == ints[middle]) {
                        temp--;
                    }
                    return temp + 1;
                }
                if (ints[middle] < searchNumber) left = middle + 1;
                if (ints[middle] > searchNumber) right = middle - 1;
            }
            return -1;
        }

        public static void main(String[] args) {
            QuestionsInChapter4 questionsInChapter4 = new QuestionsInChapter4();
            Q2 q2 = new Q2();
            System.out.println(q2.binarySearch2(ints, 8));
        }
    }

    /**
     * Q3:
     * 递归法写二分搜索
     */
    static class Q3 {
        public int binarySearch(int[] ints, int left, int right, int searchNumber) {
            if (left > right) return -1;
            int middle = (left + right) / 2;
            if (ints[middle] == searchNumber) return middle;
            if (ints[middle] < searchNumber) return binarySearch(ints, middle + 1, right, searchNumber);
            if (ints[middle] > searchNumber) return binarySearch(ints, left, middle - 1, searchNumber);
            return -1;
        }

        public static void main(String[] args) {
            QuestionsInChapter4 questionsInChapter4 = new QuestionsInChapter4();
            Q3 q3 = new Q3();
            System.out.println(q3.binarySearch(ints, 0, ints.length, 8));
        }
    }

    /**
     * Q6:
     * 选豆子问题,本题比较简单,基本思路如下:
     * 首先假设黑白豆子的数量分别是black,white有三种情况:
     * [1]颜色相同且都是白色豆子:      white -2 , black + 1;  (white >= 2)
     * [2]颜色相同且都是黑色豆子:      black -1;
     * [3]颜色不同:     black - 1;     (white >=1; black >= 1)
     *
     * 由上方可知,豆子每次都是减少一颗,所以该过程一定会终止,最后剩下一颗;
     * 由上方可知,白色豆子的减少是偶数的,所以:
     * [1]存在白色豆子的数量是奇数时,最后剩下的豆子一定是白色的;
     * [2]存在白色豆子的数量是偶数时,最后剩下的豆子一定是黑色的;
     * [3]不存在白色豆子时,最后剩下的豆子一定是黑色的;
     */

    /**
     * Q7:
     * 确定两条线段,还是二分搜索的思想,只是比较的过程发生了变化。
     * 将相邻线段组成的区间作为一个元素,进行二分查找!
     * y = a x + b
     *
     * 解题思路如下:
     * 构成梯级的线段在y方向上是递增的,因此我们可以通过二分搜索来找到包含给定点的两条线段。
     * 搜索中的基本比较说明了点在给定线段的下方,里面还是上方。
     */

    /**
     * Q8:
     * 本书9.3节,改进二分搜索
     * 返回第一个查找的字母的位置,只有一次判断,非常高效
     */
    static class Q8{
        public int binarySearch(int[] ints, int searchNumber) {
            int left = 0;
            int right = ints.length;
            int halfLength;
            int middle;
            int len = right - left;
            while (len > 0) {
                halfLength = len >> 1;
                middle = left + halfLength;
                if(ints[middle] < searchNumber){
                    left = middle + 1;
                    len = len - halfLength -1;
                }else len = halfLength;
            }
            if(left >= ints.length || ints[left] != searchNumber ) return -1;
            return left;
        }
        public static void main(String[] args) {
            QuestionsInChapter4 questionsInChapter4 = new QuestionsInChapter4();
            Q8 q8 = new Q8();
            System.out.println(q8.binarySearch(ints, 8));
        }
    }

    /**
     * Q9:
     * (1)两个n维的向量相加。初开始时:i=0表示前i个维度的都已经计算好了。在循环之中,
     * 计算一个维度,然后i加一,计算下一个维度,每个循环结束表明前i个维度已经计算完毕。
     * i一直在增大,证明这个过程是可以终止的。当最后一个循环执行完毕的时候,i的值是n,
     * 表明前n个维度已经计算好了。所以其代码是正确的。
     * (2)求x数组的最大值。初开始时候,max=x[0]表示最大值是第一个数,i=1表示前i个数的最大值已经求出。
     * 每次循环时候,如果有比max大的数,就替换,当循环结束时候,前i个数的最大值就知道了。
     * 当整个过程结束时,i==n,所以前n个数的最大值可以求出。
     * (3)当循环找个一个t的时候,就停止循环,或者当i超出范围的时候停止。i在每一次循环的时候值都增加,
     * 所以这个算法是可以结束的。当超出范围的时候,返回-1,否则返回的就是第一次出现的位置,
     * 因为i的值是从小到大递增的。
     * (4)每次递归,问题的规模都是缩小的,所以问题可以在有限步骤内结束。
     * 每次递归完成一次,就可以得到上次层想要的运算结果,接着向上传递。
     */
}

猜你喜欢

转载自blog.csdn.net/weianluo/article/details/80738870