第一章课后的几个编程题——数据结构与问题描述Java语言描述(第3版)

Page 25

实践题1.24

题目描述:素数除了1和它本身没有其他因子(1不是素数,最小素数是2)
问题1. 写一个程序判断正整数N是不是素数?
问题2. 如果N是一个非常大的整数,如何判断?

// 实践题1.24问题1答案
public static boolean isPrime(int num) {
        boolean flag = true;
        if (num <= 1) {
            flag = false;
        }else {
            for (int i = 2; i < num; i++) { // 循环条件可优化为 i <= Math.sqrt(num)
                if (num % i == 0) {
                    flag = false;
                }
            }
        }
        return flag;
    }

问题2解析:
如何判定一个大整数是否为素数

// 实践题1.24问题2答案
// 正在研究解决方案

实践题1.26

题目描述:对于一个规模为N的数组,如果有一个元素出现大于N/2次,则称其为过半元素,因此一个数组中最多只有一个过半元素。
问题:给出一个算法,如果数组中存在过半元素的话就找出来,如果不存在,则给出报告。

// 实践题1.26答案:该算法对存在过半元素的数组有效;对不存在过半元素的数组无效,无法给出报告。
public class FindOverHalfNumber {
    public static int findTheNumber(int[] array) {
        int length = array.length;
        int theNumber = array[0];
        int thisTime = 0; // 标记次数
        for (int i = 0; i < length; i++) {
            if (thisTime == 0) {
                theNumber = array[i];
                thisTime++; 
            } else {
                if (array[i] == theNumber) { // 与前一个数相同则标记次数加一
                    thisTime++;
                } else { // 与前一个数不同则标记次数减一
                    thisTime--;
                }
            }
        }
        return theNumber;
    }

    public static void main(String[] args) {
        int[] array = {
    1,0,1,2,3,1,1,3};           System.out.println(FindOverHalfNumber.findTheNumber(array));
    }
}

实践题1.27

题目描述:输入是一个N*N的矩阵,可以完全放到内存中,每行从左至右递增,每列从上至下递增,给出一个算法判断X是否在这个矩阵里。

暴力查找:遍历矩阵,我就不贴代码了。
二分查找:先从矩阵开始从上到下二分查找X所在的行,再在该行查找X,存在返回true,不存在则返回false

// 实践题1.27答案(二分查找)
// array is two_dimension array which has N lines and N columns
public static boolean findNumber(int[][] array, int number) {
    int lineStart = 0;
    int lineEnd = array.length-1;
    int columnStart = 0;
    int columnEnd = array[0].length-1;
    int lineMid = 0;
    boolean flag = false;
    // 先寻找目标元素所在的行,start==end时停止,找到该行
    while (lineStart < lineEnd) {
        lineMid = (lineStart + lineEnd)/2; // 中间行
        if (number == array[lineMid][0]) {
            flag = true;
            break;
        } else if (number < array[lineMid][0]) {
            lineEnd = lineMid -1;  // 行首元素在行首最小
        } else if(number >= array[lineMid][0] && number < array[lineMid+1][0]){
            lineStart = lineMid;
            break; //找到该行
        } else {
            lineStart = lineMid + 1; 
        }
    }
    // 再查找目标元素的列
    if (flag == false) {
        int resultLine = lineStart;
        int columnMid = 0;
        while (columnStart <= columnEnd) {
            columnMid = (columnStart + columnEnd)/2;
            if (number < array[resultLine][columnMid]) {
                columnEnd = columnMid-1; 
            } else if(number > array[resultLine][columnMid]){
                columnStart = columnMid+1;
            } else {
                flag = true;
                break;
            }
        }
    }
    return flag;
}

根据矩阵性质进行优化:从上至下递增,从左至右递增。从矩阵最后一行第一个元素开始查找(该元素在所在行最小在所在列最大),小于目标数X则在该行向右查找,大于目标数X则在该列向上查找,直到找到X或到达第一行最后一列为止。

// 实践题1.27答案,最优解
public static boolean findNumber2(int[][] array, int number) {
    int lineNum = array.length;
    int columnNum = array[0].length;
    boolean flag = false;
    for (int i = lineNum-1, j = 0; i >= 0 && j < columnNum;) {
        if (array[i][j] == number) {
            flag = true;
            break;
        } else if (array[i][j] < number) {
            j++;
        } else {
            i--;
        }
    }
    return flag;
}

实践题1.28

问题描述:设计一个有效算法,将一个正整数类型的数组array作为输入,并计算:
1. 对于j >= i,array[j] + array[i]的最大值
2. 对于j >= i,array[j] - array[i]的最大值
3. 对于j >= i,array[j] * array[i]的最大值
4. 对于j >= i,array[j] / array[i]的最大值

// 实践题1.26答案
public class ArrayUtils {
    // 问题1:寻找两个最大的数
    public static int maxSumOfTwoEle(int[] array) {
        int max = 0;
        int preMax = 0;
        if (array[0] > array[1]) {
            max = array[0];
            preMax = array[1];
        } else {
            max = array[1];
            preMax = array[0];
        }

        for (int i = 2; i < array.length; i++) {
            if (array[i] >= max) {
                preMax = max;
                max = array[i];
            } else if (array[i] < max && array[i] >= preMax) {
                preMax = array[i];
            }
        }
        return max+preMax;
    }

    // 问题2:寻找最大的数和最小的数(不合题意,正在努力修改中...)
    public static int maxDifferenceOfTwoEle(int[] array) {
        int max = 0;
        int min = 0;
        if (array[0] > array[1]) {
            max = array[0];
            min = array[1];
        } else {
            max = array[1];
            min = array[0];
        }

        for (int i = 2; i < array.length; i++) {
            if (array[i] > max) {
                max = array[i];
            } else if (array[i] < min) {
                min = array[i];
            }
        }
        return max-min;
    }

    public static void main(String[] args) {
        int[] array = {-1,-2,-3,-4,-5,-6,-7,7,6,5,4,3,2,1};
      System.out.println(ArrayUtils.maxSumOfTwoEle(array));
    System.out.println(ArrayUtils.maxDifferenceOfTwoEle(array));
    }
}

程序设计题1.29

问题描述:埃拉托色尼筛子是一种用来计算所有小于等于N的素数的方法,写一个程序实现该算法。
算法思想:先建立一个从整数2到N的表格,从表格中选出最小的质数2开始,计数器加一,然后删去表格中2的倍数,再从表格中选出最小的质数3,计数器加一,然后删去表格中3的倍数,再依次选出最小的质数,计数器加一,删去其倍数,直到该质数(记为j)的平方刚好大于N为止,最后再计算表格中j之后的质数个数加到计数器中即可,该计数器即为所求。

public class FilterPrime {
    public static int filter(int number) {
        BitSet b = new BitSet(number + 1);
        int count = 0; 
        int i = 2; // 设置BitSet:每一位代表true或false,节省空间
        int j = 2; // 寻找质数的倍数
        for ( ; i <= number; i++){
            b.set(i);
        }
        while (j * j <= number) {
            if (b.get(j)) {
    // 如果该位是质数
                count++;
                int k = 2 * j;
                while (k <= number) {
                    b.clear(k);
                    k += j;// k是i的倍数,将第k位移除
                }
            }
            j++;
        }
        while (j <= number) {
    // 计算sqrt(number)后面的数
            if (b.get(j))
                count++;
            j++;
        }
        return count;
    }

    public static void main(String[] args) {
        System.out.println(FilterPrime.filter(5));
    }
}

你可能感兴趣的:(默认,算法,java,编程,算法)