OJ 系列之常规练习题(一)
2016-01-20 09:50
447 查看
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; }
相关文章推荐
- shell字符串操作详解
- 总结的7个shell字符串操作方法和实例分享
- C/C++位操作实例总结
- JavaScript中操作字符串小结
- 深入理解链表的各类操作详解
- C++位操作的常见用法小结
- linux shell 字符串操作(长度,查找,替换)详解
- PHP中一些可以替代正则表达式函数的字符串操作函数
- JavaScript中的字符串操作详解
- Python 字符串操作实现代码(截取/替换/查找/分割)
- C语言字符串操作总结大全(超详细)
- 所谓的两个字符串相等比较--校园招聘笔试题
- 【OJ日志】超级约瑟夫
- 【OJ日志】爬楼梯
- 【OJ日志】删除升序数组的重复数字
- 几个比较大的在线提交系统(Online Judge)
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- golang 位操作
- LeetCode-Rotate Array
- LeetCode-Sudoku Solver