1.翻转单词序列
时间限制:1秒 空间限制:32768K 热度指数:197013
本题知识点: 字符串
题目描述
牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
解题思路:
- 第一步翻转句子中的所有字符,将“I am a student.”翻转后变为“.tneduts a ma I”
- 第二步就是翻转每个单词中的字符顺序,就可以得到“ students. a am I ”
class Solution {
public:
string ReverseSentence(string str) {
if("" == str)
return "";
int left = 0;
for(int i = 0;i < str.size(); ++i){
if(str[i]==' ' || i==str.size()-1){
if(i == str.size()-1)
i++;
reverse(str.begin() + left, str.begin() + i);
left = i + 1;
}
}
reverse(str.begin(),str.end());
return str;
}
};
2.扑克牌顺子
时间限制:1秒 空间限制:32768K 热度指数:113417
本题知识点: 字符串
题目描述
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。
解题思路:
- 首先将数组进行排序
- 然后统计数组中0的个数
- 最后统计排序之后的数组中相邻数字的空缺总数,如果空缺总数小于或者等于0的个数,那么这个数组就是连续的;否则就不是连续的
- 注意:如果数组中的非0数字重复出现,那么该数组一定不是连续的
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
int len = numbers.size();
if(len <= 0)
return false;
std::sort(numbers.begin(), numbers.end());
int countZero = 0;
int countGap = 0;
//统计数组中的0的个数
for(int i = 0; i < len && numbers[i] == 0; ++i)
++countZero;
//统计数组中空缺的个数
int small = countZero;
int big = small + 1;
while(big < len)
{
if(numbers[small] == numbers[big])
return false;
countGap += numbers[big] - numbers[small] - 1;
small = big;
++big;
}
return (countGap > countZero) ? false : true;
}
};
3.孩子们的游戏(圆圈中最后剩下的数)
时间限制:1秒 空间限制:32768K 热度指数:109768
本题知识点: 模拟
题目描述
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n < 1 || m < 1)
return -1;
int i = 0;
list<int> numbers;
for( ; i < n; ++i)
{
numbers.push_back(i);
}
list<int>::iterator current = numbers.begin();
while(numbers.size() > 1)
{
for(int i = 1; i < m; ++i)
{
current++;
if(current == numbers.end())
current = numbers.begin();
}
list<int>::iterator next = ++current;
if(next == numbers.end())
next = numbers.begin();
--current;
numbers.erase(current);
current = next;
}
return *(current);
}
};
4.求1+2+3+....+n
时间限制:1秒 空间限制:32768K 热度指数:112830
题目描述
求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
解题思路:
思路一:利用构造函数求解
- 围绕循环做文章,循环只是让相同的代码重复执行n次
- 我们可以定义一个类,然后创建n个该类型的实例,那么这个类型的构造函数将会被调用n次
class Temp{
public:
Temp(){
++N;
Sum += N;
}
static void Reset()
{
N = 0;
Sum = 0;
}
static int GetSum()
{
return Sum;
}
private:
static int N;
static int Sum;
};
int Temp::N=0;
int Temp::Sum=0;
class Solution {
public:
int Sum_Solution(int n) {
Temp::Reset();
Temp *a = new Temp[n];
delete[] a;
a = NULL;
return Temp::GetSum();
}
};
思路二:利用虚函数求解
- 围绕递归做文章,既然不能咋一个函数中判断是不是应该终止递归,那么可以定义两个函数
- 一个函数充当递归函数的角色,另一个函数处理终止递归的情况
- 可以用布尔变量,true(1)嗲用第一个函数,值为false(1)调用第二个函数
- 关键是要将数值变量转化成布尔值,!!n转换成true, !n转换成false;如果是0取反正好相反
- 用虚函数可以实现函数的选择,当n不为0时,嗲用函数B::Sum;当n为0,调用函数A::Sum
class A{
public:
virtual int sum_solution(int N){
return 0;
}
};
A* p[2];
class B:public A{
public:
virtual int sum_solution(int N){
return p[!!N]->sum_solution(N-1)+N;
}
};
class Solution {
public:
int Sum_Solution(int n) {
A a;
B b;
p[0]=&a;
p[1]=&b;
return p[!!n]->sum_solution(n);
}
};
思路三:利用公式n(n+1)/2
class Solution {
public:
int Sum_Solution(int n) {
return n*(n+1)/2;
}
};
5.不用加减乘除做加法
时间限制:1秒 空间限制:32768K 热度指数:70976
题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
解题思路:
- 以5和17相加为例,5的二进制位0101, 17的二进制为0001 0001.先试着把计算分成三步来计算
- 第一步,将各位依次相加但不计算进位,得到的结果是0001 0100(最后一位相加的结果是二进制的0000 0010,这一步不计进位)
- 第二步,记下进位,进位结果是0000 0010
- 第三步,将前面两步的结果进行相加,得到的结果就是0001 0110,转换成十进制正好是22
- 所以接下来就是想办法将上述步骤中的加法转换成位运算
- 第一步不考虑进位然后对每一位进行相加。1+0=1,0+1=1,0+0=0,1+1=0,可以看出这和异或运算一样
- 第二步产生进位, 对0+1,1+0,0+0的结果都不会产生进位,只有1+1会产生进位,可以看出这和按位与运算一样。先将两个数按位与,然后向左移动一位即为进位
- 第三步就是将前面两个步骤产生的结果进行相加,相加的过程仍然是重复前面的两步,直到不产生进位为止
class Solution {
public:
int Add(int num1, int num2)
{
/*
首先看十进制是如何做的: 5+7=12,三步走
第一步:相加各位的值,不算进位,得到2。
第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。
第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。
同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111 第一步:相加各位的值,不算进位,
得到010,二进制每位相加就相当于各位做异或操作,101^111。
第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。
第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。
继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果 */
int sum, carray;
do{
sum = num1 ^ num2;
carray = (num1&num2)<<1;
num1 = sum;
num2 = carray;
}while(num2 != 0);
return num1;
}
};
6.把字符串转换成整数
时间限制:1秒 空间限制:32768K 热度指数:121578本题知识点: 字符串
题目描述
将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
输入描述:
输入一个字符串,包括数字字母符号,可以为空
输出描述:
如果是合法的数值表达则返回该数字,否则返回0
示例1
输入
+2147483647 1a33
输出
2147483647 0
class Solution {
public:
enum Status {kValid = 0, kInvalid};
int g_nStatus = kValid;
long long StrToIntCore(const char* digit, bool minus){
long long num = 0;
while(*digit != '\0'){
if(*digit >= '0' && *digit <= '9'){
int flag = minus ? -1 : 1;
num = num * 10 + flag * (*digit - '0');
if((!minus && num > 0x7FFFFFFF) || (minus && num < (signed int)0x80000000)){
num = 0;
break;
}
digit++;
}
else{
num = 0;
break;
}
}
if(*digit == '\0'){
g_nStatus = kValid;
}
return num;
}
int StrToInt(string str) {
g_nStatus = kInvalid;
long long num = 0;
int length = str.length();
const char* cstr = str.c_str();
if(cstr != NULL && *cstr != '\0'){
bool minus = false;
if(*cstr == '+')
cstr++;
else if(*cstr == '-'){
cstr++;
minus = true;
}
if(*cstr != '\0'){
num = StrToIntCore(cstr, minus);
}
}
return (int)num;
}
};