简单算法练习

这篇博客介绍了几个简单的算法练习,包括水仙花数的概念和Java实现,冒泡排序的原理、分析与示例,以及求1-100以内质数的和。通过这些实例,帮助读者理解和应用基础算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单算法练习

一、水仙花数(narcissistic number)

1.问题描述:什么是水仙花数

水仙花数是指一个3位数,它的每个位上的数字的3次幂之和等于他本身(1^3 + 5^3 + 3^3 = 153)。

注意:水仙花数只是`自幂的一种

  1. 一位自幂数:独身数
    2.两位自幂数:没有
    3.三位自幂数:水仙花数
    4.四位自幂数:四叶玫瑰数(四叶玫瑰数是指四位数各位上的数字的四次方之和等于本身的数。)
    5.五位自幂数:五角星数
    6.六位自幂数:六合数
    7.七位自幂数:北斗七星数
    8.八位自幂数:八仙数
    9.九位自幂数:九九重阳数
    10.十位自幂数:十全十美数
2.问题分析

根据水仙花数的定义,判断一个数是否为“水仙花数”,最重要的是要把给出的三位数的个位、十位、百位分别拆分,并求其立方和(设为s),若s与给出的三位数相等, 三位数为“水仙花数”,反之,则不是。

3.算法设计

水仙花数”是指满足某一条件的三位数,根据这一信息可以确定整数的取值范围是 100〜999。对应的循环条件如下:

for(n=100;n<1000;n++)
{
	//......
}

上述代码说明

  • 将n除以100,得出在百位上的数字hundred;
  • 将(n-i*100)整除以10(或将n先整除以10再对10求模n/10%10),得出n在十位数上的数字ten;
  • 将n对10取余,得出n在个位上的数字unit
    求得这三个数字的立方和是否与其本身相等,若相等,则该数为水仙花数
C语言实现
#include <stdio.h>
int main()
{
	int hun, ten, unit,n;
	printf("result is:")
	for(n=100;n<1000;n++)	/*整数的取值范围*/
	{
		hun = n/100;
		ten = n/10%10;
		unit = n%10;
		if(n == hun^3 + ten^3 + unit^3) /*各位上的立方和是否与原数n相等*/
		{
			printf("%d ",n);
		}
	}
	printf("\n");
	return 0;
}
Java实现
/**
 * @Description 水仙花数
 * @Param XXX
 * @Author gfl
 * @Date 2021/3/9
 * @Since 版本 1.1.1
 */
public class NarcissisticNumber {
    public static void main(String[] args){
        for (int i=100;i<1000;i++)
        {
            int a = i/100;     //取得百位数
            int b = i/10%10;   //取得个位数
            int c = i%10;      //取得个位数
            if(i == a*a*a + b*b*b + c*c*c ){
                System.out.println(i + " 这是一个水仙花数");
            }
        }
    }
}

二、冒泡排序(Bubble Sort)

是一种组基础的交换排序。
1.问题描述

将下列的无序数列,从大到小排列;
要排序数组:[10,1,35,61,89,36,55]

2.问题分析

要排序数组:[10,1,35,61,89,36,55]

@1.原理:比较两个相邻的元素,将值大的元素交换到右边
@2.思路:依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面
  1. 第一次比较:首先比较第一和第二个数,将小数放在前面,将大数放在后面。
  2. 比较第2和第3个数,将小数 放在前面,大数放在后面。
        …
  3. 如此继续,知道比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成
  4. 在上面一趟比较完成后,最后一个数一定是数组中最大的一个数,所以在比较第二趟的时候,最后一个数是不参加比较的。
  5. 在第二趟比较完成后,倒数第二个数也一定是数组中倒数第二大数,所以在第三趟的比较中,最后两个数是不参与比较的。
  6. 依次类推,每一趟比较次数减少依次
@3.举例

(1)要排序数组:[10,1,35,61,89,36,55]
在这里插入图片描述
(2)第一趟排序

第一次排序:10和1比较,10大于1,交换位置      [1,10,35,61,89,36,55]

第二趟排序:10和35比较,10小于35,不交换位置  [1,10,35,61,89,36,55]

第三趟排序:35和61比较,35小于61,不交换位置  [1,10,35,61,89,36,55]

第四趟排序:61和89比较,61小于89,不交换位置  [1,10,35,61,89,36,55]

第五趟排序:89和36比较,89大于36,交换位置   [1,10,35,61,36,89,55]

第六趟排序:89和55比较,89大于55,交换位置   [1,10,35,61,36,55,89]

第一趟总共进行了六次比较,排序结果:[1,10,35,61,36,55,89]
在这里插入图片描述
(3)第二趟排序

第一次排序:1和10比较,1小于10,不交换位置  1,10,35,61,36,55,89

第二次排序:10和35比较,10小于35,不交换位置 1,10,35,61,36,55,89

第三次排序:35和61比较,35小于61,不交换位置 1,10,35,61,36,55,89

第四次排序:61和36比较,61大于36,交换位置   1,10,35,36,61,55,89

第五次排序:61和55比较,61大于55,交换位置   1,10,35,36,55,61,89

第二趟总共进行了5次比较,排序结果:1,10,35,36,55,61,89

(4)第三趟排序

第一次排序:1和10比较,1小于10,不交换位置  1,10,35,36,55,61,89`

第二次排序:10和35比较,10小于35,不交换位置 1,10,35,36,55,61,89

第三次排序:35和36比较,35小于36,不交换位置 1,10,35,36,55,61,89

第四次排序:36和61比较,36小于61,不交换位置   1,10,35,36,55,61,89

第三趟总共进行了4次比较,排序结果:1,10,35,36,55,61,89

到目前位置已经为有序的情形了。

算法分析

(1)由此可见:N个数字要排序完成,总共进行N-1趟排序,每i趟的排序次数为(N-i)次,所以可以用双重循环语句,外层控制循环多少趟,内层控制每一趟的循环次数
(2)冒泡排序的优点:
每进行一趟排序,就会少比较一次,因为每进行一趟排序都会找出一个较大值。如上例:第一趟比较之后,排在最后的一个数一定是最大的一个数,第二趟排序的时候,只需要比较除了最后一个数以外的其他的数,同样也能找出一个最大的数排在参与第二趟比较的数后面,第三趟比较的时候,只需要比较除了最后两个数以外的其他的数,以此类推……也就是说,没进行一趟比较,每一趟少比较一次,一定程度上减少了算法的量。
(3)时间复杂度
原始的冒泡排序是稳定的,由于该排序算法的每一轮都要遍历一遍所有的元素,轮转的次数和元素数量相当。所以时间复杂度为O(N^2)
(4)复杂度
时间复杂度: O(N^2)
空间复杂度: O(1)
稳定性:稳定

3.算法设计

/**
 * @Description 冒泡排序
 * @Param XXX
 * @Author gfl
 * @Date 2021/3/9
 * @Since 版本 1.1.1
 */
public class BubbleSortTest {
    public static void main(String[] args){
        int[] arr = {2,21,5,45,4,888,35,10,9,4};
        bubbleSort(arr);
        traverse(arr);
//        System.out.println(arr.length);
    }
    /**
     * 冒泡排序
     * @param arr
     * */
    public static void bubbleSort(int[] arr){
        if(arr==null || arr.length<2){
            return;
        }
        for (int i=0;i<arr.length-1;i++){  //(外循环,第几轮(每一轮求出一个最大值)))数组下标0-9,length=10
            for (int j = 0;j<arr.length-i-1;j++){   //内循环,每一轮的第几次
                if(arr[j]>arr[j+1]){ //数组arr[i]与或和一个元素之间的比较
                    int temp = arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;  //如果当前元素比后一个元素大的话,交换位置
                }
            }
        }
    }
    /**
     * 遍历数组
     * @param  arr
     * */
    public static void traverse(int[] arr){
        if(arr==null || arr.length<2){
            return;
        }
        //for形式循环
//        for(int i=0;i<arr.length-1;i++){
//            System.out.print(arr[i]+"   ");
//        }

        //增强for
//        for(int s:arr){
//            System.out.print(s+"  ");
//        }

        //do...while形式
//        int ii = 0;
//        do{
//            System.out.print(arr[ii]+"  ");
//            ii++;
//        }while(ii<arr.length);

        //while形式
        int g=0;
        while(g<arr.length){
            System.out.print(arr[g]+"  ");
            g++;
        }
    }
}


三、求1-100以内质数的和

指数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

package test;

/**
 * @Description 求1-100中的质数和
 * @Param XXX
 * @Author gfl
 * @Date 2021/3/9
 * @Since 版本 1.1.1
 */
public class PrimeNumber {
    public static void main(String[] args){
        //首先质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数
        //换言说:就是质数只有两个正因数(1和它本身);
        //只要一个数(2除外)除以一个大于等于2且比自身小的数没有正因数,那么它就是一个质数;
    
        int sum = 0;
        for (int i=2;i<=100;i++){       //遍历1-100的数
            Boolean isOK = true;        //默认为质数
            for (int j=2;j<i;j++){      //除数
                if(i%j==0){
                    isOK = false;
                }
            }
            if (isOK){
                System.out.print(i+" ");
                sum+=i;
            }
        }
        System.out.println();
        System.out.println("1~100的质数和为: "+sum);
    }
}

四、二维数组的遍历


/**
 * @Description 二维数组的遍历
 * @Param XXX
 * @Author gfl
 * @Date 2021/3/9
 * @Since 版本 1.1.1
 */
public class TwoDimensionalArray {
    public static void main(String[] args){
//        数据类型[][]数组名称 = new 数据类型[一维数组的个数] [ 每一个一维数组的元素个数 ]
//        int[][] arr = new int[2][3];      //动态初始化方式一
//        int[][] arr = new int[6][];       //动态初始化方式二,一定要设置行数  arr[0]=new int[5]
        int[][] arr = new int[][]{{2,5,6,8,3},{8,9,4},{36,15,8,5}};
//        System.out.println("总共有: "+arr.length+" 行");
//        System.out.println(arr[0].length);
//        System.out.println(arr[1].length);
//        System.out.println(arr[2].length);
        traverse(arr);
    }
    public static void traverse(int[][] arr){
        if(arr==null || arr.length<0){
            return;
        }

        //for循环
//        for(int i = 0;i<arr.length;i++){         //控制行数        i=  0  ,  1  ,  2   arr.length=3
//            for (int j=0;j<arr[i].length;j++){   //一行中有多少个元素j= 0~4 , 0~2 , 0~3  arr[i].length=5,3,4
//                System.out.print(arr[i][j]+"   ");
//            }
//            System.out.println();
//        }

        //增强for
//        for(int[] i:arr){   //行数    i=int[j]
//            for (int j:i) { //每行的元素数
//                System.out.print(j+"\t");
//            }
//            System.out.println();
//        }

        //while形式
//        int i = 0;
//        while(i<arr.length){
//            for (int j = 0;j<arr[i].length;j++){
//                System.out.print(arr[i][j]+"\t");
//            }
//            System.out.println();
//            i++;
//        }

        //do....while形式
        int i = 0;
        do{
            for (int j=0;j<arr[i].length;j++){
                System.out.print(arr[i][j]+"  ");
            }
            System.out.println();
            i++;
        }while(i<arr.length);
    }
}

#include<stdio.h>是在程序编译之前要处理的内容,称为编译预处理命令。编译预处理命令还有很多,它们都以“#”开头,并且不用分号结尾,所以是c语言的程序语句。
在使用标准函数库中的输入输出函数时,编译系统要求程序提供有关的信息(例如对这些输入输出函数的声明),#include<stdio.h>的作用就是用来提供这些信息的,stdio.h是C编译系统提供的一个文件名,stdio是“standard input & output”的缩写,即有关标准输入输出的信息。
在这里的编译预处理命令称为文件包含命令,其作用是在编译之前把程序需要使用的关于系统定义的函数printf()的一些信息文件stdio.h包含进来。以“.h ”作为后缀的文件称为头文件

#include<stdlib.h>是C语言中的一个头文件,stdlib 头文件里包含了C语言的一些函数,该文件包含了的C语言标准库函数的定义。

1、意思是标准输入输出头文件。

2、用到标准输入输出函数时,就要调用这个头文件。

3、stdlib.h中,包含了C语言的一些常用且方便的库函数。

4、如动态内存相关的malloc, realloc,zalloc,calloc,free等。

参考

https://www.toutiao.com/a6593273307280179715/?iid=6593273307280179715

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值