题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2-10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以看成任意数字。
思路:抛开扑克牌,就是五个1-13的数字,判断是否连续。可以把大小王看成0.先把数字排序,可以采用C语言库中的快排。之后遍历数组,分别统计0的个数,和间距的大小。最后判断0个个数是不是比间距小就行了。当数组中两个数相等的时候可以直接返回失败。
注意:使用快排的时候还需要传汝一个函数指针,用来判定是从小到大排序还是从大到小排序。
#include
#include
#include
#define bool unsigned int
#define true 1
#define false -1
#define none 2
int compare(const void* arg1,const void* arg2)
{
return *(int*)arg1-*(int*)arg2;//从小到大排序
//return *(int*)arg2-*(int*)arg1;//从大到小排序
}
bool IsContinuous(int* numbers,int length)
{
int i = 0;
int numberOf0 = 0;
int numberOfUncontinuous = 0;
if(numbers==NULL || length<1)return false;
qsort(numbers,length,sizeof(int),compare);
for(i=0;i<length;i++)
{
if(numbers[i]==0)numberOf0++;
else if(i>0)
{
if(numbers[i-1]!=0 && numbers[i]==numbers[i-1])
return false;
if(numbers[i-1]!=0 && numbers[i]-numbers[i-1]!=1)
numberOfUncontinuous+=(numbers[i]-numbers[i-1]-1);
}
}
if(numberOf0<numberOfUncontinuous)
return false;
else
return true;
}
void main()
{
int numbers[] = {0,0,3,3,6};
int i;
bool status;
status = IsContinuous(numbers,sizeof(numbers)/sizeof(int));
printf("%d",status);
}
题目:0,1,…,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
思路:建立一个环形链表,建立一个指针指向头,每次循环m-1次,删除该指针指向的节点,然后再把链表接起来。最后当链表中只剩一个的时候把该节点的数值返回。
#include
#include
#include
#define bool unsigned int
#define true 1
#define false -1
#define none 2
typedef struct ListNode
{
int data;
struct ListNode* next;
}ListNode;
void ConnectListNodes(ListNode* node1,ListNode* node2)
{
node1->next = node2;
}
ListNode* CreateListNode(int data)
{
ListNode* newListNode = (ListNode*)malloc(sizeof(ListNode));
if(!newListNode)return NULL;
newListNode->data = data;
newListNode->next = NULL;
return newListNode;
}
int LastRemaining(unsigned int n,unsigned int m)
{
int i=0;
int data = 0;
ListNode* p = NULL;
ListNode* preNode = NULL;
ListNode** node = (ListNode**)malloc(sizeof(ListNode*)*n);
if(n<1 || m<1)return false;
for(i=0;i<n;i++)
{
node[i] = CreateListNode(i);
if(i>0)
ConnectListNodes(node[i-1],node[i]);
}
ConnectListNodes(node[n-1],node[0]);
p=node[0];
preNode = node[0];
while(p->next != p)
{
for(i=0;i<m-1;i++)
{
p = p->next;
}
while(preNode->next!=p)
preNode = preNode->next;
if(preNode!=p)
{
preNode->next = p->next;
free(p);
p = preNode->next;
}
}
data = p->data;
free(p);
free(node);
return data;
}
void main()
{
int data =LastRemaining(4000,997);//1027
printf("%d",data);
}
题目:假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?例如,一只股票某些时间节点的价格为{9,11,8,5,7,12,16,14}。如果我们能在价格为5的时候买入并在价格为16时卖出,则能收获的最大利润为11.
思路:因为是买卖一次,所以就是选一个最小的,然后在他后面选一个最大的卖出去。可以使用蛮力法,求出每个值与他后面的值的差值,时间复杂度为O(N2)。之后找出所有差值中的最大值
优化:可以使用动态规划的想法,从第二个数开始,假设在该数卖出,在前面最小的时候买入。每次更新最小值就可以了。
#include
#include
#include
#define bool unsigned int
#define true 1
#define false -1
#define none 2
int MaxDiff(int* numbers,unsigned int length)
{
int minCost;
int maxDiff;
int i;
if(numbers==NULL ||length<2)return 0;
minCost = numbers[0];
maxDiff = numbers[1]- numbers[0];
for(i=2;i<length;i++)
{
if(numbers[i-1]<minCost)
minCost = numbers[i-1];
if(numbers[i]-minCost>maxDiff)
maxDiff = numbers[i]-minCost;
}
return maxDiff;
}
void main()
{
int numbers[] = {9,11,8,5,7,12,16,14};
int maxDiff;
maxDiff = MaxDiff(numbers,sizeof(numbers)/sizeof(int));
printf("%d",maxDiff);
}
题目:求1+2+…+n,要求不能使用乘除法,for,while,if,else,switch,case等关键字以及条件判断语句(A?B:C)
思路:不能用乘法不能用循环,那就只能用递归了,递归有一个问题就是最后返回时必须需要判断一下是不是到0了。不能通过判断来停止递归,那可以写两个函数,其中一个函数是正常的递归函数,另外一个是返回的函数,然后用函数指针指向这两个函数。当n等于0时调用返回的函数。通过函数指针数组来决定调用哪个函数,只有0和1两个选择,把N进行两次取反就可以了return n+f!!n;当n>0时两次取反得到1,当n=0时就是0
#include
#include
#include
#define bool unsigned int
#define true 1
#define false -1
#define none 2
typedef unsigned int (*fun)(unsigned int);
unsigned int Solution_Teminator(unsigned int n)
{
return 0;
}
unsigned int Solution(unsigned int n)
{
fun f[2] = {Solution_Teminator,Solution};
return n+f[!!n](n-1);
}
void main()
{
int data = Solution(5);
printf("%d",data);
}
题目:写一个函数,求两个整数之和,要求在函数体内不得使用加减乘除四则运算符号
思路:加法的过程主要分两步,第一步是不进位的把两个数按位相加,第二步是把进位加上去。在二进制里面,按位相加其实就是异或,都是0都是1最后都是0.进位的数其实就是两个数做与运算然后左移一位,只有都是1的时候才会是1.然后把这两个数在做同样的运算,知道没有进位的数。
#include
#include
#include
#define bool unsigned int
#define true 1
#define false -1
#define none 2
int Add(int num1,int num2)
{
int sum;
int carry;
while(num2)
{
sum = num1^num2;
carry = (num1 & num2)<<1;
num1 = sum;
num2 = carry;
}
return num1;
}
void main()
{
int data = Add(5,6);
printf("%d",data);
}
题目:给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1].不能使用乘除法。
题目:写一个函数,实现把字符串转换成整数这个功能。
思路:不考虑任何边界条件,那就不断乘10加本身就好了
#include
#include
#include
#define bool unsigned int
#define true 1
#define false -1
#define none 2
int StringToInt(char* str)
{
int result = 0;
if(str==NULL)return false;
while(*str!='\0')
{
result = *str++ -'0'+result*10;
//str++;
}
return result;
}
void main()
{
char* str = "123";
int a = StringToInt(str);
printf("%d",a);
}
优化:实际上在输入字符串的过程中,会有很多非法输入,要对这些非法输入进行很好的判断。并且当错误输入时用一个标志位来标志一下。
1.输入NULL或者‘\0’
2.输入符号±
3.输入字符比0x7fff ffff还大或者比0x80000000还小
4.输入不在‘0’到‘9’范围内的数
#include
#define bool unsigned int
#define true 1
#define false -1
#define none 2
enum Status{kValid=0,kInvalid};
int states = kInvalid;
long long StrToIntCore(char* digit,int minus)
{
long long num = 0;
int flag = minus?-1:1;
while(*digit!='\0')
{
if(*digit>='0'&&*digit<='9')
{
num = num*10 + flag*(*digit-'0');
if((!minus && num>0x7fffffff) || (minus && num<(signed int)0x80000000))
{
num = 0;
break;
}
}
else
{
num = 0;
break;
}
digit++;
}
if(*digit == '\0')
states = kValid;
return num;
}
int StrToInt(char* str)
{
long long num = 0;
int minus = 0;
if(str == NULL || *str == '\0')return 0;
if(*str == '+')str++;
else if(*str == '-')
{
str++;
minus = 1;
}
num = StrToIntCore(str,minus);
return (int)num;
}
void main()
{
char str[] = "-123";
//int data = atoi("132");
int data = StrToInt(str);
printf("%d",data);
}