您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息