第一章课后的几个编程题——数据结构与问题描述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));
    }
}
1.1 单项选择题 1. 数据结构是一门研究非数值计算的程序设计问题中,数据元素的① 、数据信息在计算机中的② 以及一组相关的运算等的课程。 ① A.操作对象   B.计算方法  C.逻辑结构  D.数据映象 ② A.存储结构 B.关系 C.运算 D.算法 2. 数据结构DS(Data Struct)可以被形式地定义为DS=(D,R),其中D是① 的有限集合,R是D上的② 有限集合。 ① A.算法 B.数据元素 C.数据操作 D.数据对象 ② A.操作 B.映象 C.存储 D.关系 3. 在数据结构中,从逻辑上可以把数据结构分成 。 A.动态结构和静态结构 B.紧凑结构和非紧凑结构 C.线性结构和非线性结构 D.内部结构和外部结构 4. 算法分析的目的是① ,算法分析的两个主要方面是② 。 ① A. 找出数据结构的合理性 B. 研究算法中的输入和输出的关系 C. 分析算法的效率以求改进 D. 分析算法的易懂性和文档性 ② A. 空间复杂性和时间复杂性 B. 正确性和简明性 C. 可读性和文档性 D. 数据复杂性和程序复杂性 5. 计算机算法指的是① ,它必具备输入、输出和② 等五个特性。 ① A. 计算方法 B. 排序方法 C. 解决问题的有限运算序列 D. 调度方法 ② A. 可行性、可移植性和可扩充性 B. 可行性、确定性和有穷性 C. 确定性、有穷性和稳定性 D. 易读性、稳定性和安全性 1.2 填空题(将正确的答案填在相应的空中) 1. 数据逻辑结构包括 、 、 和 四种类型,树形结构和图形结构合称为 。 2. 在线性结构中,第一个结点 前驱结点,其余每个结点有且只有 个前驱结点;最后一个结点 后续结点,其余每个结点有且只有 个后续结点。 3. 在树形结构中,树根结点没有 结点,其余每个结点有且只有 个直接前驱结点,叶子结点没有 结点,其余每个结点的直接后续结点可以 。 4. 在图形结构中,每个结点的前驱结点数和后续结点数可以 。 5. 线性结构中元素之间存在 关系,树形结构中元素之间存在 关系,图形结构中元素之间存在 关系。 6. 算法的五个重要特性是__ __ , __ __ , ___ _ , __ __ , _ ___。 7. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 for (i=0;i<n;i++) for (j=0;j<n; j++) A[i][j]=0; 8. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 for (i=0;i<n;i++) for (j=0; j<i; j++) A[i][j]=0; 9. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 s=0; for (i=0;i<n;i++) for (j=0;j<n;j++) for (k=0;k<n;k++) s=s+B[i][j][k]; sum=s; 10. 分析下面算法(程序段)给出最大语句频度 ,该算法的时间复杂度是__ __。 int i=0,s=0; while (s<n) { i++; s+=i; //s=s+i } 11. 分析下面算法(程序段)给出最大语句频度 ,该算法的时间复杂度是__ __。 i=1; while (i<=n) i=i*2;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值