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 

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

相关推荐
paterWang1 小时前
基于 Python 和 OpenCV 的酒店客房入侵检测系统设计与实现
开发语言·python·opencv
东方佑1 小时前
使用Python和OpenCV实现图像像素压缩与解压
开发语言·python·opencv
我真不会起名字啊2 小时前
“深入浅出”系列之杂谈篇:(3)Qt5和Qt6该学哪个?
开发语言·qt
laimaxgg2 小时前
Qt常用控件之单选按钮QRadioButton
开发语言·c++·qt·ui·qt5
水瓶丫头站住2 小时前
Qt的QStackedWidget样式设置
开发语言·qt
尼尔森系3 小时前
排序与算法:希尔排序
c语言·算法·排序算法
小钊(求职中)3 小时前
Java开发实习面试笔试题(含答案)
java·开发语言·spring boot·spring·面试·tomcat·maven
GEEK.攻城狮4 小时前
使用VSCODE开发C语言程序
c语言·ide·vscode
慕诗客5 小时前
QT基于Gstreamer采集的简单示例
开发语言·qt
Blasit5 小时前
C++ Qt建立一个HTTP服务器
服务器·开发语言·c++·qt·http