1、求M的n次方最后三位
【问题描述】
正整数M 的N次方有可能是一个非常大的数字,我们只求该数字的最后三位
例1:比如输入5和3 ,5的3次方为125,则输出为125
例2:比如输入2和10 2的10次方为1024 ,则输出结果为24
例3:比如输入111和5 111的5次方为116850581551,则输出结果为551
#include <stdlib.h>
#include "oj.h"
unsigned int GetLastThreeNumOfResult (unsigned int m, unsigned int n)
{
int i = 0;
int result = 1;
for(i=0;i<n;i++) {
result = m*result%1000;
}
return result;
}
2、向升序单向链表中插入一个节点
需要注意一点就是第一个节点前插入节点。
#include "OJ.h"
struct ListNode {
int m_nKey;
ListNode* m_pNext;
};
/*
功能: 输入一个升序单向链表和一个链表节点,向单向链表中按升序插入这个节点。
输入为空指针的情况视为异常,另外不考虑节点值相等的情况。
输入: ListNode* pListHead 单向链表
ListNode* pInsertNode 新插入节点
输出: ListNode* pListHead 单向链表
返回: 正常插入节点返回链表头指针,其它异常返回空指针
*/
ListNode* InsertNodeToList(ListNode* pListHead, ListNode* pInsertNode)
{
if(!pListHead ||!pInsertNode)
return (ListNode*)NULL;
/*1.添加一个头结点,处理插入的节点是在第一个节点之前*/
ListNode* dummy = (ListNode*)malloc(sizeof(ListNode));
dummy->m_pNext = pListHead;
ListNode* p = pListHead;
ListNode* pre = dummy;
while(p){
if(p->m_nKey > pInsertNode->m_nKey){
break;
}
pre = p; /*保留前一个节点*/
p = p->m_pNext;
}
pInsertNode->m_pNext = p;
pre->m_pNext = pInsertNode;
pListHead = dummy->m_pNext;
free(dummy);
return pListHead;
}
3、删除链表中的重复节点、剩余节点逆序输出
解题思路:
- 1、将链表节点的数据放入一个数组中mydata
- 2、对这个mydata进行去重处理(本题最主要工作),剩余元素就是我们想要的数据。
- 3、申请节点地址,逆序输出
#include <stdlib.h>
#include "oj.h"
#include <vector>
using namespace std;
typedef struct strNode {
int data;
strNode * pstrNext;
}strNode;
/*
功能: 输入一个不带头节点的单向链表(链表的节点数小于100),
删除链表中内容重复的节点(重复的节点全部删除),剩余的节点逆序倒排。
输入: pstrIn: 输入一个不带头节点的单向链表
输出: pstrOut:删除内容重复的节点后,
逆序排列的链表(不带头节点,链表第一个节点的内存已经申请)。
返回:
示例:
输入链表的内容依次为 6,7,8,8,9,10,6
则输出链表的内容依次应该是 10,9,7
*/
void move(int *a,int index,int count)
{
int in=index;
/*覆盖原来的数据*/
for(int i=0;i<count-1;i++) {
a[in]=a[in+1];
in++;
}
}
int iChanProcess(strNode * pstrIn,strNode * pstrOut)
{
if(!pstrIn||!pstrOut)
return 0;
/*最大节点个数为100个*/
int mydata[100];
strNode *pstrIntemp = pstrIn;
int mydataLen = 0;
/*1.取出节点的数据*/
while(pstrIntemp) {
mydata[mydataLen] = pstrIntemp->data;
pstrIntemp = pstrIntemp->pstrNext;
mydataLen ++;
}
int i = 0,j = 0;
int temp = 0;
int moveFlag = 0;
/*2.除去相同元素*/
for(i=0;i<mydataLen;i++) {
temp = mydata[i];
for(j = i+1;j<mydataLen;j++) {
if(temp==mydata[j]) {
move(mydata,j,mydataLen-j);
moveFlag = 1;
mydataLen--;
}
}
if(moveFlag) {
move(mydata,i,mydataLen-i);
mydataLen--;
moveFlag = 0;
}
}
/*头结点地址已经申请*/
strNode *MypstrOut=pstrOut;
MypstrOut->data=mydata[mydataLen-1];
/*3.逆序输出,申请节点地址*/
for(int tep=mydataLen-2;tep>=0;tep--) {
strNode* padd = (strNode *)malloc(sizeof(strNode));
padd->data = mydata[tep];/*数据*/
MypstrOut->pstrNext = padd;
padd->pstrNext = NULL;
MypstrOut = MypstrOut->pstrNext;
}
return 0;
}
/* 释放链表 */
void vFreeChan(strNode * pstrChan)
{
strNode *p,*pstrd;
pstrd=pstrChan;
while(pstrd) {
p=pstrd->pstrNext; /*保存下一个节点*/
free(pstrd);
pstrd=p;
}
return;
}
4、二维数组的列排序
程序如下,不过时间复杂度比较高,可以使用更好的排序算法(快速排序)代替冒泡。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "oj.h"
// 功能:排列一个m行n列 大小的数组
// 输入: int * pArray 指向数组第一个元素的指针,m为行数, n为列数 ,请按第i列排列
// 输出:按第i列排序完成后的数组放到入参指定的地址中 (i的取值范围 1 - n)
// 返回:
void RangeArray(int * pArray,unsigned int m,
unsigned int n,unsigned int i)
{
i--;
if (pArray == NULL || m<=0 || n<=0 || i<0 || i>=n) {
return;
}
int j = 0,k = 0;
int i2 = 0;
int aa = 0,bb = 0;
int temp = 0;
int nIndex = 0;
/*前两个for目的是冒泡法排序,第三个for是列*/
for (j=0;j<m;j++) { /*行*/
for (k=j+1;k<m;k++) {
for (i2 = i; i2<n; i2++) { /*列*/
aa = *(pArray+j*n+i2); /*第j行第i2列数据*/
bb = *(pArray+k*n+i2); /*第j+1行第i2列数据*/
if (*(pArray+j*n+i2) > *(pArray+k*n+i2)) {
/*交换两行数据*/
for (nIndex=0;nIndex<n;nIndex++) {
temp = pArray[j*n + nIndex];
pArray[j*n + nIndex] = pArray[k*n + nIndex];
pArray[k*n + nIndex] = temp;
}
break;
/*两个数相等,需要比较下一列的数据*/
} else if (*(pArray+j*n+i2) == *(pArray+k*n+i2)) {
continue;
/*次序正确,无需变动*/
} else if(*(pArray+j*n+i2) < *(pArray+k*n+i2)) {
break;
}
}
}
}
}
5、取给定正整数的指定bit位开始的指定长度的数据
startbit-bitlen+1理解为bit位从右向左数的,比如11011,startbit为3、bitlen为3,该数为101,因此原数字需要先左移到startbit-bitlen+1 = 1,移动到101最低位。
/*
Description
取给定正整数的指定bit位开始的指定长度的数据。bit位从右向左从0开始计算。
Prototype
unsigned int GetBitsValue(unsigned int input, unsigned int startbit,unsigned int bitlen)
Input Param
input 输入的整数
startbit 需要获取的开始bit
bitlen 需要获取的bit长度
Output Param
无
Return Value
对应的bit取值
*/
unsigned int GetBitsValue(unsigned int input, unsigned int startbit,
unsigned int bitlen)
{
/*在这里实现功能*/
if(startbit>31||bitlen>32||(bitlen>startbit))
return -1;
if(bitlen==0)
return -1;
unsigned int i = 0;
input = input>>(startbit-bitlen+1);
int sum = 1;
int temp = 1;
for(i=1;i<bitlen;i++) {
temp = (temp<<1);
sum = sum + temp;
}
input = input∑
return input;
}
6、兔子产子
假定你有一雄一雌一对刚出生的兔子,它们在长到一个月大小时开始交配,在第二月结束时,雌兔子产下另一对兔子,过了一个月后它们也开始繁殖,如此这般持续下去。每只雌兔在开始繁殖时每月都产下一对兔子,假定没有兔子死亡,在一年后总共会有多少对兔子?
在一月底,最初的一对兔子交配,但是还只有1对兔子;在二月底,雌兔产下一对兔子,共有2对兔子;在三月底,最老的雌兔产下第二对兔子,共有3对兔子;在四月底,最老的雌兔产下第三对兔子,两个月前生的雌兔产下一对兔子,共有5对兔子;……如此这般计算下去,兔子对数分别是:1, 1, 2, 3, 5, 8, 13, 21, 34, 55,89, 144, …看出规律了吗?从第3个数目开始,每个数目都是前面两个数目之和。这就是著名的斐波那契(Fibonacci)数列。
#include <stdlib.h>
#include "oj.h"
// 功能:获取第nValue1个月出生多少对兔子
// 输入: nValue1为正整数
// 输出:无
// 返回:第nValue1个月出生多少对兔子
unsigned int GetBirthRabbitNum(unsigned int nValue1)
{
if(nValue1==0) {
return 0;
}
if(nValue1==1||nValue1==2) {
return 1;
}
int sum = 1;
int sumpre = 1;
int i = 0;
int result = 0;
for(i=3;i<=nValue1;i++) {
result = sum+sumpre;
sumpre = sum;
sum = result;
}
return result;
}
7、报文转换
/*
功能:
将给定的报文按规则转换成另一个报文后输出。
转换规则如下:
报文中如果出现0x7E,转义成为2个字节0x7D 0x5E,如果出现0x7D,转义成为2个字节0x7D 0x5D。最后在报文头尾各加上一个0x7E定界。
示例(每个字节以十六进制数表示)
给定原始报文:1D 2B 3C 4D 5E 7E 6F 7D 7E
转换后的报文:7E 1D 2B 3C 4D 5E 7D 5E 6F 7D 5D 7D 5E 7E
输入:
char* pInput: 给定的输入报文,内存空间由调用者申请和释放
int iLen: 给定报文的长度
输出:
char* pOutput:转换后的报文,内存空间由调用者申请和释放
返回:
int: 成功 0, 失败 -1
*/
本文处理是先在栈中申请一个足够大的数组,长度为10000,假设报文足够,本程序不适用。
int PktTrans(char* pInput, int iLen, char* pOutput)
{
if(pInput==NULL||*pInput=='\0'||
(iLen < 0) || (iLen >= 100)||pOutput==NULL) {
return -1;
}
if(iLen==0)
return 0;
char temp[10000];
int i=0,j=0;
for(i = 0;i<iLen;i++)
{
if(pInput[i]==0x7E) {
temp[j++]=0x7D;
temp[j++]=0x5E;
} else if(pInput[i]==0x7D) {
temp[j++]=0x7D;
temp[j++]=0x5D;
} else {
temp[j]=pInput[i];
j++;
}
}
temp[j]='\0';
pOutput[0]=0x7E;
for(int k=0;k<j;k++) {
pOutput[k+1]=temp[k];
}
pOutput[j+1]=0x7E;
pOutput[j+2]='\0';
return 0;
}
8、计算二进制数的0的个数
#include <stdio.h>
int bit_zero_cal(unsigned int n)
{
int count = 0;
while(n) {
if(!(n&1))
count ++;
n = n>>1;
}
printf("%d\n",count);
return count;
}
int main()
{
unsigned int n;
scanf("%d",&n);
bit_zero_cal(n);
getchar();
}
9、简单密码破解
/*
密码是我们生活中非常重要的东东,我们的那么一点不能说的秘密就全靠它了。
哇哈哈. 接下来渊子要在密码之上再加一套密码,虽然简单但也安全。
假设渊子原来一个BBS上的密码为zvbo9441987,为了方便记忆,
他通过一种算法把这个密码变换成YUANzhi1987,这个密码是他的名字和出生年份,怎么忘都忘不了,
而且可以明目张胆地放在显眼的地方而不被别人知道真正的密码。
他是这么变换的,大家都知道手机上的字母:
1--1, abc--2, def--3, ghi--4, jkl--5, mno--6,
pqrs--7, tuv--8 wxyz--9, 0--0,
就这么简单,渊子把密码中出现的小写字母都变成对应的数字,数字和其他的符号都不做变换,
声明:密码中没有空格,而密码中出现的大写字母则变成小写之后往后移一位,
如:X,先变成小写,再往后移一位,不就是y了嘛,简单吧。记住,z往后移是a哦。
*/
代码实现
#include <stdio.h>
#include <string.h>
void Decoding(char *inputCodestr)
{
if(!inputCodestr)
return;
int inputCodestrLen = strlen(inputCodestr);
int i = 0;
while(inputCodestr[i]!='\0') {
if(inputCodestr[i]>='A'&&inputCodestr[i]<='Y') {
inputCodestr[i]=inputCodestr[i]+'a'-'A'+1;
}
else if(inputCodestr[i]=='Z') {
inputCodestr[i]='a';
}
else if(inputCodestr[i]>='a'&&inputCodestr[i]<='c') {
inputCodestr[i]='2';
}
else if(inputCodestr[i]>='d'&&inputCodestr[i]<='f') {
inputCodestr[i]='3';
}
else if(inputCodestr[i]>='g'&&inputCodestr[i]<='i') {
inputCodestr[i]='4';
}
else if(inputCodestr[i]>='j'&&inputCodestr[i]<='l') {
inputCodestr[i]=='5';
}
else if(inputCodestr[i]>='m'&&inputCodestr[i]<='o') {
inputCodestr[i]='6';
}
else if(inputCodestr[i]>='p'&&inputCodestr[i]<='s') {
inputCodestr[i]='7';
}
else if (inputCodestr[i]>='t'&&inputCodestr[i]<='v') {
inputCodestr[i]='8';
}
else if(inputCodestr[i]>='w'&&inputCodestr[i]<='z') {
inputCodestr[i]='9';
}
else {
inputCodestr[i]=inputCodestr[i];
}
i++;
}
printf("%s\n",inputCodestr);
}
int main()
{
char inputCodestr[100];
gets(inputCodestr);
Decoding(inputCodestr);
return 0;
}
10、密码验证合格程序
/*
密码要求:
1.长度超过8位
2.包括大小写字母.数字.其它符号,以上四种至少三种
3.不能有相同长度超2的子串重复
说明:长度超过2的子串
输入:
一组或多组长度超过2的子符串。每组占一行
输出:
如果符合要求输出:OK,否则输出NG
每行输出对应一组输入的结果;
样例输入: 021Abc9000
021Abc9Abc1
021ABC9000
021$bc9000
样例输出: OK
NG
NG
OK
*/
本题难点在于如何实现多行输入:while(scanf(“%s”,inputstr)!=EOF)
代码实现
#include <stdio.h>
#include <string.h>
void judge(char inputstr[])
{
if(!inputstr) {
printf("NG");
return;
}
int i = 0,j = 0;
int inputstrLen = strlen(inputstr);
/*1.条件1---长度超过8位*/
if(inputstrLen<=8) {
printf("NG");
return;
}
int numCount = 0;
int LowercaseLettersCount = 0;
int CapitalLettersCount = 0;
int OtherCharactersCount = 0;
for (i=0;i<inputstrLen;i++) {
if(inputstr[i]>='0' && inputstr[i]<='9')
numCount ++;
else if(inputstr[i]>='a' && inputstr[i]<='z')
LowercaseLettersCount ++;
else if(inputstr[i]>='A' && inputstr[i]<='Z')
CapitalLettersCount ++;
else {
OtherCharactersCount ++;
}
}
/*2.条件2---至少三种字符*/
if(numCount==0) {
if(LowercaseLettersCount==0||CapitalLettersCount==0||OtherCharactersCount==0) {
printf("NG");
return;
}
} else if(LowercaseLettersCount==0) {
if(CapitalLettersCount==0||OtherCharactersCount==0) {
printf("NG");
return;
}
} else if(CapitalLettersCount==0) {
if(OtherCharactersCount==0) {
printf("NG");
return;
}
}
char inputStrtemp[2];
/*3.条件3---相同长度超2的子串重复*/
for (i=0;i<inputstrLen-1;i++) {
inputStrtemp[0] = inputstr[i];
inputStrtemp[1] = inputstr[i+1];
for(j=i+2;j<inputstrLen-1;j++) {
if(inputstr[j]==inputStrtemp[0]&&inputstr[j+1]==inputStrtemp[1]) {
printf("NG");
return;
}
}
}
printf("OK");
}
int main()
{
char inputstr[1024];
while(scanf("%s",inputstr)!=EOF) {
judge(inputstr);
}
return 0;
}