线性表练习之Example013-只用一个变量来求个位数字组成的正整数数组中的最小值

Example013

原文链接:Example013

题目

N 个个位正整数存放在 int 型数组 A[0, …, N-1] 中,N 为已定义的常量且 N≤9,数组 A[] 的长度为 N,另给一个 int 型变量 i,要求只用上述变量(A[0]~A[N-1]i,这 N+1 个整型变量〉写一个算法,找出这 N 个整数中的最小者,并且要求不能破坏数组 A[] 中的数据。

分析

对于普通的寻找数组最小值的方法如下,在方法中会用到两个变量 mini。其中 min 用来记录数组中的最小值,而 i 用来作为循环变量控制循环。

    /**
 * 寻找数组 A 中的最小数
 *
 * @param A 由 N 个个位正整数组成的整型数组
 * @return 得到数组中整数的最小数
 */
public int min(int[]A){
        // 初始时,将数组第一个元素置为最小值
        int min=A[0];
        // 循环数组所有元素
        for(int i=0;i<N; i++){
        // 如果发现数组中有元素比最小值还小
        if(A[i]<min){
        // 那么更新记录最小值的变量,将该数记为最小值
        min=A[i];
        }
        }
        // 返回最小值
        return min;
        }

但现在要求只用一个变量 i,也就是说必须用变量 i 来保存最小值和循环变量控制循环。

从题目中得知数组中元素个数最多为 9 个,并且数组中每个数都是个位数,这就给了我们操作的空间。

我们可以用一个十位数 num([10,99])来完成操作,其中让十位数记录最小值 [1, 9],而个位数记录循环变量 [0, 9]

我们可以利用 num/10 得到十位上的数值,而利用 num%10 得到个位上的数,每次 num%10+1 就可以让循环变量加 1 控制循环。

图解

略。

C实现

核心代码:

/**
 * 求数组中的最小值
 * @param A 指定数组
 * @return 最小值
 */
int min(int A[]) {
    // 十位记录最小值,个位记录循环变量
    int i = A[0] * 10 + 0;// 其中 0 就表示循环变量,而A[0]表示临时最小值,乘以 10 是因为它表示十位
    // 其中 i%10 就得到个位数,即循环变量
    while (i % 10 < N) {
        // i/10 可以得到十位数,即记录的最小值,通过 A[i%10] 就相当于 A[0]、A[1] 访问数组中对应下标的值,然后比较大小
        if (i / 10 > A[i % 10]) {
            // 如果该数比记录的最小值还要小,那么就更新变量 i,更新 i 的十位为新的最小值,并且也要更新循环变量,继续数组中的下一个元素
            // A[i%10]就是新的十位,而乘以 10 是让它成为一个两位数,i%10 是获取原来的个位数
            i = A[i % 10] * 10 + i % 10;
        }
        // 加 1 就是让个位数加1,就是新的循环变量,等价于原来的 i++
        i += 1;
    }
    // 返回最小值,要除以 10 才能得到十位数表示的最小值
    return i / 10;
}

完整代码:

#include <stdio.h>

#define N 8

/**
 * 求数组中的最小值
 * @param A 指定数组
 * @return 最小值
 */
int min(int A[]) {
    // 十位记录最小值,个位记录循环变量
    int i = A[0] * 10 + 0;// 其中 0 就表示循环变量,而A[0]表示临时最小值,乘以 10 是因为它表示十位
    // 其中 i%10 就得到个位数,即循环变量
    while (i % 10 < N) {
        // i/10 可以得到十位数,即记录的最小值,通过 A[i%10] 就相当于 A[0]、A[1] 访问数组中对应下标的值,然后比较大小
        if (i / 10 > A[i % 10]) {
            // 如果该数比记录的最小值还要小,那么就更新变量 i,更新 i 的十位为新的最小值,并且也要更新循环变量,继续数组中的下一个元素
            // A[i%10]就是新的十位,而乘以 10 是让它成为一个两位数,i%10 是获取原来的个位数
            i = A[i % 10] * 10 + i % 10;
        }
        // 加 1 就是让个位数加1,就是新的循环变量,等价于原来的 i++
        i += 1;
    }
    // 返回最小值,要除以 10 才能得到十位数表示的最小值
    return i / 10;
}

int main() {
    int A[] = {2, 4, 6, 1, 5, 3, 7, 8};

    // 调用函数
    int m = min(A);
    printf("最小值:%d", m);
}

执行结果:

最小值:1

事实上,书上的写法是利用 i 的十位上的数字作为循环变量,将 i 的个位上的数字来代替题目中的 min 的功能,而利用 i%10 取得 i 个位上的数字,i/10 取得 i 十位上的数字。代码如下:

void min(int A[], int &i) {// 用 i 来保存最小值
	i=A[0];// i先保存存入A[0]的值
	while(i/10<=N-1) { // 取 i 的十位上的数字作为循环变量,与 N-1 作比较
		if(i%10>A[i/10]) { // 取 i 的个位上的数字与 A[i/10] 中的各数值比较
			i=i-i%10;// 如果 i 的个位上的数字大于 A[I/10] 中数字
			i=i+A[i/10];// 则将 i 的个位上的数字换成 A[I/10]
		}
		i=i+10;// i 的十位上的数字加 1,即对 A[] 中的下一个数字进行检测
	}
	i=i%10;// 循环结束后,i 的个位上的数字保存了 A[] 中的最小值,将 i 更新为 i 的个位上的数字
}

Java实现

核心代码:

    /**
 * 求数组 A 中的最小值
 *
 * @param A 全是个位正整数的数组
 * @return 数组中的最小值
 */
public int min(int[]A){
        // 十位记录最小值,个位记录循环变量
        int i=A[0]*10+0;// 其中 0 就表示循环变量,而A[0]表示临时最小值,乘以 10 是因为它表示十位
        // 其中 i%10 就得到个位数,即循环变量
        while((i%10)<N){
        // i/10 可以得到十位数,即记录的最小值,通过 A[i%10] 就相当于 A[0]、A[1] 访问数组中对应下标的值,然后比较大小
        if((i/10)>A[i%10]){
        // 如果该数比记录的最小值还要小,那么就更新变量 i,更新 i 的十位为新的最小值,并且也要更新循环变量,继续数组中的下一个元素
        // A[i%10]就是新的十位,而乘以 10 是让它成为一个两位数,i%10 是获取原来的个位数
        i=A[i%10]*10+(i%10);
        }
        // 加 1 就是让个位数加1,就是新的循环变量,等价于原来的 i++
        i+=1;
        }
        // 返回最小值,要除以 10 才能得到十位数表示的最小值
        return i/10;
        }

完整代码:

public class SeqList {
    private final int N = 8;

    /**
     * 求数组 A 中的最小值
     *
     * @param A 全是个位正整数的数组
     * @return 数组中的最小值
     */
    public int min(int[] A) {
        // 十位记录最小值,个位记录循环变量
        int i = A[0] * 10 + 0;// 其中 0 就表示循环变量,而A[0]表示临时最小值,乘以 10 是因为它表示十位
        // 其中 i%10 就得到个位数,即循环变量
        while ((i % 10) < N) {
            // i/10 可以得到十位数,即记录的最小值,通过 A[i%10] 就相当于 A[0]、A[1] 访问数组中对应下标的值,然后比较大小
            if ((i / 10) > A[i % 10]) {
                // 如果该数比记录的最小值还要小,那么就更新变量 i,更新 i 的十位为新的最小值,并且也要更新循环变量,继续数组中的下一个元素
                // A[i%10]就是新的十位,而乘以 10 是让它成为一个两位数,i%10 是获取原来的个位数
                i = A[i % 10] * 10 + (i % 10);
            }
            // 加 1 就是让个位数加1,就是新的循环变量,等价于原来的 i++
            i += 1;
        }
        // 返回最小值,要除以 10 才能得到十位数表示的最小值
        return i / 10;
    }
}

测试代码:

public class SeqListTest {
    public static void main(String[] args) {
        SeqList list = new SeqList();
        int[] A = new int[]{2, 4, 3, 5, 7, 1, 6, 8};

        int min = list.min(A);
        System.out.println("最小值:" + min);
    }
}

执行结果:

最小值:1
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值