c语言输出1位小数不进位,剑指offer(C语言)60-68

61 扑克牌中的顺子

题目:从扑克牌中随机抽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

{

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

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);

}

62 圆圈中最后剩下的数字

题目: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

{

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

{

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);

}

63 股票的最大利润

题目:假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?例如,一只股票某些时间节点的价格为{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

{

if(numbers[i-1]

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);

}

64 求1+2+…+n

题目:求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);

}

65 不用加减乘除做加法

题目:写一个函数,求两个整数之和,要求在函数体内不得使用加减乘除四则运算符号

思路:加法的过程主要分两步,第一步是不进位的把两个数按位相加,第二步是把进位加上去。在二进制里面,按位相加其实就是异或,都是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);

}

66 构建乘积数组(暂过)

题目:给定一个数组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].不能使用乘除法。

67 把字符串转换成整数

题目:写一个函数,实现把字符串转换成整数这个功能。

思路:不考虑任何边界条件,那就不断乘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

{

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);

}

68 树中两个节点的最低公共祖先

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值