一个基本算法题暴露出来的C++基础不扎实
2013-06-01 23:56
441 查看
好久没有写算法了,写算法都手生了,这可不利于找工作呀,打算坚持每周看一下算法方面的相关知识。今天是第一次,所以就入门一下吧,看了一下鸡兔同笼的问题。问题如下:
问题描述
一个笼子里面关了鸡和兔子(鸡有2 只脚,兔子有4 只脚,没有例外)。已经知道了笼
子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物
输入数据
第1 行是测试数据的组数n,后面跟着n 行输入。每组测试数据占1 行,包括一个正整
数a (a < 32768)。
输出要求
n 行,每行输出对应一个输入。输出是两个正整数,第一个是最少的动物数,第二个是
最多的动物数,两个正整数用空格分开。如果没有满足要求的情况出现,则输出2 个0。
输入样例
2
3
20
输出样例
0 0
5 10
题很简单,所以很快就写出了代码,如下:
运行了一下,结果竟然有问题,输入20时,输出时0 10,第一个最小的动物数明显计算有误,然后仔细看了一下代码, 问题出在一下语句中:
其实逻辑很简单,最小的动物数应该时除以4,如果还剩2条腿,则在加一。理论上是没有问题的,但是上面的语句就是输出有误。然后改动如下就可以了
可以看出是由于运算符号的优先级引起的问题,然后又温了一下书:
在C/C++中,上面语句中涉及的运算符有 >> , + , & 和 ? : 四个,这四个的优先级从高到低依次为:
+, >>, & , ? :
这样,int cntMin= legCnt>>2 + legCnt&0x2 ? 1 :0;就被编译成一下运算顺序
int cntMin = ((legCnt>>(2+legCnt))&0x2)? 1 : 0;
所以才会得出20个腿算出的 最小可能动物数是 0。
其实问题很简单的, 但是反映出对于C++的运算优先顺序还是不够熟悉。以为自己做的不错,结果一个小问题,就能查出自己的基本功有问题呀。还是要多练习一下了。wiki中找到 C/C++的运算优先级列在如下:
问题描述
一个笼子里面关了鸡和兔子(鸡有2 只脚,兔子有4 只脚,没有例外)。已经知道了笼
子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物
输入数据
第1 行是测试数据的组数n,后面跟着n 行输入。每组测试数据占1 行,包括一个正整
数a (a < 32768)。
输出要求
n 行,每行输出对应一个输入。输出是两个正整数,第一个是最少的动物数,第二个是
最多的动物数,两个正整数用空格分开。如果没有满足要求的情况出现,则输出2 个0。
输入样例
2
3
20
输出样例
0 0
5 10
题很简单,所以很快就写出了代码,如下:
#include <iostream> int main(){ int cnt; std::cin>>cnt; for(int i=0;i<cnt;++i){ int legCnt = 0; std::cin>>legCnt; if(legCnt & 0x1){ std::cout <<0 <<" "<<0<<std::endl; }else{ int cntMin= legCnt>>2 + legCnt&0x2 ? 1 :0; int cntMax = legCnt>>1; std::cout << cntMin<<" " << cntMax<<std::endl; } } }
运行了一下,结果竟然有问题,输入20时,输出时0 10,第一个最小的动物数明显计算有误,然后仔细看了一下代码, 问题出在一下语句中:
int cntMin= legCnt>>2 + legCnt&0x2 ? 1 :0;
其实逻辑很简单,最小的动物数应该时除以4,如果还剩2条腿,则在加一。理论上是没有问题的,但是上面的语句就是输出有误。然后改动如下就可以了
int cntMin= (legCnt>>2) + ((legCnt&0x2) ? 1 :0);
可以看出是由于运算符号的优先级引起的问题,然后又温了一下书:
在C/C++中,上面语句中涉及的运算符有 >> , + , & 和 ? : 四个,这四个的优先级从高到低依次为:
+, >>, & , ? :
这样,int cntMin= legCnt>>2 + legCnt&0x2 ? 1 :0;就被编译成一下运算顺序
int cntMin = ((legCnt>>(2+legCnt))&0x2)? 1 : 0;
所以才会得出20个腿算出的 最小可能动物数是 0。
其实问题很简单的, 但是反映出对于C++的运算优先顺序还是不够熟悉。以为自己做的不错,结果一个小问题,就能查出自己的基本功有问题呀。还是要多练习一下了。wiki中找到 C/C++的运算优先级列在如下:
优先级 | 运算符 | 叙述 | 示例 | 重载性 | 结合性 |
---|---|---|---|---|---|
1 | :: | 作用域解析(C++专有) | Class::age = 2; | 否 | 由左至右 |
2 | ++ | 后缀递增 | i++ | ||
-- | 后缀递减 | i-- | |||
{} | 组合 | {i++;a*=i;} | |||
() | 函数调用或变量初始化 | c_tor(int x, int y) : _x(x), _y(y * 10) {} | |||
[] | 数组访问 | array[4] = 2; | |||
. | 以对象方式访问成员 | obj.age = 34; | 否 | ||
-> | 以指针方式访问成员 | ptr->age = 34; | |||
dynamic_cast | 运行时检查类型转换(C++专有) | Y& y = dynamic_cast<Y&>(x); | 否 | ||
static_cast | 未经检查的类型转换(C++专有) | Y& y = static_cast<Y&>(x); | 否 | ||
reinterpret_cast | 重定义类型转换(C++专有) | int const* p = reinterpret_cast<int const*>(0x1234); | 否 | ||
const_cast | 更改非常量属性(C++专有) | int* q = const_cast<int*>(p); | 否 | ||
typeid | 获取类型信息(C++专有) | std::type_info const& t = typeid(x); | 否 | ||
3 | ++ | 前缀递增 | ++i | 由右至左 | |
-- | 前缀递减 | --i | |||
+ | 一元正号 | int i = +1; | |||
- | 一元负号 | int i = -1; | |||
! not | 逻辑非!的备用拼写 | if (!done) … | |||
~ compl | 按位取反~的备用拼写 | flag1 = ~flag2; | |||
(type) | 强制类型转换 | int i = (int)floatNum; | |||
* | 取指针指向的值 | int data = *intPtr; | |||
& | 取变量的地址 | int *intPtr = &data; | |||
sizeof | 某某的大小 | size_t s = sizeof(int); | 否 | ||
new | 动态内存分配(C++专有) | long* pVar = new long; | |||
new[] | 动态数组内存分配(C++专有) | long* array = new long[20]; | |||
delete | 动态内存释放(C++专有) | delete pVar; | |||
delete[] | 动态数组内存释放(C++专有) | delete [] array; | |||
4 | .* | 成员对象选择(C++专有) | obj.*var = 24; | 否 | 由左至右 |
->* | 成员指针选择(C++专有) | ptr->*var = 24; | |||
5 | * | 乘法 | int i = 2 * 4; | ||
/ | 除法 | float f = 10.0 / 3.0; | |||
% | 模数(取余) | int rem = 4 % 3; | |||
6 | + | 加法 | int i = 2 + 3; | ||
- | 减法 | int i = 5 - 1; | |||
7 | << | 比特左移 | int flags = 33 << 1; | ||
>> | 比特右移 | int flags = 33 >> 1; | |||
8 | < | 小于关系 | if (i < 42) … | ||
<= | 小于等于关系 | if (i <= 42) ... | |||
> | 大于关系 | if (i > 42) … | |||
>= | 大于等于关系 | if (i >= 42) ... | |||
9 | == eq | 等于关系==的备用拼写 | if (i == 42) ... | ||
!= not_eq | 不等于关系!=的备用拼写 | if (i != 42) … | |||
10 | & bitand | 比特 AND&的备用拼写 | flag1 = flag2 & 42; | ||
11 | ^ xor | 比特 XOR(独占or)^的备用拼写 | flag1 = flag2 ^ 42; | ||
12 | | bitor | 比特 OR(包含or)|的备用拼写 | flag1 = flag2 | 42; | ||
13 | && and | 逻辑 AND&&的备用拼写 | if (conditionA && conditionB) … | ||
14 | || or | 逻辑 OR||的备用拼写 | if (conditionA || conditionB) ... | ||
15 | c?t:f | 三元条件运算 | int i = a > b ? a : b; | 否 | 由右至左 |
16 | = | 直接赋值 | int a = b; | ||
+= | 以和赋值 | a += 3; | |||
-= | 以差赋值 | b -= 4; | |||
*= | 以乘赋值 | a *= 5; | |||
/= | 以除赋值 | a /= 2; | |||
%= | 以取余数赋值 | a %= 3; | |||
<<= | 以比特左移赋值 | flags <<= 2; | |||
>>= | 以比特右移赋值 | flags >>= 2; | |||
&= and_eq | 以比特AND赋值&=的备用拼写 | flags &= new_flags; | |||
^= xor_eq | 以比特XOR赋值^=的备用拼写 | flags ^= new_flags; | |||
|= or_eq | 以比特OR赋值|=的备用拼写 | flags |= new_flags; | |||
17 | throw | 抛出异常 | throw EClass(“Message”); | 否 | |
18 | , | 逗号运算符 | for (i = 0, j = 0; i < 10; i++, j++) … | 由左至右 |
相关文章推荐
- C++ 有关string类的基本语法以及一个简单算法 理论加案例的形式
- 算法导论-第22章-基本的图算法:强连通分量(深度优先遍历基础上)C++实现
- 试编写一个算法,将两个有序线性表合成一个有序线性表...最好是在c++上可以直接运行出来的
- C++ 中关于一个线性时间算法(linear-time algorithm)
- 排序基础算法总结与c++实现
- C++——算法基础之排序——快速排序
- effective c++ Item 17: 在一个独立的语句中将 new 出来的对象存入智能指针
- 基础算法测试——生成一个1-10之间的随机整数组合
- 无向图相关算法基础(c++实现)
- C++单链表的基本算法
- java基础—JVM的垃圾算法有哪几种?CMS垃圾回收的基本流程?
- C/C++笔试题-主要考察C/C++语言基础概念、算法及编程
- !!!有奖竞猜!!!运行以下程序,会出现什么问题?为什么?(一个C++的基础题)
- C/C++:各种基本算法实现小结(二)—— 堆 栈
- C++基础知识(五)—— 基本输入输出
- C++语法基础--泛型算法(generic algorithm)--插入迭代器back_inserter(),front_insertor(),inserter()以及next()函数简介
- C++——算法基础之动态查找表2——平衡二叉树(插入)
- C++ 又一个字符串分割算法
- c++ 提高4 map容器 共性机制 使用时机 比较| STL算法 算法基础仿函数 谓词 函数适配器 遍历算法
- 算法基础-基本数据类型