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 

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

相关推荐
古希腊掌管学习的神17 分钟前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
赵钰老师17 分钟前
【R语言遥感技术】“R+遥感”的水环境综合评价方法
开发语言·数据分析·r语言
就爱学编程25 分钟前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
emoji1111111 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
每天都要学信号1 小时前
Python(第一天)
开发语言·python
TENET信条1 小时前
day53 第十一章:图论part04
开发语言·c#·图论
北国无红豆1 小时前
【CAN总线】STM32的CAN外设
c语言·stm32·嵌入式硬件
生信圆桌1 小时前
【生信圆桌x教程系列】如何安装 seurat V5版本R包,最详细安装手册
开发语言·r语言
IT猿手1 小时前
最新高性能多目标优化算法:多目标麋鹿优化算法(MOEHO)求解TP1-TP10及工程应用---盘式制动器设计,提供完整MATLAB代码
开发语言·深度学习·算法·机器学习·matlab·多目标算法