算法(1)

一、数组循环移位算法

设计一个算法,把一个含有 N 个元素的数组循环右移 K 位,要求时间复杂度为

ON),且只允许使用两个附加变量。

(1)问题:什么时数组循环移位呢?

比如,A={1,2,3,4}循环右移1位,结果为,4,1,2,3

A循环右移两位结果为,3,4,1,2

(2)如何实现?

如果移动1位,我们容易想到,将最后一个元素先存起来,然后将其余元素后移一位,再将之前存起来的元素放入第一个位置

移动两位,将倒数第1个存起来,其余元素移动两位,再将之前存起来的元素放入第一个位置

      (下面都是从初始状态进行的移动)

初始1234
m14123
m23412
m32341
m41234
void rightShift(int* arr, int n, int k)
{	int i;
	while(k--)
	{
	int t = arr[n-1];
	for( i = n-1; i > 0; i--)
	arr[i] = arr[i-1];
	arr[0] = t;	 
	 }
}

右移k位,比如要移动2位,先移动一位一次,然后在移动一位一次。(k--的作用)

(3)如何达到题目要求
上面的解法比较简单,但是达不到题目的复杂度要求。

比如 12345abcde,向右移 4 个位置后变为 bcde12345a, bcde 12345a 顺序都不

变,仔细观察后,可以这样处理:

(1)12345a 反转得 a54321

(2) bcde 反转得 edcb,此时数组 a54321edcb

(3) 再反转 bcde12345a;复杂度 O(N)

关键:逆序代码,比如A={1,2,3,4},5对应数组下标为0,1,2,3

设temp,temp=A[0]=1,A[0]=A[3]=4,A[3]=temp=1    结果为  4,2,3,1

             temp=A[1]=2,A[1]=A[2]=3,A[3]=temp=2    结果为  4,3,2,1

#include<stdio.h>
void reverse(int*arr,int begin,int end)
{
for( ; begin<end; begin++, end--) //实现逆序
{
	int temp=arr[begin];
	arr[begin]=arr[end];
	arr[end]=temp;
}
}
void rightShift1(int* arr,int k,int n)
{
k%=n;
reverse(arr,0,n-k-1);
reverse(arr,n-k,n-1);
reverse(arr,0,n-1);
}

void rightShift2(int* arr, int n, int k)
{	int i;
	while(k--)
	{
	int t = arr[n-1];
	for( i = n-1; i > 0; i--)
	arr[i] = arr[i-1];
	arr[0] = t;
	 
	 }
}
void Print(int arr[],int n){
	int i;
	for(i=0;i<n;i++){
	printf("%d ",arr[i]);	
	}	
}
int main()
{ 	int A[]={1,2,3,4};
	int B[]={1,2,3,4,5,6,7,8,9,10}; 
 	int l1=sizeof(A)/sizeof(A[0]);
 	int l2=sizeof(B)/sizeof(B[0]);
	rightShift2(A,l1,1);
	printf("方法1:\n");
	Print(A,l1);
	printf("\n");
	rightShift2(B,l2,5);
	printf("方法2:\n");
	Print(B,l2);	
 	return 0;
}

二、实现矩阵转置

(1)问题分析

矩阵转置,把矩阵的行环成同序数的列得到新矩阵,如下图对角线

观察可得,(aij代表位置)即为a12与与a21互换,a13与与a31互换,a23与a32互换

实质为交换:设temp,temp=A[i][j], A[i][j]=A[j][i],A[j][i]=temp

(2)实现

此处设立一个数组来存储转置矩  ↵

示例:

i=0,

j=0 ,  temp[0] [0]=arr[0][0] ,

j=1, temp[0] [1]=arr1][0] ,

j=2, temp[0] [2]=arr[2][0] ,

#include<stdio.h>
#define row 3
#define col 3
void Tran(int arr[row][col]){
	int i,j,temp[row][col];
	for(i=0;i<col;i++){
		for(j=0;j<row;j++)
			temp[i][j]=arr[j][i];
	}
	//打印转置后的数组 
	for(i=0;i<row;i++){
		for(j=0;j<col;j++){
			printf("%d ",temp[i][j]);
			}
		printf("\n");	
		}		
}
int main(void){
	int arr[row][col]={{3,4,5},{7,6,5},{1,2,4}};
	Tran(arr);
}

三、完数

编程实现给出指定整数范围  【a,b】内的所有完数,一个数恰好等于除它本身外的所有因子和,此数称为完数,例如6=1+2+3

(1)分析

因子和,则需求出因子,6%1=0,6%2=0,6%3=0,6%4!=0,6%5!=0,因子和1+2+3=6

一层循环指定遍历区间

二层循环求因子和,1为任何数的因子,从2开始到指定范围

if语句判断是否为完数

(2)实现

#include<stdio.h>
void FindWS(int begin,int end){
	int i,j,temp;
	for(i=begin+1;i<end;++i)
	{	temp=1;
		for(j=2;j<i;++j){
		if(i%j==0){
			temp=temp+j;
			}
		}
		if(temp==i){
		printf("%d\n",i);
		}
	}
}
int main(void){
	FindWS(2,30);	 
}

四、压缩字符串

对于字符串中连续出现的同一字符,用该字符加上连续出现的次数来表示(连续出现次数小于3的不压缩)

   设计程序将采用该压缩方法后的字符串解压还原为原  字符串并输出

注意字母后方跟的数字不一定是一位的 

连续出现 2 次直接写即可(题目说连续出现次数小于 3 不压缩)

第一个a出现一次,输出一个a;b后面为5,输出5个5;a后面为10输出10个a;c后面为5,输出5个c

#include<stdio.h>

int main(void){
	int i=0,sum,count,k;
	char s[100];
	gets(s);
	while(s[i]){
		printf("%c",s[i]);
		i++;
		sum=0;
		count=0;
		while(s[i]>='0'&&s[i]<='9'){
			sum=sum*10+s[i]-'0';
			i++;
			count++;
		}
		for(k=0;k<sum-1;k++){
			printf("%c",s[i-count-1]);
		}
	}	 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值