C语言实例_1之从4个不重复的数中,找出3个不重复的数的集合

题目

有 1、2、3、4 四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

分析

可填在百位、十位、个位的数字都是 1、2、3、4,组成所有的排列后再去掉不满足条件的排列。

实例代码

cpp 复制代码
#include<stdio.h>
// 程序入口 
int main()
{
	// [0] 定义了三个整型变量 `i`、`j` 和 `k`,它们将分别用于表示三位数的百位、十位和个位上的数字
    int i = 0;
    int j = i;
    int k = i;
    // [0]
    // [1] 输出`换行`
    printf("\n");
    // [1]
    // [2] 以下为三重循环
    // [3] 遍历百位上可能出现的数字,从 `1` 开始,到 `4` 结束(因为题目给定的数字是 `1`、`2`、`3`、`4`),每次循环 `i` 的值都会改变,代表不同的百位数字
    for(i = 1; i < 5; i++) { 
        // [4] 遍历十位上可能出现的数字,同样是从 `1` 到 `4`
        for(j = 1; j < 5; j++) {
            // [5] 遍历个位上可能出现的数字,同样是从 `1` 到 `4`
            for (k = 1; k < 5; k++) {
            	// [6] 确保i、j、k三位数互不相同
                if ( (i!=k) && (i!=j) && (j!=k) ) { 
                	// [7] `printf` 函数中的 `%d%d%d ` 是格式化输出的占位符,分别对应 `i`、`j`、`k` 这三个变量的值,输出时会按照顺序将它们组成一个三位数并打印出来,每个三位数后面跟着一个空格
                    printf("%d,%d,%d ", i, j, k);
                    // [7]
                }
                // [6]
            }
            // [5]
        }
        // [4]
    }
    // [3]
    // [2]
    // 程序正常结束
    return 0;
}

以上实例代码存在以下两点可优化的方面:

  • 1.存在多余比较 :在最内层的循环判断条件中,每次都要进行三次比较(i!=k) && (i!=j) && (j!=k)来确保三个数字互不相同。实际上,在外层循环已经对百位和十位数字做了一定的限制(比如百位从14依次取值,十位在每次百位确定后也从14取值且与百位不同),所以到内层判断个位数字时,有些比较是多余的。例如,当百位是1,十位是2时,在判断个位数字时其实只需要判断个位数字不等于1且不等于2即可,而不需要再判断十位不等于百位这种已经确定的情况,这会导致一些不必要的计算开销,尤其在处理更复杂的数字组合或数字范围更大时,这种多余的比较可能会累积影响效率。
  • 2.未利用已有条件优化循环范围 :在每个循环中,都是从14进行完整的遍历。可以考虑根据前面已经确定的数字来缩小后续循环的范围,比如十位数字的循环可以从百位数字+1开始(确保与百位不同且能减少循环次数),个位数字的循环也可以根据百位和十位数字进一步优化范围,这样能减少不必要的循环迭代次数,从而提高运行效率。

优化方法1之减少不必要的循环次数

在实例代码中,内层循环每次都要从 1 遍历到 4,即使前面已经确定了百位和十位数字,有些情况是可以提前判断并跳过不必要的循环的。

十位数字的循环从 i + 1 开始,这样就避免了重复判断十位数字等于百位数字的情况,减少了一些不必要的循环次数。

cpp 复制代码
#include <stdio.h>

int main() {
    int i, j, k;

    // 百位数字的循环
    for (i = 1; i < 5; i++) {
        // 十位数字的循环,注意要和百位数字不同
        for (j = 1; j < 5; j++) {
            if (j!= i) {
                // 个位数字的循环,要和百位、十位数字都不同
                for (k = 1; k < 5; k++) {
                    if (k!= i && k!= j) {
                        // 输出满足条件的三位数
                        printf("%d%d%d ", i, j, k);
                    }
                }
            }
        }
    }

    return 0;
}

优化方法2之使用位运算进行标记

利用位运算来标记已经使用过的数字,从而快速判断是否满足无重复数字的条件。

通过位运算来快速判断数字是否已经被使用过,相比于原始代码中的多次条件判断,在某些情况下可能会提高执行效率,尤其是当需要处理的数字范围较大且重复判断较多时,位运算的优势会更加明显。不过这种方法相对来说理解起来可能会稍微复杂一些。

cpp 复制代码
#include <stdio.h>

int main() {
    int i, j, k;

    // 百位数字的循环,从1到4
    for (i = 1; i < 5; i++) {
        // 使用位运算标记百位数字已经被使用
        int used = 1 << (i - 1);

        // 十位数字的循环,从1到4
        for (j = 1; j < 5; j++) {
            // 如果十位数字未被使用(通过位运算判断)
            if (!(used & (1 << (j - 1)))) {
                // 更新位标记,表示十位数字也被使用了
                used |= (1 << (j - 1));

                // 个位数字的循环,从1到4
                for (k = 1; k < 5; k++) {
                    // 如果个位数字未被使用(通过位运算判断)
                    if (!(used & (1 << (k - 1)))) {
                        // 输出满足条件的三位数
                        printf("%d%d%d ", i, j, k);
                    }
                }

                // 清除十位数字的位标记,以便下一次十位数字循环时重新判断
                used &= ~(1 << (j - 1));
            }
        }
    }

    return 0;
}

输出结果

cpp 复制代码
123 124 132 134 142 143 213 214 231 234 241 243 312 314 321 324 341 342 412 413 421 423 431 432 

高价出售本人脑子没有用过有意者私。

相关推荐
zmzb01031 小时前
C++课后习题训练记录Day98
开发语言·c++
猫头虎2 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
YUJIANYUE3 小时前
PHP纹路验证码
开发语言·php
仟濹3 小时前
【Java基础】多态 | 打卡day2
java·开发语言
孞㐑¥3 小时前
算法——BFS
开发语言·c++·经验分享·笔记·算法
Re.不晚3 小时前
JAVA进阶之路——无奖问答挑战2
java·开发语言
八零后琐话3 小时前
干货:程序员必备性能分析工具——Arthas火焰图
开发语言·python
3GPP仿真实验室3 小时前
【MATLAB源码】CORDIC-QR :基于Cordic硬件级矩阵QR分解
开发语言·matlab·矩阵
知南x3 小时前
【Ascend C系列课程(高级)】(1) 算子调试+调优
c语言·开发语言
忆~遂愿3 小时前
GE 引擎与算子版本控制:确保前向兼容性与图重写策略的稳定性
大数据·开发语言·docker